From 5df4fd432d7c1935d68dfd15db4fee5d2131d027 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Tue, 22 Jan 2013 20:34:41 -0800 Subject: [PATCH] update the default template to generate pretty-printed source files (#208) enabled by default. to disable pretty-printed source files, add the property templates.default.outputSourceFiles: false to your conf.json file. --- LICENSE.md | 25 ++- conf.json.EXAMPLE | 5 +- lib/jsdoc/path.js | 65 ++++++ package.json | 2 +- plugins/prettyPrintSource.js | 83 ------- templates/default/publish.js | 96 ++++++++- .../default/static/styles/jsdoc-default.css | 5 + .../static/styles/prettify-tomorrow.css | 132 ++++++++++++ templates/default/tmpl/container.tmpl | 2 + templates/default/tmpl/details.tmpl | 4 +- templates/default/tmpl/layout.tmpl | 2 +- templates/default/tmpl/source.tmpl | 8 + templates/prettyPrintSource/publish.js | 58 ----- .../scripts/prettify/Apache-License-2.0.txt | 202 ------------------ .../static/scripts/prettify/prettify.js | 28 --- .../static/styles/desert.css | 34 --- .../static/styles/prettify.css | 52 ----- .../static/styles/sunburst.css | 51 ----- templates/prettyPrintSource/tmpl/layout.tmpl | 25 --- test/specs/jsdoc/path.js | 86 ++++++++ 20 files changed, 424 insertions(+), 541 deletions(-) create mode 100644 lib/jsdoc/path.js delete mode 100644 plugins/prettyPrintSource.js create mode 100644 templates/default/static/styles/prettify-tomorrow.css create mode 100644 templates/default/tmpl/source.tmpl delete mode 100644 templates/prettyPrintSource/publish.js delete mode 100644 templates/prettyPrintSource/static/scripts/prettify/Apache-License-2.0.txt delete mode 100644 templates/prettyPrintSource/static/scripts/prettify/prettify.js delete mode 100644 templates/prettyPrintSource/static/styles/desert.css delete mode 100644 templates/prettyPrintSource/static/styles/prettify.css delete mode 100644 templates/prettyPrintSource/static/styles/sunburst.css delete mode 100644 templates/prettyPrintSource/tmpl/layout.tmpl create mode 100644 test/specs/jsdoc/path.js diff --git a/LICENSE.md b/LICENSE.md index 1908712e..5bc540c9 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -115,6 +115,17 @@ The source code for github-flavored-markdown is available at: https://github.com/hegemonic/github-flavored-markdown +## Google Code Prettify ## + +Google Code Prettify is distributed under the Apache License 2.0, which is +included with this package. + +Copyright (c) 2006 Google Inc. + +The source code for Google Code Prettify is available at: +https://code.google.com/p/google-code-prettify/ + + ## Jasmine ## Jasmine is distributed under the MIT license, which is reproduced above. @@ -139,7 +150,7 @@ https://github.com/mhevery/jasmine-node js2xmlparser is distributed under the MIT license, which is reproduced above. -Copyright (C) 2012 Michael Kourlas. +Copyright (c) 2012 Michael Kourlas. The source code for js2xmlparser is available at: https://github.com/michaelkourlas/node-js2xmlparser @@ -249,6 +260,18 @@ The source code for TaffyDB is available at: https://github.com/hegemonic/taffydb +## Tomorrow Theme for Google Code Prettify ## + +License information for the Tomorrow Theme for Google Code Prettify is not +available. It is assumed that the package is distributed under an open source +license that is compatible with the Apache License 2.0. + +Copyright (c) Yoshihide Jimbo. + +The source code for the Tomorrow Theme is available at: +https://github.com/jmblog/color-themes-for-google-code-prettify + + ## Rhino ## Rhino is distributed under the following licenses: diff --git a/conf.json.EXAMPLE b/conf.json.EXAMPLE index d390703e..deb458d0 100644 --- a/conf.json.EXAMPLE +++ b/conf.json.EXAMPLE @@ -9,7 +9,10 @@ "plugins": [], "templates": { "cleverLinks": false, - "monospaceLinks": false + "monospaceLinks": false, + "default": { + "outputSourceFiles": true + } }, "jsVersion": 180 } \ No newline at end of file diff --git a/lib/jsdoc/path.js b/lib/jsdoc/path.js new file mode 100644 index 00000000..3f036632 --- /dev/null +++ b/lib/jsdoc/path.js @@ -0,0 +1,65 @@ +/** + * Extended version of the standard `path` module. + * @module jsdoc/path + */ + +var path = require('path'); + + +function prefixReducer(previousPath, current) { + var currentPath = []; + + // if previousPath is defined, but has zero length, there's no common prefix; move along + if (previousPath && !previousPath.length) { + return currentPath; + } + + currentPath = path.resolve( process.cwd(), path.dirname(current) ).split(path.sep); + + if (previousPath) { + // remove chunks that exceed the previous path's length + currentPath = currentPath.slice(0, previousPath.length); + + // if a chunk doesn't match the previous path, remove everything from that chunk on + for (var i = 0, l = currentPath.length; i < l; i++) { + if (currentPath[i] !== previousPath[i]) { + currentPath.splice(i, currentPath.length - i); + break; + } + } + } + + return currentPath; +} + +/** + * Find the common prefix for an array of paths. If there is a common prefix, a trailing separator + * is appended to the prefix. Relative paths are resolved relative to the current working directory. + * + * For example, assuming that the current working directory is `/Users/jsdoc`: + * + * + For paths `foo/bar/baz/qux.js`, `foo/bar/baz/quux.js`, and `foo/bar/baz.js`, the common prefix + * is `/Users/jsdoc/foo/bar/`. + * + For paths `../jsdoc/foo/bar/baz/qux/quux/test.js`, `/Users/jsdoc/foo/bar/bazzy.js`, and + * `../../Users/jsdoc/foo/bar/foobar.js`, the common prefix is `/Users/jsdoc/foo/bar/`. + * + For paths `foo/bar/baz/qux.js` and `../../Library/foo/bar/baz.js`, there is no common prefix, + * and an empty string is returned. + * + * @param {Array.} paths - The paths to search for a common prefix. + * @return {string} The common prefix, or an empty string if there is no common prefix. + */ +exports.commonPrefix = function(paths) { + var common = paths.reduce(prefixReducer, undefined); + + // if there's anything left (other than a placeholder for a leading slash), add a placeholder + // for a trailing slash + if ( common.length && (common.length > 1 || common[0] !== '') ) { + common.push(''); + } + + return common.join(path.sep); +}; + +Object.keys(path).forEach(function(member) { + exports[member] = path[member]; +}); diff --git a/package.json b/package.json index 350bc60e..86ed008b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jsdoc", "version": "3.1.0-dev", - "revision": "1358265302670", + "revision": "1358915320017", "description": "An API documentation generator for JavaScript.", "keywords": [ "documentation", "javascript" ], "licenses": [ diff --git a/plugins/prettyPrintSource.js b/plugins/prettyPrintSource.js deleted file mode 100644 index cd99597f..00000000 --- a/plugins/prettyPrintSource.js +++ /dev/null @@ -1,83 +0,0 @@ -/*global env: true */ -/** - * @file Adds pretty printed source code to - * the output files. - * @author Matthew Christopher Kastor-Inare III - * Hial Atropa!! - * @version 20121017 - */ - -exports.handlers = { - beforeParse: function(e) { - - function backslashToForwardslash(text) { - return text.replace(/\\/g, '/'); - } - - function toRelativePath(text) { - text = backslashToForwardslash(text); - return text.replace(/^.*:/, ''); - } - - function slashesCollapseToDots(text) { - return text.replace(/[\/\\]+/g, '.'); - } - - function suffixFsCollapse(text) { - return text.replace(/\/+$/, '/'); - } - - function noDotPrefix(text) { - return text.replace(/^\.+/, ''); - } - - function noDotSuffix(text) { - return text.replace(/\.+$/, ''); - } - - function trimDots(text) { - text = noDotPrefix(text); - return noDotSuffix(text); - } - - function relativePathToNamespace (text) { - text = slashesCollapseToDots(text); - return trimDots(text); - } - - function makeOutputFileName(sourceFileName, extension) { - extension = extension || ''; - - sourceFileName = toRelativePath(sourceFileName); - sourceFileName = relativePathToNamespace(sourceFileName); - sourceFileName = sourceFileName += extension; - return sourceFileName; - } - - function getOutputDirectory() { - var path = require('path'); - var out; - - out = path.resolve(env.opts.destination); - out = backslashToForwardslash(out); - return suffixFsCollapse(out + '/'); - } - - function generateHighlightedSourceFile(outputDirectory, outputFileName, sourceCode) { - var prettyPrinter = require('templates/prettyPrintSource/publish'); - prettyPrinter.publish(outputDirectory, outputFileName, sourceCode); - } - - function main() { - var outputDirectory = getOutputDirectory(); - var outputFileName = makeOutputFileName(e.filename); - var sourceCode = e.source; - - // write source to file with a unique name - generateHighlightedSourceFile(outputDirectory, outputFileName, sourceCode); - // link to source in documentation somehow - } - - main(); - } -}; \ No newline at end of file diff --git a/templates/default/publish.js b/templates/default/publish.js index 71b7ceab..3f8629b8 100644 --- a/templates/default/publish.js +++ b/templates/default/publish.js @@ -1,8 +1,9 @@ /*global env: true */ var template = require('jsdoc/template'), fs = require('jsdoc/fs'), - path = require('path'), + path = require('jsdoc/path'), taffy = require('taffydb').taffy, + handle = require('jsdoc/util/error').handle, helper = require('jsdoc/util/templateHelper'), htmlsafe = helper.htmlsafe, linkto = helper.linkto, @@ -57,8 +58,38 @@ function addAttribs(f) { f.attribs = ''+htmlsafe(attribs.length? '<'+attribs.join(', ')+'> ' : '')+''; } + +function shortenPaths(files, commonPrefix) { + // always use forward slashes + var regexp = new RegExp('\\\\', 'g'); + + Object.keys(files).forEach(function(file) { + files[file].shortened = files[file].resolved.replace(commonPrefix, '') + .replace(regexp, '/'); + }); + + return files; +} + +function resolveSourcePath(filepath) { + return path.resolve(process.cwd(), filepath); +} + +function getPathFromDoclet(doclet) { + if (!doclet.meta) { + return; + } + + var filepath = doclet.meta.path && doclet.meta.path !== 'null' ? + doclet.meta.path + '/' + doclet.meta.filename : + doclet.meta.filename; + + return filepath; +} -function generate(title, docs, filename) { +function generate(title, docs, filename, resolveLinks) { + resolveLinks = resolveLinks === false ? false : true; + var docData = { title: title, docs: docs @@ -67,11 +98,35 @@ function generate(title, docs, filename) { var outpath = path.join(outdir, filename), html = view.render('container.tmpl', docData); - html = helper.resolveLinks(html); // turn {@link foo} into foo + if (resolveLinks) { + html = helper.resolveLinks(html); // turn {@link foo} into foo + } fs.writeFileSync(outpath, html, 'utf8'); } +function generateSourceFiles(sourceFiles) { + Object.keys(sourceFiles).forEach(function(file) { + var source; + // links are keyed to the shortened path in each doclet's `meta.filename` property + var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); + helper.registerLink(sourceFiles[file].shortened, sourceOutfile); + + try { + source = { + kind: 'source', + code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, 'utf8') ) + }; + } + catch(e) { + handle(e); + } + + generate('Source: ' + sourceFiles[file].shortened, [source], sourceOutfile, + false); + }); +} + /** * Create the navigation sidebar. * @param {object} members The members that will be used to create the sidebar. @@ -204,6 +259,9 @@ function buildNav(members) { exports.publish = function(taffyData, opts, tutorials) { data = taffyData; + var conf = env.conf.templates || {}; + conf['default'] = conf['default'] || {}; + var templatePath = opts.template; view = new template.Template(templatePath + '/tmpl'); @@ -224,6 +282,8 @@ exports.publish = function(taffyData, opts, tutorials) { data = helper.prune(data); data.sort('longname, version, since'); + var sourceFiles = {}; + var sourceFilePaths = []; data().each(function(doclet) { doclet.attribs = ''; @@ -247,6 +307,19 @@ exports.publish = function(taffyData, opts, tutorials) { doclet.see[i] = hashToLink(doclet, seeItem); }); } + + // build a list of source files + var sourcePath; + var resolvedSourcePath; + if (doclet.meta) { + sourcePath = getPathFromDoclet(doclet); + resolvedSourcePath = resolveSourcePath(sourcePath); + sourceFiles[sourcePath] = { + resolved: resolvedSourcePath, + shortened: null + }; + sourceFilePaths.push(resolvedSourcePath); + } }); // update outdir if necessary, then create outdir @@ -266,9 +339,20 @@ exports.publish = function(taffyData, opts, tutorials) { fs.copyFileSync(fileName, toDir); }); + sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) ); data().each(function(doclet) { var url = helper.createLink(doclet); helper.registerLink(doclet.longname, url); + + // replace the filename with a shortened version of the full path + var docletPath; + if (doclet.meta) { + docletPath = getPathFromDoclet(doclet); + docletPath = sourceFiles[docletPath].shortened; + if (docletPath) { + doclet.meta.filename = docletPath; + } + } }); data().each(function(doclet) { @@ -316,6 +400,12 @@ exports.publish = function(taffyData, opts, tutorials) { // once for all view.nav = buildNav(members); + // only output pretty-printed source files if requested; do this before generating any other + // pages, so the other pages can link to the source files + if (conf['default'].outputSourceFiles) { + generateSourceFiles(sourceFiles); + } + if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); } // index page displays information from package.json and lists files diff --git a/templates/default/static/styles/jsdoc-default.css b/templates/default/static/styles/jsdoc-default.css index 620e40af..ea49f607 100644 --- a/templates/default/static/styles/jsdoc-default.css +++ b/templates/default/static/styles/jsdoc-default.css @@ -220,6 +220,11 @@ h6 { border: 1px solid #ddd; width: 80%; + overflow: auto; +} + +.prettyprint.source { + width: inherit; } .prettyprint code diff --git a/templates/default/static/styles/prettify-tomorrow.css b/templates/default/static/styles/prettify-tomorrow.css new file mode 100644 index 00000000..aa2908c2 --- /dev/null +++ b/templates/default/static/styles/prettify-tomorrow.css @@ -0,0 +1,132 @@ +/* Tomorrow Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* Pretty printing styles. Used with prettify.js. */ +/* SPAN elements with the classes below are added by prettyprint. */ +/* plain text */ +.pln { + color: #4d4d4c; } + +@media screen { + /* string content */ + .str { + color: #718c00; } + + /* a keyword */ + .kwd { + color: #8959a8; } + + /* a comment */ + .com { + color: #8e908c; } + + /* a type name */ + .typ { + color: #4271ae; } + + /* a literal value */ + .lit { + color: #f5871f; } + + /* punctuation */ + .pun { + color: #4d4d4c; } + + /* lisp open bracket */ + .opn { + color: #4d4d4c; } + + /* lisp close bracket */ + .clo { + color: #4d4d4c; } + + /* a markup tag name */ + .tag { + color: #c82829; } + + /* a markup attribute name */ + .atn { + color: #f5871f; } + + /* a markup attribute value */ + .atv { + color: #3e999f; } + + /* a declaration */ + .dec { + color: #f5871f; } + + /* a variable name */ + .var { + color: #c82829; } + + /* a function name */ + .fun { + color: #4271ae; } } +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { + color: #060; } + + .kwd { + color: #006; + font-weight: bold; } + + .com { + color: #600; + font-style: italic; } + + .typ { + color: #404; + font-weight: bold; } + + .lit { + color: #044; } + + .pun, .opn, .clo { + color: #440; } + + .tag { + color: #006; + font-weight: bold; } + + .atn { + color: #404; } + + .atv { + color: #060; } } +/* Style */ +/* +pre.prettyprint { + background: white; + font-family: Menlo, Monaco, Consolas, monospace; + font-size: 12px; + line-height: 1.5; + border: 1px solid #ccc; + padding: 10px; } +*/ + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; } + +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + /* */ } + +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + /* */ } diff --git a/templates/default/tmpl/container.tmpl b/templates/default/tmpl/container.tmpl index 35b2664c..2760fc3c 100644 --- a/templates/default/tmpl/container.tmpl +++ b/templates/default/tmpl/container.tmpl @@ -5,6 +5,8 @@ + +
diff --git a/templates/default/tmpl/details.tmpl b/templates/default/tmpl/details.tmpl index 35d9556d..3c6eefa4 100644 --- a/templates/default/tmpl/details.tmpl +++ b/templates/default/tmpl/details.tmpl @@ -64,7 +64,9 @@ var self = this;
Source:
-
  • , line
+
  • + , line +
diff --git a/templates/default/tmpl/layout.tmpl b/templates/default/tmpl/layout.tmpl index e5202cfa..4f167411 100644 --- a/templates/default/tmpl/layout.tmpl +++ b/templates/default/tmpl/layout.tmpl @@ -9,7 +9,7 @@ - + diff --git a/templates/default/tmpl/source.tmpl b/templates/default/tmpl/source.tmpl new file mode 100644 index 00000000..e1092ef2 --- /dev/null +++ b/templates/default/tmpl/source.tmpl @@ -0,0 +1,8 @@ + +
+
+
+
+
\ No newline at end of file diff --git a/templates/prettyPrintSource/publish.js b/templates/prettyPrintSource/publish.js deleted file mode 100644 index eafcf400..00000000 --- a/templates/prettyPrintSource/publish.js +++ /dev/null @@ -1,58 +0,0 @@ -/*global env: true */ -/** - * Turn the data about your docs into file output. - * @param {TAFFY} data A TaffyDB collection representing - * all the symbols documented in your code. - * @param {object} opts An object with options information. - * @param {Tutorial} tutorialResolverRoot An object with information about included tutorials - * @see http://www.taffydb.com/ - * @see http://www.taffydb.com/workingwithdata - * @see http://underscorejs.org/#template - * @see http://nodejs.org/api/fs.html - * @see http://nodejs.org/api/path.html - */ -exports.publish = function(outputDirectory, outputFileName, sourceCode) { - - var fs = require('jsdoc/fs'); - var path = require('path'); - var helper = require('jsdoc/util/templateHelper'); - var template = require('jsdoc/template'); - - outputDirectory = path.resolve(outputDirectory); - - var staticFilesDirectory = path.resolve(__dirname + '/templates/prettyPrintSource/static'); - var outputFile = path.join(outputDirectory, outputFileName + '.html'); - var templateName = 'layout.tmpl'; - var templatePath = path.resolve(__dirname + '/templates/prettyPrintSource'); - var temmplateFilesDirectory= path.join(templatePath, '/tmpl'); - var templateData = {}; - - templateData.title = 'Source of : ' + outputFileName; - templateData.sourceCode = helper.htmlsafe(sourceCode); - - var view = new template.Template(temmplateFilesDirectory); - var outputContent = view.render(templateName, templateData); - - /* - console.log('templateData : ' + templateData); - console.log('outputDirectory : ' + outputDirectory); - console.log('outputFile : ' + outputFile); - console.log('outputContent : ' + outputContent); - */ - fs.mkPath(outputDirectory); - fs.writeFileSync(outputFile, outputContent, 'utf8'); - - // copy static files to outdir - var fromDir = path.join(templatePath, '/static'); - var staticFiles = fs.ls(fromDir, 3); - - staticFiles.forEach(function(fileName) { - var toDir = fs.toDir(fileName.replace(fromDir, outputDirectory)); - fs.mkPath(toDir); - if(!fs.existsSync(path.join(toDir, '/' + fileName))) { - fs.copyFileSync(fileName, toDir); - } - }); - - -}; diff --git a/templates/prettyPrintSource/static/scripts/prettify/Apache-License-2.0.txt b/templates/prettyPrintSource/static/scripts/prettify/Apache-License-2.0.txt deleted file mode 100644 index d6456956..00000000 --- a/templates/prettyPrintSource/static/scripts/prettify/Apache-License-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/templates/prettyPrintSource/static/scripts/prettify/prettify.js b/templates/prettyPrintSource/static/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7e..00000000 --- a/templates/prettyPrintSource/static/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p - - - <?js= title ?> - - - - - - - - -
-
-      
- - - \ No newline at end of file diff --git a/test/specs/jsdoc/path.js b/test/specs/jsdoc/path.js new file mode 100644 index 00000000..838337e7 --- /dev/null +++ b/test/specs/jsdoc/path.js @@ -0,0 +1,86 @@ +/*global beforeEach: true, describe: true, expect: true, it: true, spyOn: true */ + +describe('jsdoc/path', function() { + var os = require('os'); + var path = require('jsdoc/path'); + var standardPath = require('path'); + + it('should exist', function() { + expect(path).toBeDefined(); + expect(typeof path).toEqual('object'); + }); + + it('should export all functions in the "path" module', function() { + Object.keys(standardPath).forEach(function(item) { + if (typeof standardPath[item] === 'function') { + expect(path[item]).toBeDefined(); + expect(typeof path[item]).toEqual('function'); + } + }); + }); + + it('should export a "commonPrefix" function', function() { + expect(path.commonPrefix).toBeDefined(); + expect(typeof path.commonPrefix).toEqual('function'); + }); + + describe('commonPrefix', function() { + beforeEach(function() { + spyOn(process, 'cwd').andCallFake(function() { + return os.platform().match(/^win/) ? 'C:\\Users\\jsdoc' : '/Users/jsdoc'; + }); + }); + + it('finds the correct prefix for a group of relative paths', function() { + var cwd = process.cwd().split(path.sep); + var paths = [ + path.join('foo', 'bar', 'baz', 'qux.js'), + path.join('foo', 'bar', 'baz', 'quux.js'), + path.join('foo', 'bar', 'baz.js') + ]; + // we expect a trailing slash + var expected = cwd.concat('foo', 'bar', '').join(path.sep); + + expect( path.commonPrefix(paths) ).toEqual(expected); + }); + + it('finds the correct prefix for a group of absolute paths', function() { + var cwd = process.cwd().split(path.sep); + var paths = [ + cwd.concat('foo', 'bar', 'baz', 'qux.js').join(path.sep), + cwd.concat('foo', 'bar', 'baz', 'quux.js').join(path.sep), + cwd.concat('foo', 'bar', 'baz.js').join(path.sep) + ]; + // we expect a trailing slash + var expected = cwd.concat('foo', 'bar', '').join(path.sep); + + expect( path.commonPrefix(paths) ).toEqual(expected); + }); + + it('finds the correct prefix for a group of absolute paths and dotted relative paths', + function() { + var cwd = process.cwd().split(path.sep); + var paths = [ + path.join('..', 'jsdoc', 'foo', 'bar', 'baz', 'qux', 'quux', 'test.js'), + cwd.concat('foo', 'bar', 'bazzy.js').join(path.sep), + path.join('..', '..', 'Users', 'jsdoc', 'foo', 'bar', 'foobar.js') + ]; + // we expect a trailing slash + var expected = cwd.concat('foo', 'bar', '').join(path.sep); + + expect( path.commonPrefix(paths) ).toEqual(expected); + }); + + it('returns an empty string when there is no common prefix', function() { + // skip on Windows, since the paths share a drive letter at the start + if ( !os.platform().match(/^win/) ) { + var paths = [ + path.join('foo', 'bar', 'baz', 'qux.js'), + path.join('..', '..', 'Library', 'foo', 'bar', 'baz.js') + ]; + + expect( path.commonPrefix(paths) ).toEqual(''); + } + }); + }); +});