Skip to content

Commit

Permalink
feat: Generate an index from glossary terms with links to sections wh…
Browse files Browse the repository at this point in the history
…ere they are being mentioned. (#3)

Adds a new config option 'indexFile'. Details see README.md
  • Loading branch information
about-code committed Dec 8, 2019
1 parent bb27d6c commit bc94edb
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 18 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ When true any occurrence of a term will be linked no matter how it was spelled.

Paths or Glob-Patterns for files to include.

### `--indexFile` | `--x`

- **Range:** string[]

Path relative to `outDir` where to write an index file to. The index contains links from glossary terms to their occurrences in documents or document sections.

### `--keepRawFiles` | `--r`

- **Range:** string[]
Expand Down
1 change: 1 addition & 0 deletions lib/glossarify.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ api.glossarify = function(opts) {
.then(context => terminator.readTermDefinitions(context))
.then(context => linker.linkTermOccurrences(context))
.then(context => writer.writeOutput(context))
.then(context => writer.writeIndex(context))
.then(context => writer.writeReport(context))
.then(context => writer.writeTestOutput(context))
.catch(err => console.error(err) && proc.exit(1));
Expand Down
36 changes: 36 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const {relativeFromTo} = require("./pathplus");
const path = require("path");

const api = {};
let md = "";

api.writeIndex = function(context) {
md =
`# Index
`;
const {terms: dict, opts} = context;
const {outDir, indexFile} = opts;
const terms = dict.inOrder();
for (let i = 0, iLen = terms.length; i < iLen; i++) {
const term = terms[i];
const text = term.term;
const glossaryUrl = relativeFromTo(
path.resolve(outDir, indexFile),
path.resolve(outDir, term.glossary.file)
) + term.anchor;
md +=
`
#### ${text}
* [Glossary](${glossaryUrl})
`;
const occurrences = terms[i].occurrences;
for (url of Object.keys(occurrences)) {
md +=
`* [${occurrences[url]}](${url})
`;
}
};
return md;
}
module.exports = api;
17 changes: 14 additions & 3 deletions lib/linker.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Term = require("./term.js");
const linkifyRegex = require("./linkify");
const common = require("./common.js");
const {toSystemSlash, toForwardSlash} = require("./pathplus");
const {relativeFromTo, toForwardSlash} = require("./pathplus");
const path = require("path");
const unified = require("unified");
const unifiedNgin = require("unified-engine");
Expand Down Expand Up @@ -120,6 +120,7 @@ function linker(context) {
*/
function linkify(txtNode, sectionNode, termDefs, context, vFile) {
const sectionUrl = getSectionUrl(context, sectionNode, vFile);
const sectionTitle = getSectionTitle(sectionNode);
const term = termDefs[0];
const hasMultipleDefs = termDefs.length > 1;
let linkNode_ = null;
Expand All @@ -129,7 +130,7 @@ function linkify(txtNode, sectionNode, termDefs, context, vFile) {
linkNode.title = term.getShortDescription();
linkNode.url = getGlossaryUrl(context, term, vFile);
linkNode_ = linkNode;
term.countOccurrence(sectionUrl);
term.addOccurrence(sectionTitle, sectionUrl);
if (!hasMultipleDefs && term.hint) {
if (/\$\{term\}/.test(term.hint)) {
linkNode.children[0].value = term.hint.replace("${term}", linkNode.children[0].value);
Expand Down Expand Up @@ -228,7 +229,7 @@ function getSectionUrl(context, sectionNode, vFile) {
let file = `${vFile.dirname}/${vFile.basename}`;
if (linking === 'relative') {
sectionUrl = toForwardSlash(
path.relative(
relativeFromTo(
path.resolve(outDir, indexFile),
path.resolve(outDir, file)
)
Expand All @@ -251,4 +252,14 @@ function getSectionUrl(context, sectionNode, vFile) {
return url.parse(sectionUrl).format();
}

function getSectionTitle(sectionNode) {
if (! sectionNode || !sectionNode.children || sectionNode.children.length === 0) {
return;
} else if (sectionNode.children[0].type === "text") {
return sectionNode.children[0].value;
} else {
return getSectionTitle(sectionNode.children[0]);
}
}

module.exports = api;
14 changes: 5 additions & 9 deletions lib/term.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ class Term {
this.regex = data.regex || "";
this.aliases = [...(data.aliases || [])];
this.ignoreCase = false || data.ignoreCase;
this.countOccurrenceByFile = {};
this.occurrences = {};
this.countOccurrenceTotal = 0;
this.setTerm(this.term);
this.setAliases(this.aliases);

}

setAliases(strArray) {
Expand All @@ -29,13 +28,10 @@ class Term {
updateRegExp(this);
}

countOccurrence(path) {
const countByFile = this.countOccurrenceByFile;
const count = countByFile[path];
if (! count) {
countByFile[path] = 1;
} else {
countByFile[path] = count + 1;
addOccurrence(sectionTitle, sectionUrl) {
const occurrences = this.occurrences;
if (sectionUrl && !occurrences[sectionUrl]) {
occurrences[sectionUrl] = sectionTitle || sectionUrl;
}
this.countOccurrenceTotal++;
}
Expand Down
24 changes: 21 additions & 3 deletions lib/writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require("path");
const proc = require("process");
const glob = require("glob");
const {toForwardSlash, toSystemSlash} = require("./pathplus");

const {writeIndex} = require("./index");
const CWD = proc.cwd();
const api = {};

Expand Down Expand Up @@ -47,6 +47,24 @@ api.copyBaseDirToOutDir = function(context) {
});
}

api.writeIndex = function(context) {
const {opts, terms} = context;
const {indexFile, outDir} = opts;
if (! indexFile) {
return Promise.resolve(context);;
}
return new Promise((resolve, reject) => {
const p = path.resolve(outDir, indexFile);
fs.outputFile(p, writeIndex(context), (err) => {
if (err) {
reject(err);
} else {
resolve(context);
}
})
});
}

api.writeReport = function(context) {
const {terms: dict} = context;
let report = "";
Expand All @@ -72,8 +90,8 @@ api.writeOutput = function(context) {
} else {
resolve(context);
}
})})
)
})
}))
).then(() => context);
}

Expand Down
5 changes: 2 additions & 3 deletions test/conf.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ let errors = [];
})();

if(errors.length > 0) {
console.log(`Tests failed with errors.
${errors}
`, );
console.log(errors);
console.log("Tests failed with errors.");
process.exit(1);
};

0 comments on commit bc94edb

Please sign in to comment.