diff --git a/config/jsdoc/api/conf.json b/config/jsdoc/api/conf.json index 0b5b66be93..5aa84df9eb 100644 --- a/config/jsdoc/api/conf.json +++ b/config/jsdoc/api/conf.json @@ -7,7 +7,7 @@ "allowUnknownTags": true }, "source": { - "includePattern": ".+\\.js(doc)?$", + "includePattern": ".+\\.js$", "excludePattern": "(^|\\/|\\\\)_", "include": [ "src/ol" @@ -15,8 +15,10 @@ }, "plugins": [ "plugins/markdown", - "config/jsdoc/api/plugins/normalize-exports", + "config/jsdoc/api/plugins/convert-types", + "config/jsdoc/api/plugins/normalize-longnames", "config/jsdoc/api/plugins/inline-options", + "config/jsdoc/api/plugins/inheritdoc", "config/jsdoc/api/plugins/events", "config/jsdoc/api/plugins/observable", "config/jsdoc/api/plugins/api" diff --git a/config/jsdoc/api/index.md b/config/jsdoc/api/index.md index 4817f900f6..0eb4a286c6 100644 --- a/config/jsdoc/api/index.md +++ b/config/jsdoc/api/index.md @@ -8,10 +8,10 @@

The view manages the visual parameters of the map view, like resolution or rotation.

[View](module-ol_View-View.html) with center, projection, resolution and rotation

Layers are lightweight containers that get their data from [sources](module-ol_source_Source-Source.html).

-[layer/Tile](module-ol_layer_Tile-TileLayer.html)
-[layer/Image](module-ol_layer_Image-ImageLayer.html)
-[layer/Vector](module-ol_layer_Vector-VectorLayer.html)
-[layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html) +[ol/layer/Tile](module-ol_layer_Tile-TileLayer.html)
+[ol/layer/Image](module-ol_layer_Image-ImageLayer.html)
+[ol/layer/Vector](module-ol_layer_Vector-VectorLayer.html)
+[ol/layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html) ControlsInteractionsSources and formats @@ -21,18 +21,18 @@ [Map default interactions](module-ol_interaction.html#~defaults)
Interactions for [vector features](module-ol_Feature-Feature.html) - + [All interactions](module-ol_interaction_Interaction-Interaction.html) -[Tile sources](module-ol_source_Tile-TileSource.html) for [layer/Tile](module-ol_layer_Tile-TileLayer.html) -
[Image sources](module-ol_source_Image-ImageSource.html) for [layer/Image](module-ol_layer_Image-ImageLayer.html) -
[Vector sources](module-ol_source_Vector-VectorSource.html) for [layer/Vector](module-ol_layer_Vector-VectorLayer.html) -
[Vector tile sources](module-ol_source_VectorTile-VectorTile.html) for [layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html) +[Tile sources](module-ol_source_Tile-TileSource.html) for [ol/layer/Tile](module-ol_layer_Tile-TileLayer.html) +
[Image sources](module-ol_source_Image-ImageSource.html) for [ol/layer/Image](module-ol_layer_Image-ImageLayer.html) +
[Vector sources](module-ol_source_Vector-VectorSource.html) for [ol/layer/Vector](module-ol_layer_Vector-VectorLayer.html) +
[Vector tile sources](module-ol_source_VectorTile-VectorTile.html) for [ol/layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)
[Formats](module-ol_format_Feature-FeatureFormat.html) for reading/writing vector data -
[format/WMSCapabilities](module-ol_format_WMSCapabilities-WMSCapabilities.html) +
[ol/format/WMSCapabilities](module-ol_format_WMSCapabilities-WMSCapabilities.html) ProjectionsObservable objectsOther components -

All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [proj.transform()](module-ol_proj.html#.transform) and [proj.transformExtent()](module-ol_proj.html#.transformExtent).

+

All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [ol/proj#transform()](module-ol_proj.html#.transform) and [ol/proj#transformExtent()](module-ol_proj.html#.transformExtent).

[ol/proj](module-ol_proj.html)

Changes to all [ol/Object](module-ol_Object-BaseObject.html)s can be observed by calling the [object.on('propertychange')](module-ol_Object-BaseObject.html#on) method. Listeners receive an [ol/Object~ObjectEvent](module-ol_Object-ObjectEvent.html) with information on the changed property and old value.

diff --git a/config/jsdoc/api/plugins/api.js b/config/jsdoc/api/plugins/api.js index eab6a0bf94..b283ab35b4 100644 --- a/config/jsdoc/api/plugins/api.js +++ b/config/jsdoc/api/plugins/api.js @@ -95,17 +95,18 @@ exports.handlers = { newDoclet: function(e) { const doclet = e.doclet; if (doclet.stability) { - modules[doclet.longname.split('~').shift()] = true; + modules[doclet.longname.split(/[~\.]/).shift()] = true; api.push(doclet); } - // Mark explicity defined namespaces - needed in parseComplete to keep - // namespaces that we need as containers for api items. - if (/.*\.jsdoc$/.test(doclet.meta.filename) && doclet.kind == 'namespace') { - doclet.namespace_ = true; - } if (doclet.kind == 'class') { - modules[doclet.longname.split('~').shift()] = true; - classes[doclet.longname] = doclet; + modules[doclet.longname.split(/[~\.]/).shift()] = true; + if (!(doclet.longname in classes)) { + classes[doclet.longname] = doclet; + } + } + if (doclet.name === doclet.longname && !doclet.memberof) { + // Make sure anonymous default exports are documented + doclet.setMemberof(doclet.longname); } }, @@ -113,7 +114,7 @@ exports.handlers = { const doclets = e.doclets; for (let i = doclets.length - 1; i >= 0; --i) { const doclet = doclets[i]; - if (doclet.stability || doclet.namespace_) { + if (doclet.stability) { if (doclet.kind == 'class') { includeAugments(doclet); } diff --git a/config/jsdoc/api/plugins/convert-types.js b/config/jsdoc/api/plugins/convert-types.js new file mode 100644 index 0000000000..effc1a4b3b --- /dev/null +++ b/config/jsdoc/api/plugins/convert-types.js @@ -0,0 +1,139 @@ +const path = require('path'); +const fs = require('fs'); + +const importRegEx = /(typeof )?import\("([^"]*)"\)\.([^ \.\|\}><,\)=\n]*)([ \.\|\}><,\)=\n])/g; +const typedefRegEx = /@typedef \{[^\}]*\} ([^ \r?\n?]*)/; + +const defaultExports = {}; +const fileNodes = {}; + +function getDefaultExportName(moduleId, parser) { + if (!defaultExports[moduleId]) { + if (!fileNodes[moduleId]) { + const classDeclarations = {}; + const absolutePath = path.join(process.cwd(), 'src', moduleId + '.js'); + const file = fs.readFileSync(absolutePath, 'UTF-8'); + const node = fileNodes[moduleId] = parser.astBuilder.build(file, absolutePath); + if (node.program && node.program.body) { + const nodes = node.program.body; + for (let i = 0, ii = nodes.length; i < ii; ++i) { + const node = nodes[i]; + if (node.type === 'ClassDeclaration') { + classDeclarations[node.id.name] = node; + } else if (node.type === 'ExportDefaultDeclaration') { + const classDeclaration = classDeclarations[node.declaration.name]; + if (classDeclaration) { + defaultExports[moduleId] = classDeclaration.id.name; + } + } + } + } + } + } + if (!defaultExports[moduleId]) { + defaultExports[moduleId] = ''; + } + return defaultExports[moduleId]; +} + +exports.astNodeVisitor = { + + visitNode: function(node, e, parser, currentSourceName) { + if (node.type === 'File') { + const modulePath = path.relative(path.join(process.cwd(), 'src'), currentSourceName).replace(/\.js$/, ''); + fileNodes[modulePath] = node; + const identifiers = {}; + if (node.program && node.program.body) { + const nodes = node.program.body; + for (let i = 0, ii = nodes.length; i < ii; ++i) { + let node = nodes[i]; + if (node.type === 'ExportNamedDeclaration' && node.declaration) { + node = node.declaration; + } + if (node.type === 'ImportDeclaration') { + node.specifiers.forEach(specifier => { + let defaultImport = false; + switch (specifier.type) { + case 'ImportDefaultSpecifier': + defaultImport = true; + // fallthrough + case 'ImportSpecifier': + identifiers[specifier.local.name] = { + defaultImport, + value: node.source.value + }; + break; + default: + } + }); + } else if (node.type === 'ClassDeclaration') { + if (node.id && node.id.name) { + identifiers[node.id.name] = { + value: path.basename(currentSourceName) + }; + } + + // Add class inheritance information because JSDoc does not honor + // the ES6 class's `extends` keyword + if (node.superClass && node.leadingComments) { + const leadingComment = node.leadingComments[node.leadingComments.length - 1]; + const lines = leadingComment.value.split(/\r?\n/); + lines.push(lines[lines.length - 1]); + const identifier = identifiers[node.superClass.name]; + if (identifier) { + const absolutePath = path.resolve(path.dirname(currentSourceName), identifier.value); + const moduleId = path.relative(path.join(process.cwd(), 'src'), absolutePath).replace(/\.js$/, ''); + const exportName = identifier.defaultImport ? getDefaultExportName(moduleId, parser) : node.superClass.name; + lines[lines.length - 2] = ' * @extends ' + `module:${moduleId}${exportName ? '~' + exportName : ''}`; + } else { + lines[lines.length - 2] = ' * @extends ' + node.superClass.name; + } + leadingComment.value = lines.join('\n'); + } + + } + } + } + if (node.comments) { + node.comments.forEach(comment => { + //TODO Handle typeof, to indicate that a constructor instead of an + // instance is needed. + comment.value = comment.value.replace(/typeof /g, ''); + + // Convert `import("path/to/module").export` to + // `module:path/to/module~Name` + let importMatch; + while ((importMatch = importRegEx.exec(comment.value))) { + importRegEx.lastIndex = 0; + const rel = path.resolve(path.dirname(currentSourceName), importMatch[2]); + const importModule = path.relative(path.join(process.cwd(), 'src'), rel).replace(/\.js$/, ''); + const exportName = importMatch[3] === 'default' ? getDefaultExportName(importModule, parser) : importMatch[3]; + const replacement = `module:${importModule}${exportName ? '~' + exportName : ''}`; + comment.value = comment.value.replace(importMatch[0], replacement + importMatch[4]); + } + + // Treat `@typedef`s like named exports + const typedefMatch = comment.value.replace(/\r?\n?\s*\*\s/g, ' ').match(typedefRegEx); + if (typedefMatch) { + identifiers[typedefMatch[1]] = { + value: path.basename(currentSourceName) + }; + } + + // Replace local types with the full `module:` path + Object.keys(identifiers).forEach(key => { + const regex = new RegExp(`(@fires |[\{<\|,] ?)${key}`, 'g'); + if (regex.test(comment.value)) { + const identifier = identifiers[key]; + const absolutePath = path.resolve(path.dirname(currentSourceName), identifier.value); + const moduleId = path.relative(path.join(process.cwd(), 'src'), absolutePath).replace(/\.js$/, ''); + const exportName = identifier.defaultImport ? getDefaultExportName(moduleId, parser) : key; + comment.value = comment.value.replace(regex, '$1' + `module:${moduleId}${exportName ? '~' + exportName : ''}`); + } + }); + }); + } + } + } + +}; diff --git a/config/jsdoc/api/plugins/events.js b/config/jsdoc/api/plugins/events.js index b1ffa9dfba..03761a9af0 100644 --- a/config/jsdoc/api/plugins/events.js +++ b/config/jsdoc/api/plugins/events.js @@ -12,7 +12,7 @@ exports.handlers = { events[cls] = []; } events[cls].push(doclet.longname); - } else if (doclet.kind == 'class') { + } else if (doclet.kind == 'class' && !(doclet.longname in classes)) { classes[doclet.longname] = doclet; } }, @@ -29,7 +29,7 @@ exports.handlers = { event = doclet.fires[j].replace('event:', ''); if (events[event]) { fires.push.apply(fires, events[event]); - } else { + } else if (doclet.fires[j] !== 'event:ObjectEvent') { fires.push(doclet.fires[j]); } } @@ -40,4 +40,3 @@ exports.handlers = { } }; - diff --git a/config/jsdoc/api/plugins/inheritdoc.js b/config/jsdoc/api/plugins/inheritdoc.js new file mode 100755 index 0000000000..e252269bcc --- /dev/null +++ b/config/jsdoc/api/plugins/inheritdoc.js @@ -0,0 +1,109 @@ +/* + * This is a hack to prevent inheritDoc tags from entirely removing + * documentation of the method that inherits the documentation. + * + * TODO: Remove this hack when https://github.com/jsdoc3/jsdoc/issues/53 + * is addressed. + */ + + +exports.defineTags = function(dictionary) { + dictionary.defineTag('inheritDoc', { + mustHaveValue: false, + canHaveType: false, + canHaveName: false, + onTagged: function(doclet, tag) { + doclet.inheritdoc = true; + } + }); +}; + + +const lookup = {}; +const incompleteByClass = {}; +const keepKeys = ['comment', 'meta', 'name', 'memberof', 'longname', 'augment', + 'stability']; + +exports.handlers = { + + newDoclet: function(e) { + const doclet = e.doclet; + let incompletes; + if (!(doclet.longname in lookup)) { + lookup[doclet.longname] = []; + } + lookup[doclet.longname].push(doclet); + if (doclet.inheritdoc) { + if (!(doclet.memberof in incompleteByClass)) { + incompleteByClass[doclet.memberof] = []; + } + incompletes = incompleteByClass[doclet.memberof]; + if (incompletes.indexOf(doclet.name) == -1) { + incompletes.push(doclet.name); + } + } + }, + + parseComplete: function(e) { + let ancestors, candidate, candidates, doclet, i, j, k, l, key; + let incompleteDoclet, stability, incomplete, incompletes; + const doclets = e.doclets; + for (i = doclets.length - 1; i >= 0; --i) { + doclet = doclets[i]; + if (doclet.augments) { + ancestors = [].concat(doclet.augments); + } + incompletes = incompleteByClass[doclet.longname]; + if (ancestors && incompletes) { + // collect ancestors from the whole hierarchy + for (j = 0; j < ancestors.length; ++j) { + candidates = lookup[ancestors[j]]; + if (candidates) { + for (k = candidates.length - 1; k >= 0; --k) { + candidate = candidates[k]; + if (candidate.augments) { + ancestors = ancestors.concat(candidate.augments); + } + } + } + } + // walk through all inheritDoc members + for (j = incompletes.length - 1; j >= 0; --j) { + incomplete = incompletes[j]; + candidates = lookup[doclet.longname + '#' + incomplete]; + if (candidates) { + // get the incomplete doclet that needs to be augmented + for (k = candidates.length - 1; k >= 0; --k) { + incompleteDoclet = candidates[k]; + if (incompleteDoclet.inheritdoc) { + break; + } + } + } + // find the documented ancestor + for (k = ancestors.length - 1; k >= 0; --k) { + candidates = lookup[ancestors[k] + '#' + incomplete]; + if (candidates) { + for (l = candidates.length - 1; l >= 0; --l) { + candidate = candidates[l]; + if (candidate && !candidate.inheritdoc) { + stability = candidate.stability || incompleteDoclet.stability; + if (stability) { + incompleteDoclet.stability = stability; + for (key in candidate) { + if (candidate.hasOwnProperty(key) && + keepKeys.indexOf(key) == -1) { + incompleteDoclet[key] = candidate[key]; + } + } + } + } + } + } + } + } + } + } + } + +}; diff --git a/config/jsdoc/api/plugins/normalize-exports.js b/config/jsdoc/api/plugins/normalize-exports.js deleted file mode 100644 index a24e767cd5..0000000000 --- a/config/jsdoc/api/plugins/normalize-exports.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @filedesc - * Expands module path type to point to default export when no name is given - */ - -const fs = require('fs'); -const path = require('path'); - -let moduleRoot; - -function addDefaultExportPath(obj) { - if (!Array.isArray(obj)) { - obj = obj.names; - } - obj.forEach((name, index) => { - const matches = name.match(/module\:([^>|),\.<]|)+/g); - if (matches) { - matches.forEach(module => { - if (!/[~\.]/.test(module)) { - const checkFile = path.resolve(moduleRoot, module.replace(/^module\:/, '')); - const file = fs.readFileSync(require.resolve(checkFile), 'utf-8'); - const lines = file.split('\n'); - let hasDefaultExport = false; - for (let i = 0, ii = lines.length; i < ii; ++i) { - hasDefaultExport = hasDefaultExport || /^export default [^\{]/.test(lines[i]); - const match = lines[i].match(/^export default ([A-Za-z_$][A-Za-z0-9_$]+);$/); - if (match) { - // Use variable name if default export is assigned to a variable. - obj[index] = name = name.replace(module, `${module}~${match[1]}`); - return; - } - } - if (hasDefaultExport) { - // Duplicate last part if default export is not assigned to a variable. - obj[index] = name = name.replace(module, `${module}~${module.split('/').pop()}`); - } - } - }); - } - }); -} - -function replaceLinks(comment) { - const matches = comment.match(/\{@link [^\} #]+}/g); - if (matches) { - const modules = matches.map(m => { - const mm = m.match(/(module:[^\}]+)}$/); - if (mm) { - return mm[1]; - } - }).filter(m => !!m); - const newModules = modules.concat(); - addDefaultExportPath(newModules); - modules.forEach((module, i) => { - comment = comment.replace(module, newModules[i]); - }); - } - return comment; -} - -exports.handlers = { - - /** - * Adds default export to module path types without name - * @param {Object} e Event object. - */ - newDoclet: function(e) { - const doclet = e.doclet; - if (doclet.kind == 'module') { - const levelsUp = doclet.longname.replace(/^module\:/, '').split('/'); - if (doclet.meta.filename != 'index.js') { - levelsUp.pop(); - } - const pathArgs = [doclet.meta.path].concat(levelsUp.map(() => '../')); - moduleRoot = path.resolve.apply(null, pathArgs); - } else { - if (doclet.description) { - doclet.description = replaceLinks(doclet.description); - } - if (doclet.classdesc) { - doclet.classdesc = replaceLinks(doclet.classdesc); - } - - const module = doclet.longname.split('#').shift(); - if (module.indexOf('module:') == 0 && module.indexOf('.') !== -1) { - doclet.longname = doclet.longname.replace(module, module.replace('.', '~')); - } - if (doclet.augments) { - addDefaultExportPath(doclet.augments); - } - if (doclet.params) { - doclet.params.forEach(p => addDefaultExportPath(p.type)); - } - if (doclet.returns) { - doclet.returns.forEach(r => addDefaultExportPath(r.type)); - } - if (doclet.properties) { - doclet.properties.forEach(p => addDefaultExportPath(p.type)); - } - if (doclet.type) { - addDefaultExportPath(doclet.type); - } - } - } - -}; diff --git a/config/jsdoc/api/plugins/normalize-longnames.js b/config/jsdoc/api/plugins/normalize-longnames.js new file mode 100644 index 0000000000..34bda84717 --- /dev/null +++ b/config/jsdoc/api/plugins/normalize-longnames.js @@ -0,0 +1,21 @@ +/** + * @filedesc + * Normalize module path to make no distinction between static and member at + * the module level. + */ + +exports.handlers = { + + /** + * Adds default export to module path types without name + * @param {Object} e Event object. + */ + newDoclet: function(e) { + const doclet = e.doclet; + const module = doclet.longname.split('#').shift(); + if (module.indexOf('module:') == 0 && module.indexOf('.') !== -1) { + doclet.longname = doclet.longname.replace(module, module.replace('.', '~')); + } + } + +}; diff --git a/config/jsdoc/api/plugins/observable.js b/config/jsdoc/api/plugins/observable.js index 44e7353c54..744be13123 100644 --- a/config/jsdoc/api/plugins/observable.js +++ b/config/jsdoc/api/plugins/observable.js @@ -5,7 +5,7 @@ exports.handlers = { newDoclet: function(e) { const doclet = e.doclet; - if (doclet.kind == 'class') { + if (doclet.kind == 'class' && !(doclet.longname in classes)) { classes[doclet.longname] = doclet; } }, diff --git a/config/jsdoc/api/plugins/typedefs.js b/config/jsdoc/api/plugins/typedefs.js deleted file mode 100644 index 66227c3c04..0000000000 --- a/config/jsdoc/api/plugins/typedefs.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Changes @enum annotations into @typedef. - */ - -// types that are undefined or typedefs containing undefined -let undefinedLikes = null; - -/** - * Changes the description of the param if it is required. - * @param {Object} doclet The doclet. - * @returns {Object} The modified doclet. - */ -function markRequiredIfNeeded(doclet) { - const memberof = doclet.memberof; - if (!memberof) { - return doclet; - } - - const types = doclet.type.names; - let isRequiredParam = true; - - // iterate over all types that are like-undefined (see above for explanation) - for (let idx = undefinedLikes.length - 1; idx >= 0; idx--) { - const undefinedLike = undefinedLikes[idx]; - // … if the current types contains a type that is undefined-like, - // it is not required. - if (types.indexOf(undefinedLike) != -1) { - isRequiredParam = false; - } - } - - if (isRequiredParam) { - const reqSnippet = 'Required.

'; - const endsWithP = /<\/p>$/i; - let description = doclet.description; - if (description && endsWithP.test(description)) { - description = description.replace(endsWithP, ' ' + reqSnippet); - } else if (doclet.description === undefined) { - description = '

' + reqSnippet; - } - doclet.description = description; - } - return doclet; -} - -/** - * Iterates over all doclets and finds the names of types that contain - * undefined. Stores the names in the global variable undefinedLikes, so - * that e.g. markRequiredIfNeeded can use these. - * @param {Array} doclets The doclets. - */ -function findTypesLikeUndefined(doclets) { - undefinedLikes = ['undefined']; // include type 'undefined' explicitly - for (let i = doclets.length - 1; i >= 0; --i) { - const doclet = doclets[i]; - if (doclet.kind === 'typedef') { - const types = doclet.type.names; - if (types.indexOf('undefined') !== -1) { - // the typedef contains 'undefined', so it self is undefinedLike. - undefinedLikes.push(doclet.longname); - } - } - } -} - -exports.handlers = { - - newDoclet: function(e) { - const doclet = e.doclet; - if (doclet.isEnum) { - // We never export enums, so we document them like typedefs - doclet.kind = 'typedef'; - delete doclet.isEnum; - } - }, - - parseComplete: function(e) { - const doclets = e.doclets; - findTypesLikeUndefined(doclets); - for (let i = doclets.length - 1; i >= 0; --i) { - markRequiredIfNeeded(doclets[i]); - } - } - -}; diff --git a/config/jsdoc/api/template/static/scripts/main.js b/config/jsdoc/api/template/static/scripts/main.js index acf43fde7b..a3419068d6 100644 --- a/config/jsdoc/api/template/static/scripts/main.js +++ b/config/jsdoc/api/template/static/scripts/main.js @@ -30,7 +30,11 @@ $(function () { }); // Show an item related a current documentation automatically - var filename = $('.page-title').data('filename').replace(/\.[a-z]+$/, ''); + var filename = $('.page-title').data('filename') + .replace(/\.[a-z]+$/, '') + .replace('module-', 'module:') + .replace(/_/g, '/') + .replace(/-/g, '~'); var $currentItem = $('.navigation .item[data-name*="' + filename + '"]:eq(0)'); if ($currentItem.length) { @@ -97,7 +101,8 @@ $(function () { var anchors = $('.anchor'); var _onHashChange = function () { var activeHash = window.document.location.hash - .replace(/\./g, '\\.'); // Escape dot in element id + .replace(/\./g, '\\.') // Escape dot in element id + .replace(/\~/g, '\\~'); // Escape tilde in element id anchors.removeClass('highlighted'); @@ -108,4 +113,9 @@ $(function () { $(window).on('hashchange', _onHashChange); _onHashChange(); + + // Make links that JSDoc forgot clickable + $('p').each(function(i, p) { + p.innerHTML = anchorme(p.innerHTML); + }); }); diff --git a/config/jsdoc/api/template/tmpl/layout.tmpl b/config/jsdoc/api/template/tmpl/layout.tmpl index fd99c511a7..74d383cd09 100644 --- a/config/jsdoc/api/template/tmpl/layout.tmpl +++ b/config/jsdoc/api/template/tmpl/layout.tmpl @@ -14,6 +14,7 @@ var version = obj.packageInfo.version; OpenLayers v<?js= version ?> API - <?js= title ?> + diff --git a/config/jsdoc/api/template/tmpl/members.tmpl b/config/jsdoc/api/template/tmpl/members.tmpl index 280556e3a5..243e1f22cd 100644 --- a/config/jsdoc/api/template/tmpl/members.tmpl +++ b/config/jsdoc/api/template/tmpl/members.tmpl @@ -14,7 +14,7 @@ if (data.type && data.type.names) {

- +

@@ -28,9 +28,9 @@ if (data.type && data.type.names) { - + - +
Example 1? 's':'' ?>
diff --git a/config/jsdoc/api/template/tmpl/navigation.tmpl b/config/jsdoc/api/template/tmpl/navigation.tmpl index f57d604640..cfa91d196a 100644 --- a/config/jsdoc/api/template/tmpl/navigation.tmpl +++ b/config/jsdoc/api/template/tmpl/navigation.tmpl @@ -1,5 +1,8 @@