From d3b8d0b676d4b7d1ff9ea101b6b0255d75020992 Mon Sep 17 00:00:00 2001 From: Paul Spencer Date: Sat, 26 Oct 2013 14:43:22 -0400 Subject: [PATCH] Add jsdoc plugin that maps @todo tags to @stability and @observable tags. This is a temporary measure until Plovr handles custom tags or is replaced in the build system. Add support for indicating API stability with inline documentation In preparation for documenting the stability of API features, this commit adds support for indicating API stability via a new jsdoc tag @stability. There is a small plugin for jsdoc that adds a new tag, @stabiility, with some ability to enforce specific level names. The templates and css have been updated to include the stability level in the generated documentation. (+1 squashed commit) Squashed commits: [d6bc03d] Add jsdoc plugin for documenting observable properties of a class. --- apidoc/conf.json | 8 +++++- apidoc/plugins/observable.js | 26 +++++++++++++++++ apidoc/plugins/stability.js | 20 ++++++++++++++ apidoc/plugins/todo.js | 28 +++++++++++++++++++ apidoc/template/tmpl/container.tmpl | 9 ++++++ apidoc/template/tmpl/members.tmpl | 2 ++ apidoc/template/tmpl/method.tmpl | 2 ++ apidoc/template/tmpl/observables.tmpl | 40 +++++++++++++++++++++++++++ apidoc/template/tmpl/stability.tmpl | 9 ++++++ resources/layout.css | 37 +++++++++++++++++++++++++ 10 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 apidoc/plugins/observable.js create mode 100644 apidoc/plugins/stability.js create mode 100644 apidoc/plugins/todo.js create mode 100644 apidoc/template/tmpl/observables.tmpl create mode 100644 apidoc/template/tmpl/stability.tmpl diff --git a/apidoc/conf.json b/apidoc/conf.json index 72bc7c9173..5c56857620 100644 --- a/apidoc/conf.json +++ b/apidoc/conf.json @@ -13,11 +13,17 @@ "plugins": [ "plugins/markdown", "apidoc/plugins/inheritdoc", - "apidoc/plugins/exports" + "apidoc/plugins/exports", + "apidoc/plugins/todo", + "apidoc/plugins/observable", + "apidoc/plugins/stability" ], "markdown": { "parser": "gfm" }, + "stability": { + "levels": ["deprecated","experimental","unstable","stable","frozen","locked"] + }, "templates": { "cleverLinks": false, "monospaceLinks": false, diff --git a/apidoc/plugins/observable.js b/apidoc/plugins/observable.js new file mode 100644 index 0000000000..14bf45a722 --- /dev/null +++ b/apidoc/plugins/observable.js @@ -0,0 +1,26 @@ +var util = require('util'); +exports.defineTags = function(dictionary) { + dictionary.defineTag('observable', { + mustHaveValue: true, + canHaveType: true, + canHaveName: true, + onTagged: function(doclet, tag) { + if (!doclet.observables) { + doclet.observables = []; + } + var description = tag.value.description; + var readonly = description.split(' ').shift() === 'readonly'; + if (readonly) { + description = description.split(' ').slice(1).join(' '); + } + doclet.observables.push({ + name: tag.value.name, + type: { + names: tag.value.type.names + }, + description: description, + readonly: readonly + }); + } + }); +}; diff --git a/apidoc/plugins/stability.js b/apidoc/plugins/stability.js new file mode 100644 index 0000000000..bd006cdbab --- /dev/null +++ b/apidoc/plugins/stability.js @@ -0,0 +1,20 @@ +var conf = env.conf.stability; +var defaultLevels = ["deprecated","experimental","unstable","stable","frozen","locked"]; +var levels = conf.levels || defaultLevels; +var util = require('util'); +exports.defineTags = function(dictionary) { + dictionary.defineTag('stability', { + mustHaveValue: true, + canHaveType: false, + canHaveName: true, + onTagged: function(doclet, tag) { + var level = tag.text; + if (levels.indexOf(level) >=0) { + doclet.stability = level; + } else { + var errorText = util.format('Invalid stability level (%s) in %s line %s', tag.text, doclet.meta.filename, doclet.meta.lineno); + require('jsdoc/util/error').handle( new Error(errorText) ); + } + } + }) +}; diff --git a/apidoc/plugins/todo.js b/apidoc/plugins/todo.js new file mode 100644 index 0000000000..1389daaa32 --- /dev/null +++ b/apidoc/plugins/todo.js @@ -0,0 +1,28 @@ +var util = require('util'); +exports.defineTags = function(dictionary) { + dictionary.defineTag('todo', { + mustHaveValue: true, + canHaveType: true, + canHaveName: true, + onTagged: function(doclet, tag) { + var parts = tag.text.split(' '); + if (parts[0] === 'stability') { + doclet.stability = parts.slice(1).join(' '); + } else if (parts[0] === 'observable') { + if (!doclet.observables) { + doclet.observables = []; + } + var readonly = parts.length > 3 && parts[3] === 'readonly'; + var description = (readonly ? parts.slice(4) : parts.slice(3)).join(' '); + doclet.observables.push({ + name: parts[2], + type: { + names: tag.value.type.names + }, + description: description, + readonly: readonly + }); + } + } + }); +}; diff --git a/apidoc/template/tmpl/container.tmpl b/apidoc/template/tmpl/container.tmpl index c546088e67..b10f51a72a 100644 --- a/apidoc/template/tmpl/container.tmpl +++ b/apidoc/template/tmpl/container.tmpl @@ -92,6 +92,15 @@ + +

Observable Properties

+
+ + + ">

+ +

diff --git a/apidoc/template/tmpl/method.tmpl b/apidoc/template/tmpl/method.tmpl index c448eb11fd..1bb11a2091 100644 --- a/apidoc/template/tmpl/method.tmpl +++ b/apidoc/template/tmpl/method.tmpl @@ -5,6 +5,8 @@ var self = this;

+ +

diff --git a/apidoc/template/tmpl/observables.tmpl b/apidoc/template/tmpl/observables.tmpl new file mode 100644 index 0000000000..b5b5fa68be --- /dev/null +++ b/apidoc/template/tmpl/observables.tmpl @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeGetSetEventDescription
+ + + + change:
diff --git a/apidoc/template/tmpl/stability.tmpl b/apidoc/template/tmpl/stability.tmpl new file mode 100644 index 0000000000..a261220574 --- /dev/null +++ b/apidoc/template/tmpl/stability.tmpl @@ -0,0 +1,9 @@ + +
Stability:
+ +
Stability: not documented
+ diff --git a/resources/layout.css b/resources/layout.css index d870e4a7c5..d9c6ae745f 100644 --- a/resources/layout.css +++ b/resources/layout.css @@ -27,3 +27,40 @@ body, h1, h2, h3, h4, p, li, td, th { padding: 5px; } +.stability { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + color: #333; + background-color: #fcfcfc; + border: 1px solid #ccc; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.stability-deprecated { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.stability-experimental { + color: #c09853; + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.stability-unstable { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.stability-stable, +.stability-locked, +.stability-locked, { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +}