chore: fix "Invalid example" warnings from shred map builder

closes #1832
The shred map (xref) builder was issuing warnings. This fix includes
- Adjustments to the shredder map builder itself so that it
understands, e.g., app-project relative example paths.
- `**/guide/glossary.jade` now (Jade) `includes` the shared parent
`glossary.jade` rather than (Harp) importing (via `partial`). This
fixes `makeExample` path issues in the glossary.
- Adjusted some `makeExample` paths that were ok for site build, but
confused the xref tool.
This commit is contained in:
Patrice Chalin 2016-07-05 16:46:44 -07:00 committed by Ward Bell
parent 0664a271ba
commit fb9edf972e
6 changed files with 51 additions and 31 deletions

View File

@ -101,7 +101,7 @@ block dart-map-alternative
As an alternative to using a configuration `Map`, we can define
a custom configuration class:
+makeExample('dependency-injection/ts/app/app.config.ts','config-alt','app/app-config.ts (alternative config)')(format='.')
+makeExample('lib/app_config.dart (alternative config)','config-alt')
:marked
Defining a configuration class has a few benefits. One key benefit

View File

@ -1 +1 @@
!= partial("../glossary")
include ../glossary

View File

@ -132,9 +132,6 @@ code-example(language="bash").
### Add a base tag
// Our Tour of Heroes needs routing,
// so we load the library in the `index.html` in a script tag immediately *after* the angular script itself.
//+makeExample('toh-5/dart/web/index.html', 'router', 'index.html (router)')(format=".")
:marked
First, edit `index.html` and add `<base href="/">` at the top of the `<head>` section.
+makeExample('toh-5/dart/web/index.html', 'base-href', 'index.html (base href)')(format=".")

View File

