angular-docs-cn/public/_includes/_util-fns.jade

454 lines
17 KiB
Plaintext
Raw Normal View History

2015-09-11 03:19:23 -04:00
//- Mixins and associated functions
//- _docsFor: used to identify the language this version of the docs if for;
//- Should be one of: 'ts', 'dart' or 'js'. Set in lang specific _util-fns file.
- var _docsFor = '';
//- Should match `_docsFor`, but in this case provides the full capitalized
//- name of the language.
- var _Lang = 'TypeScript';
//- Simple "macros" used via interpolation in text:
//- e.g., the #{_priv}el variable has an `@Input` #{_decorator}.
//- Use #{_decorator} whereever the word "decorator" is expected, provided it is not
//- preceded by the article "a". (E.g., will be "annotation" for Dart)
- var _decorator = 'decorator';
//- Articles (which toggle between 'a' and 'an'). Used for, e.g.,
//- array vs. list; decorator vs. annotation.
- var _a = 'a';
- var _an = 'an';
//- TS arrays vs. Dart lists
- var _Array = 'Array';
- var _array = 'array';
//- Promise vs. Future, etc
- var _Promise = 'Promise';
- var _PromiseUrl = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise';
- var _PromiseLinked = '<a href="' + _PromiseUrl + '">' + _Promise + '</a>';
- var _Observable = 'Observable';
//- Directories & folders
- var _appDir = 'app';
- var _indexHtmlDir = 'project root';
- var _mainDir = _appDir;
//- Location of sample code
- var _liveLink = 'live link';
//- NgModule related
- var _AppModuleVsAppComp = 'AppModule'
- var _appModuleTsVsAppCompTs = 'app/app.module.ts'
- var _appModuleTsVsMainTs = 'app/app.module.ts'
- var _bootstrapModule = 'bootstrapModule'
- var _moduleVsComp = 'module'
- var _moduleVsRootComp = 'module'
- var _platformBrowserDynamicVsBootStrap = 'platformBrowserDynamic'
//- Other
- var _truthy = 'truthy';
- var _falsey = 'falsey';
//- Used to prefix identifiers that are private. In Dart this will be '_'.
- var _priv = '';
//- Use to conditionally include the block that follows +ifDocsFor(...).
//- Generally favor use of Jade named blocks instead. ifDocsFor is convenient
//- for prose that should appear only in one language version.
mixin ifDocsFor(langPattern)
if _docsFor.toLowerCase().match(langPattern.toLowerCase())
block
//- Use to map inlined (prose) TS paths into, say, Dart paths via the
//- adjustTsExamplePathForDart transformer function.
mixin adjExPath(path)
if adjustTsExamplePathForDart
| #{adjustTsExamplePathForDart(path)}
else
| #{path}
mixin includeShared(filePath, region)
- var newPath = translatePath(filePath, region);
!=partial(newPath)
mixin makeExample(_filePath, region, _title, stylePatterns)
- var adjustments = adjustExamplePathAndTitle({filePath:_filePath, title:_title});
- var filePath = adjustments.filePath;
- var title = adjustments.title;
- var language = attributes.language || getExtn(filePath);
- var frag = getFrag(filePath, region);
- var defaultFormat = frag.split('\n').length > 2 ? "linenums" : "";
- var format = attributes.format || defaultFormat;
- if (attributes.format === '.') format = '';
- var avoid = !!attributes.avoid;
- var avoidClass = avoid ? 'is-anti-pattern' : '';
div(class="code-example #{avoidClass}")
if (title)
header
h4 #{title}
code-example(language="#{language}" format="#{format}")
!= styleString(frag, stylePatterns)
//- Like makeExample, but: (1) doesn't show line numbers. (2) If region
//- is omitted and title is 'foo (r)' then region is taken as 'r'.
//- (3) Title will always end with a phrase in parentheses; if no such
//- ending is given or is just (), then the title will be suffixed with
//- either "(excerpt)", or "(#{_region})" when _region is defined.
mixin makeExcerpt(_filePath, _region, _title, stylePatterns)
- var matches = _filePath.match(/(.*)\s+\(([^\)]*)\)$/);
- var parenText;
- if (matches) { _filePath = matches[1]; parenText = matches[2]; }
- var adjustments = adjustExamplePathAndTitle({filePath:_filePath, title:_title});
- var filePath = adjustments.filePath;
- var title = adjustments.title;
- var region = _region || (_region === '' ? '' : parenText);
- var excerpt = parenText || region || 'excerpt';
- if (title) title = title + ' (' + excerpt + ')';
+makeExample(filePath, region, title, stylePatterns)(format='.')
//- Get the doc example name either from `_example` if set, or
//- extract the example name from `current`.
- var getExampleName = function() {
- var dir = current.path[current.path.length - 1];
- return _example ? _example : dir == 'latest' ? current.source : dir;
- };
2015-09-11 03:19:23 -04:00
mixin makeTabs(filePaths, regions, tabNames, stylePatterns)
- filePaths = strSplit(filePaths);
- if (adjustTsExamplePathForDart) filePaths = filePaths.map(adjustTsExamplePathForDart);
- regions = strSplit(regions, filePaths.length);
- tabNames = strSplit(tabNames, filePaths.length);
- if (adjustTsExampleTitleForDart) tabNames = tabNames.map(adjustTsExampleTitleForDart);
2015-09-11 03:19:23 -04:00
code-tabs
each filePath,index in filePaths
- var region = regions[index].trim();
2015-09-11 03:19:23 -04:00
- var tabName = tabNames[index].trim();
- var language = attributes.language || getExtn(filePath);
2015-09-11 03:19:23 -04:00
- var format = attributes.format || "linenums";
- var frag = getFrag(filePath, region);
2015-09-11 03:19:23 -04:00
- var sps = Array.isArray(stylePatterns) ? stylePatterns[index] : stylePatterns;
code-pane(language="#{language}" name="#{tabName}" format="#{format}")
!= styleString(frag, sps)
mixin makeJson( filePath, jsonConfig, title, stylePatterns)
- var language = attributes.language || getExtn(filePath);
2015-09-11 16:50:19 -04:00
- var format = attributes.format || "linenums";
- var frag = getFrag(filePath, '');
- var json = unescapeHtml(frag);
- var jsonExtract = extractJson(json, jsonConfig);
- var avoid = !!attributes.avoid;
- var avoidClass = avoid ? 'is-anti-pattern' : '';
div(class="code-example #{avoidClass}")
if (title)
header
h4 #{title}
code-example(language="#{language}" format="#{format}")
if (jsonExtract == 'ERROR')
err ERROR: Unable to extract json using config: "#{jsonConfig.toString()}"
else
!= styleString(jsonExtract, stylePatterns)
if !jade2ng
//- Open (and close) an explanation <div>. See QuickStart
script.
function why(id, backTo) {
var id = "#"+id;
var el = document.querySelector(id);
el.hidden=el.hidden=!el.hidden;
if (el.hidden && backTo){
// the next line is required to work around a bug in WebKit (Chrome / Safari)
location.href = "#";
location.href = "#" + backTo;
}
}
script.
function verbose(isVerbose) {
isVerbose = !! isVerbose;
var el = document.querySelector('button.verbose.off');
el.style.display = isVerbose ? 'block' : 'none';
var el = document.querySelector('button.verbose.on');
el.style.display = isVerbose ? 'none' : 'block';
CCSStylesheetRuleStyle('main','.l-verbose-section', 'display',
isVerbose ? 'block' : 'none');
}
script.
function CCSStylesheetRuleStyle(stylesheet, selectorText, style, value){
/* returns the value of the element style of the rule in the stylesheet
* If no value is given, reads the value
* If value is given, the value is changed and returned
* If '' (empty string) is given, erases the value.
* The browser will apply the default one
*
* string stylesheet: part of the .css name to be recognized, e.g. 'default'
* string selectorText: css selector, e.g. '#myId', '.myClass', 'thead td'
* string style: camelCase element style, e.g. 'fontSize'
* string value optional : the new value
*/
var CCSstyle = undefined, rules, sheet;
for(var m in document.styleSheets){
sheet = document.styleSheets[m];
if(sheet.href && sheet.href.indexOf(stylesheet) != -1){
rules = sheet[document.all ? 'rules' : 'cssRules'];
for(var n in rules){
console.log(rules[n].selectorText);
if(rules[n].selectorText == selectorText){
CCSstyle = rules[n].style;
break;
}
}
break;
}
}
if(value == undefined)
return CCSstyle[style]
else
return CCSstyle[style] = value
}
2015-09-11 16:50:19 -04:00
//---------------------------------------------------------------------------------------------------------
//- Converts the given project-relative path (like 'app/main.ts')
//- to a doc folder relative path (like 'quickstart/ts/app/main.ts')
//- by prefixing it with '<example-name>/ts/'. If title is not given,
//- then the project-relative path is used, adjusted to remove numeric
//- file version qualifiers; e.g. 'styles.1.css' becomes 'styles.css'.
- var adjExampleProjPathAndTitle = function(ex/*:{filePath,title}*/) {
- // E.g. of a project relative path is 'app/main.ts'
- if (ex.title === null || ex.title === undefined) {
- // Title is not given so take it to be ex.filePath.
docs(toh-5): TS/Dart review, and Dart resync (#2115) * docs(toh-5): review and update/resync Dart **NOTE: run `gulp add-example-boilerplate` after pulling in the commit.** This is preparatory work for #2035. As part of the the chapter review, the Dart .jade was enhanced to use Jade extends (#2018). By the same token it contributed to a post-RC5 resync (#2077). Other key changes: Dart and TS code: - Eliminated `styles.1.css` in favor of docregions in `styles.css`. - `docregion` tags renamed in a few places. - **No other code changes**. TS prose - Fixed: misnamed variable `routing` -> `appRoutes`. - All other changes are **minor copy edits**, or changes to support Dart via Jade extends. Diff of generated HTML for TS chapter was inspected to ensure only minor copy edits prevailed (i.e., that the support for Jade extends had no impact on the generated HTML). * docs(toh-5): edits after doing tutorial - Some adjustments following actually doing the tutorial. In some cases code shown (e.g. this is what file foo should look like now) didn't match what the user would have. E.g., lingering @Input on the hero property. - Fixed some lingering deprecated-router prose elements on TS side (e.g., still referring to a route by the old string names like `HeroDetail`). - Added extra step to `app.component.ts` creation rather than having a critical-call-out later on. - Reorder some prose for better harmony between TS and Dart prose (also improves the flow). - Moved the `styleUrls` call-out to the point of first use. * post-review changes * more post-review changes * toh-6 cache update
2016-08-17 16:31:40 -04:00
- // Title like styles.1.css or foo_1.dart? Then drop the '.1' or '_1' qualifier:
- var matches = ex.filePath.match(/^(.*)[\._]\d(\.\w+)$/);
- ex.title = matches ? matches[1] + matches[2] : ex.filePath;
- }
- ex.filePath = getExampleName() + '/' + _docsFor + '/' + ex.filePath;
- return ex;
- };
//- If the given path is project relative, then first convert it using
//- adjExampleProjPathAndTitle(ex). Then the path is adjusted to match
//- the documentation language.
- var adjustExamplePathAndTitle = function(ex/*:{filePath,title}*/) {
- // Not a doc folder relative path? Assume that it is app project relative.
- if(isProjRelDir(ex.filePath)) adjExampleProjPathAndTitle(ex);
- // Adjust doc folder relative paths if adjustment functions exist.
- if(adjustTsExamplePathForDart) ex.filePath = adjustTsExamplePathForDart(ex.filePath);
- if(adjustTsExampleTitleForDart) ex.title = adjustTsExampleTitleForDart(ex.title);
- return ex;
- };
//- Returns truthy iff path is example project relative.
- var isProjRelDir = function(path) {
- return !path.match(/\/(js|ts|dart)(-snippets)?\//) && !path.endsWith('e2e-spec.ts');
- // Last conjunct handles case for shared project e2e test file like
- // cb-component-communication/e2e-spec.js (is shared between ts & dart)
- // TODO: generalize: compare start with getExampleName(); which needs to be fixed.
- };
- var translatePath = function(filePath, region) {
- filePath = filePath.trim();
- var regionPad = (region && region.length) ? '-' + region.toString() : '';
- var matches = /{(.*)}.*/.exec(filePath);
- if (matches) {
- var topLevelDir = matches[1];
- var currentPath = current.path;
- var subPaths = currentPath.slice(2);
- // subPaths[subPaths.length - 1] = "_." + subPaths[subPaths.length - 1];
- subPaths[subPaths.length - 1] = "_fragments/" + subPaths[subPaths.length - 1];
- var newPath = getPathToDocs() + topLevelDir + '/' + subPaths.join("/");
- var result = newPath + regionPad + ".jade";
- } else {
- var extn = getExtn(filePath);
- var baseFileName = getBaseFileName(filePath);
- var noExtnFileName = baseFileName.substr(0,baseFileName.length - (extn.length + 1));
- var folder = getFolder(filePath);
- // var result = folder + "/_." + noExtnFileName + regionPad + "." + extn;
- var result = folder + "/_fragments/" + noExtnFileName + regionPad + "." + extn;
- }
- return result
- }
- var EMPTY_STRINGS = [ '','','','','','',''];
- var strSplit = function(str, length) {
- var res;
- str = str || '';
- if (!length) {
- res = str.split(",");
- } else {
- res = str.split(",");
- if (res.length < length) {
- res = res.concat(EMPTY_STRINGS.slice(0, length - res.length));
- }
- }
- return res;
- }
- var getFrag = function(filePath, region) {
- var fullFileName = getFragFilePath(filePath, region);
- var frag = partial(fullFileName);
- if (frag == null) {
- return "BAD FILENAME: " + fullFileName + " Current path: " + current.path + " PathToDocs: " + getPathToDocs();
- } else {
- // ``` gets translated to <pre><code>.....</code></pre> and we need
- // to remove this from the fragment prefix is 11 long and suffix is 13 long
- frag = frag.substring(11, frag.length-13);
2015-09-11 16:50:19 -04:00
- // Uncomment next line for debugging.
- // frag = "FileName: " + fullFileName + " Current path: " + current.path + " PathToDocs: " + getPathToDocs() + "\n" + frag;
- return frag;
- }
- }
- var extractJson = function(json, jsonConfig ) {
- try {
- if (jsonConfig) {
- return extractJsonFragment(json, jsonConfig.rootPath || null, jsonConfig.paths || [], jsonConfig.space || " ");
- } else {
- return json;
- }
- } catch (e) {
- return "ERROR";
- // return json;
- }
- }
- var unescapeHtml = function(s) {
- // can't break across multiple lines because of jade limitations.
- return s.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#039/g, "'");
- }
2015-09-11 16:50:19 -04:00
- var styleString = function(source, stylePatterns) {
- if (stylePatterns) {
- for (var styleName in stylePatterns) {
- var rxs = stylePatterns[styleName];
- rxs = Array.isArray(rxs) ? rxs : [rxs];
- rxs.forEach(function(rx) {
- source = applyStyle(source, styleName, rx );
- });
- }
- }
- return source;
- }
- var getFragFilePath = function (filePath, region) {
- filePath = filePath.trim();
- var extn = getExtn(filePath);
- var fileBase = filePath.substr(0,filePath.length - (extn.length + 1));
- var regionPad = (region && region.length) ? '-' + region.toString() : '';
- var fullFileName = getPathToFrags() + fileBase + regionPad + "." + extn + '.md';
- return fullFileName;
- }
2015-09-11 16:50:19 -04:00
//- styles a string according to a regular expression.
//- The match groups resulting from the regexp application are what is styled
//- (not the whole regexp).
- var applyStyle = function(str, styleName, rx) {
- var repls = {};
- var matches;
- do {
- matches = rx.exec(str);
- if (matches) {
- matches.slice(1).forEach(function(match) {
- var repl = '<span class="' + styleName + '">' + match + '</span>';
- repls[match] = { repl: repl, isGlobal: rx.global };
- });
- }
- } while (matches != null && rx.global );
- for (var match in repls) {
- var repl = repls[match];
- // var escapedMatch = match.replace(/\\/g,'\\').replace(/\(/g,'\(').replace(/\)/g, '\)').replace(/\./,'\.');
- // var rx2 = new RegExp(escapedMatch, repl.isGlobal ? "g" : "");
- var rx2 = match;
- str = str.replace(rx2, repl.repl);
- };
- return str;
- }
- var getExtn = function(fileName) {
- var ix = fileName.lastIndexOf('.');
- return ix > 0 ? fileName.substr(ix+1) : "";
- }
- var getBaseFileName = function(fileName) {
- var ix = fileName.lastIndexOf('/');
- return ix > 0 ? fileName.substr(ix+1) : "";
- }
- var getFolder = function(fileName) {
- var ix = fileName.lastIndexOf('/');
- return ix > 0 ? fileName.substr(0, ix) : "";
- }
2015-09-11 16:50:19 -04:00
- var getPathToDocs = function() {
- // simple way to only take as many '../' sections as we need to back up to the 'docs' dir
- // from the current document
- // we will almost certainly never go 10 or 11 deep but ...
2015-09-11 16:50:19 -04:00
- return current.pathToDocs || "../../../../../../../../../../../".substr(0, (current.path.length-2)*3);
- }
- var getPathToFrags = function() {
- return getPathToDocs() + "_fragments/";
- }
- var getPathToExamples = function() {
- return getPathToDocs() + "_examples/";
- }
//- Extract a subset of a json file in a specified order defined
//- by extractPaths while retaining original order for any
//- unspecified subobjects.
//-
//- based on the principle that JSON.parse(source) constructs objects
//- in order from the top down in 'source' and JSON.stringify(source) iterates 'source'
//- properties according to the order in which they were inserted. ( the spec actually
//- discourages this assumption but this method will only
//- run on node (v8) and the assumption seems safe there. )
- function extractJsonFragment(source, rootPath, extractPaths, space) {
2015-09-11 16:50:19 -04:00
- var objSource = JSON.parse(source);
- if (rootPath && rootPath.length > 0) {
- objSource = getSubObject(objSource, rootPath);
- }
- var objDest = {};
- extractPaths.trim().split(",").forEach(function(dotPath) {
- processPath(objSource, objDest, dotPath );
- });
- var result = JSON.stringify(objDest, null, space || " ");
2015-09-11 16:50:19 -04:00
- return result;
- function getSubObject(source, path) {
- var nextSource = source;
- var pathParts = path.trim().split(".");
- while (pathParts.length > 0) {
- var nextProp = pathParts.shift();
- nextSource = nextSource[nextProp];
- }
- return nextSource;
2015-09-11 16:50:19 -04:00
- }
- function processPath(source, dest, dotPath) {
- var nextSource = source;
- var nextDest = dest;
- var pathParts = dotPath.trim().split(".");
- while (pathParts.length > 0) {
- var nextProp = pathParts.shift();
- nextSource = nextSource[nextProp];
- if (pathParts.length > 0) {
- var val = nextDest[nextProp] || {};
- nextDest[nextProp] = val;
- nextDest = val;
- } else {
- nextDest[nextProp] = nextSource;
- }
2015-09-11 16:50:19 -04:00
- }
- }
- }