forked from angular/angular.io
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path_util-fns.jade
460 lines (408 loc) · 17.2 KB
/
_util-fns.jade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
//- 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';
- var _ngRepoURL = 'https://github.com/angular/angular';
- var _ngDocRepoURL = 'https://github.com/angular/angular.io';
- var _qsRepo = 'https://github.com/angular/quickstart';
- var _qsRepoZip = _qsRepo + '/archive/master.zip';
- var _npm = 'npm';
//- NgModule related
- var _AppModuleVsAppComp = 'AppModule'
- var _appModuleTsVsAppCompTs = 'src/app/app.module.ts'
- var _appModuleTsVsMainTs = 'src/app/app.module.ts'
- var _bootstrapModule = 'bootstrapModule'
- var _declsVsDirectives = 'declarations'
- var _moduleVsComp = 'module'
- var _moduleVsRootComp = 'module'
- var _platformBrowserDynamicVsBootStrap = 'platformBrowserDynamic'
//- Other
- var _truthy = 'truthy';
- var _falsy = 'falsy';
//- 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;
- };
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);
code-tabs
each filePath,index in filePaths
- var region = regions[index].trim();
- var tabName = tabNames[index].trim();
- var language = attributes.language || getExtn(filePath);
- var format = attributes.format || "linenums";
- var frag = getFrag(filePath, region);
- 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);
- 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
}
//---------------------------------------------------------------------------------------------------------
//- 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.
- // 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);
- // 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(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'");
- }
- 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;
- }
//- 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) : "";
- }
- 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 ...
- 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) {
- 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 || " ");
- 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;
- }
- 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;
- }
- }
- }
- }