@ -54,7 +54,7 @@ include _util-fns
The barrel itself is a module file that re-exports *selected* exports of other modules.
Imagine three modules in a `heroes` folder:
code-example(format='').
code-example.
// heroes/hero.component.ts
export class HeroComponent {}
@ -65,26 +65,26 @@ include _util-fns
export class HeroService {}
:marked
Without a barrel, a consumer would need three import statements:
code-example(format='').
code-example.
import { HeroComponent } from '../heroes/hero.component.ts';
import { Hero } from '../heroes/hero.model.ts';
import { HeroService } from '../heroes/hero.service.ts';
:marked
We can add a barrel to the `heroes` folder (called `index` by convention) that exports all of these items:
code-example(format='').
code-example.
export * from './hero.model.ts'; // re-export all of its exports
export * from './hero.service.ts'; // re-export all of its exports
export { HeroComponent } from './hero.component.ts'; // re-export the named thing
:marked
Now a consumer can import what it needs from the barrel.
code-example(format='').
code-example.
import { Hero, HeroService } from '../heroes'; // index is implied
:marked
The Angular [scoped packages](#scoped-package) each have a barrel named `index`.
// #enddocregion b-c
:marked
That's why we can write this:
+makeExample('../docs/_fragments/quickstart/ts/app/app.component.ts', 'import')(format=".")
+makeExcerpt('quickstart/ts/app/app.component.ts', 'import', '')
// #docregion b-c
:marked
@ -584,7 +584,7 @@ include _util-fns
The only difference, from a consumer perspective,
is that the package name begins with the Angular *scope name*, `@angular`.
+makeExample('../docs/_fragments/architecture/ts/app/app.component.ts', 'import')(format=".")
+makeExcerpt('architecture/ts/app/app.component.ts', 'import', '')
// #docregion n-s-2
:marked

View File

@ -1 +1 @@
!= partial("../glossary")
include ../glossary

View File

@ -18,25 +18,37 @@ module.exports = function shredMapProcessor(log, createDocMessage) {
var fragToJadeMap = {};
docs.forEach(function(doc) {
var jadePath = path.join(options.jadeDir, doc.fileInfo.relativePath);
var relativePath = doc.fileInfo.relativePath;
var jadePath = path.join(options.jadeDir, relativePath);
var lang = relativePath.substr(0, relativePath.indexOf('\/'));
var appProjDirName = jadeBaseFileNameToExampleName(doc.fileInfo.baseName);
var fragInfoSet = {};
doc.fragItems.forEach(function(fragItem) {
var mixinPath = fragItem.mixinPath;
var fullExamplePath;
// Normalize mixinPath: strip out optional trailing '(...)'
var mixinPath = mixinPath.replace(/ \([^\)]*\)/,'');
if ( mixinPath.indexOf('_api') >= 0) {
var sourcePath = mixinPath.replace('_api/','');
fullExamplePath = path.join(options.apiExamplesDir, sourcePath);
} else {
fullExamplePath = path.join(options.devguideExamplesDir, mixinPath);
}
var region = fragItem.region ? "-" + fragItem.region : '';
var extn = path.extname(mixinPath);
var basename = path.basename(mixinPath, extn);
var fragDir = path.dirname(mixinPath);
var fragPath = path.join(fragDir, basename + region + extn) + '.md';
var fullFragPath = path.join(options.fragmentsDir, fragPath);
var fragInfo = { fragPath: fullFragPath, examplePath: fullExamplePath, exists: fs.existsSync(fullFragPath) };
var fragInfo = makeFragInfo(options.fragmentsDir, fullExamplePath, fragItem, mixinPath);
if (!fragInfo.exists) {
var savedFragInfo = fragInfo;
// Assume that mixinPath is actually app-project-folder relative and
// prepend "lang/appProjDirName":
var appProjRelPath = mixinPath;
mixinPath = appProjDirName + '/' + lang + '/' + mixinPath;
fragInfo = makeFragInfo(options.fragmentsDir, fullExamplePath, fragItem, mixinPath);
if (fragInfo.exists) {
log.info('Ajusted example path (' + doc.fileInfo.baseName + '): ' + appProjRelPath + ' -> ' + mixinPath);
} else {
fragInfo = savedFragInfo;
}
}
var fragPath = fragInfo.relFragPath;
fragInfoSet[fragPath] = fragInfo;
if (fragInfo.exists) {
var jadePathsSet = fragToJadeMap[fragPath];
@ -46,7 +58,7 @@ module.exports = function shredMapProcessor(log, createDocMessage) {
}
jadePathsSet[jadePath] = jadePath;
} else {
var relativePath = path.relative(".", fullFragPath);
var relativePath = path.relative(".", fragInfo.fragPath);
log.warn(createDocMessage('Invalid example (unable to locate fragment file: "' + relativePath + '")', doc));
}
});
@ -82,13 +94,24 @@ module.exports = function shredMapProcessor(log, createDocMessage) {
}
};
function getExampleName(fragPath) {
// pattern to isolate base fileName and extension from fragment name
var rx = /(.*)\-(.*)\.(.s)/;
var r = rx.exec(fragPath);
if (r) {
return r[1] + '.' + r[3];
} else {
return fragPath;
// TODO: use the functionality in public/resources/js/util.js once it lands.
function jadeBaseFileNameToExampleName(name) {
// Adjust for known cases where chapter name is not the example name.
var matches = name.match(/(toh-)pt(\d+)/);
if (matches) name = matches[1] + matches[2];
return name;
}
function makeFragInfo(fragmentsDir, fullExamplePath, fragItem, mixinPath) {
var region = fragItem.region ? "-" + fragItem.region : '';
var extn = path.extname(mixinPath);
var basename = path.basename(mixinPath, extn);
var fragDir = path.dirname(mixinPath);
var fragPath = path.join(fragDir, basename + region + extn) + '.md';
var fullFragPath = path.join(fragmentsDir, fragPath);
return {
fragPath: fullFragPath,
relFragPath: fragPath,
examplePath: fullExamplePath,
exists: fs.existsSync(fullFragPath) };
}