Skip to content

Commit

Permalink
feat: limiting the number of glossary links to once per paragraph (#118)
Browse files Browse the repository at this point in the history
* feat: Limiting the number of glossary links to first in paragraph (#117, #118, #127)
* test: New baseline.
  • Loading branch information
about-code authored Dec 6, 2020
1 parent 04894ce commit 0310e93
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 29 deletions.
25 changes: 20 additions & 5 deletions conf.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@
},
"linking": {
"description": "Whether to use relative or absolute links. Choosing 'absolute' requires a 'baseUrl'.",
"type": "string",
"enum": [
"relative",
"absolute"
],
"oneOf": [{
"$ref": "#/$defs/LinkingOpts"
},{
"description": "Deprecated. Use linking: { \"paths\": \"...\" } with values \"relative\" or \"absolute\" instead.",
"$ref": "#/$defs/LinkPaths"
}],
"default": "relative"
},
"outDir": {
Expand Down Expand Up @@ -224,6 +225,20 @@
}
}
},
"LinkingOpts": {
"type": "object",
"properties": {
"paths": { "$ref": "#/$defs/LinkPaths" },
"terms": {
"type": "string",
"enum": ["all", "first-in-paragraph"]
}
}
},
"LinkPaths": {
"type": "string",
"enum": ["relative", "absolute"]
},
"DevOpts": {
"type": "object",
"properties": {
Expand Down
6 changes: 6 additions & 0 deletions lib/linker.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ function linkifyAst(paragraphNode, headingNode, indexEntrySet, context, vFile) {
const termNode = termNodes[0];
const fromDocumentPath = vFile.path;
const toGlossaryPath = termNode.glossary.vFile.path;
const maxReplacements = (context.opts.linking.terms === "first-in-paragraph") ? 1 : Infinity;
let countReplacements = 0;
let linkNodes = [];
if (hasMultipleDefs) {
// Create superscript links if there exist multiple definitions for the term
Expand All @@ -114,13 +116,17 @@ function linkifyAst(paragraphNode, headingNode, indexEntrySet, context, vFile) {

// Search for term and insert a term occurrence node
const newParagraphNode = findReplace(paragraphNode, termNode.regex, (linkText) => {
if (countReplacements >= maxReplacements) {
return text(linkText);
}
if (!hasMultipleDefs && termNode.hint) {
if (/\$\{term\}/.test(termNode.hint)) {
linkText = termNode.hint.replace("${term}", linkText);
} else {
linkText += termNode.hint;
}
}
countReplacements ++;
return new TermOccurrence({
parent: paragraphNode
,headingNode: headingNode
Expand Down
2 changes: 1 addition & 1 deletion lib/path/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ api.getFileLinkUrl = function getFileLinkUrl(context, pathFrom, pathTo, anchor)
if (anchor && anchor[0] !== "#") {
anchor = `#${anchor}`;
}
if (linking === "relative") {
if (linking === "relative" || linking.paths === "relative") {
targetUrl = toForwardSlash(
relativeFromTo(
path.resolve(outDir, pathFrom || "."),
Expand Down
32 changes: 32 additions & 0 deletions test/input/config-linking/terms-first-in-paragraph/document.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Test Case 'option linking.terms'

## Section 1

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term 'Lorem'
AND a document with term 'Lorem' in this *first* paragraph *of section 1*
AND and the term 'Lorem' being mentioned *three times* in this paragraph
THEN only the first occurrence of the term MUST be linkified.

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term 'Lorem'
AND a document with term 'Lorem' in this *second* paragraph *of section 1*
AND and the term 'Lorem' being mentioned *three times* in this paragraph
THEN only the first occurrence of the term MUST be linkified.

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term 'Lorem'
AND a glossary term 'Ipsum'
AND a document with term 'Lorem' in this *third* paragraph *of section 1*
AND a document with term 'Ipsum' in this *third* paragraph *of section 1*
AND and the term 'Lorem' being mentioned *three times* in this paragraph
AND and the term 'Ipsum' being mentioned *three times* in this paragraph
THEN only the first occurrence of *each* term MUST be linkified.

## Section 2

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term 'Lorem'
AND a document with term 'Lorem' in this *first* paragraph *of section 2*
AND and the term 'Lorem' being mentioned *three times* in this paragraph
THEN only the first occurrence of the term MUST be linkified.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"$schema": "../../../../conf.schema.json",
"baseDir": ".",
"linking": {
"paths": "relative",
"terms": "first-in-paragraph"
},
"glossaries": [
{
"file": "./glossary.md"
}
],
"ignoreCase": false,
"outDir": "../../../output-actual/config-linking/terms-first-in-paragraph",
"dev": {
"termsFile": "../../../output-actual/config-linking/terms-first-in-paragraph/terms.json",
"reproducablePaths": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Glossary

## Lorem

Test term

## Ipsum

Test term
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# [Test Case 'option linking.terms'](#test-case-option-linkingterms)

## [Section 1](#section-1)

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term '[Lorem][1]'
AND a document with term 'Lorem' in this _first_ paragraph _of section 1_
AND and the term 'Lorem' being mentioned _three times_ in this paragraph
THEN only the first occurrence of the term MUST be linkified.

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term '[Lorem][1]'
AND a document with term 'Lorem' in this _second_ paragraph _of section 1_
AND and the term 'Lorem' being mentioned _three times_ in this paragraph
THEN only the first occurrence of the term MUST be linkified.

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term '[Lorem][1]'
AND a glossary term '[Ipsum][2]'
AND a document with term 'Lorem' in this _third_ paragraph _of section 1_
AND a document with term 'Ipsum' in this _third_ paragraph _of section 1_
AND and the term 'Lorem' being mentioned _three times_ in this paragraph
AND and the term 'Ipsum' being mentioned _three times_ in this paragraph
THEN only the first occurrence of _each_ term MUST be linkified.

## [Section 2](#section-2)

GIVEN option `linking: { terms: "first-in-paragraph" }`
AND a glossary term '[Lorem][1]'
AND a document with term 'Lorem' in this _first_ paragraph _of section 2_
AND and the term 'Lorem' being mentioned _three times_ in this paragraph
THEN only the first occurrence of the term MUST be linkified.

[1]: ./glossary.md#lorem "Test term"

[2]: ./glossary.md#ipsum "Test term"
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"$schema": "../../../../conf.schema.json",
"baseDir": ".",
"linking": {
"paths": "relative",
"terms": "first-in-paragraph"
},
"glossaries": [
{
"file": "./glossary.md"
}
],
"ignoreCase": false,
"outDir": "../../../output-actual/config-linking/terms-first-in-paragraph",
"dev": {
"termsFile": "../../../output-actual/config-linking/terms-first-in-paragraph/terms.json",
"reproducablePaths": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# [Glossary](#glossary)

## [Lorem](#lorem)

Test term

## [Ipsum](#ipsum)

Test term
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[
{
"shortDesc": "Test term",
"value": "Ipsum",
"hint": "",
"longDesc": "Test term",
"anchor": "#ipsum",
"glossary": {
"file": "./glossary.md",
"termHint": "",
"basePath": "/{CWD}/output-actual/config-linking/terms-first-in-paragraph/glossary.md",
"outPath": "/{CWD}/output-actual/config-linking/terms-first-in-paragraph/glossary.md"
},
"regex": {},
"aliases": [],
"ignoreCase": false,
"countOccurrenceTotal": 1
},
{
"shortDesc": "Test term",
"value": "Lorem",
"hint": "",
"longDesc": "Test term",
"anchor": "#lorem",
"glossary": {
"file": "./glossary.md",
"termHint": "",
"basePath": "/{CWD}/output-actual/config-linking/terms-first-in-paragraph/glossary.md",
"outPath": "/{CWD}/output-actual/config-linking/terms-first-in-paragraph/glossary.md"
},
"regex": {},
"aliases": [],
"ignoreCase": false,
"countOccurrenceTotal": 4
}
]
46 changes: 23 additions & 23 deletions test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"config": "node ../bin/index.js --config",
"dconfig": "node --inspect-brk ../bin/index.js --config",
"debug": "node --inspect-brk ../bin/index.js --config ./gitignore.conf.json",
"debug-at": "node --inspect-brk ./node_modules/.bin/npm-run-all",
"debug-diffcheck": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node --inspect-brk ../bin/test.js",
"pretest": "rm -rf ./output-actual",
"pretest-win": "del /Q .\\output-actual",
Expand Down Expand Up @@ -38,28 +37,29 @@
"test_17": "npx . --config ./input/config-excludeFiles/glossarify-md.conf.json",
"test_18": "npx . --config ./input/config-linking/relative/glossarify-md.conf.json",
"test_19": "npx . --config ./input/config-linking/absolute-baseUrl/glossarify-md.conf.json",
"test_20": "npx . --shallow \"{'baseDir':'./input/config-cli/arg-config-skip', 'outDir':'../../../output-actual/config-cli/arg-config-skip', 'includeFiles':['.'], 'glossaries':[{'file':'./glossary.md'}] }\"",
"test_21": "npx . --config ./input/config-cli/arg-shallow/glossarify-md.conf.json --shallow \"{'baseUrl': 'cli://localhost', 'linking': 'absolute', 'glossaries':[{'file':'./glossary2.md'}] }\"",
"test_22": "npx . --config ./input/config-cli/arg-deep/glossarify-md.conf.json --deep \"{'glossaries':[{'file':'./glossary2.md'}]}\"",
"test_23": "npx . --config ./input/config-cli/deep-defaults/glossarify-md.conf.json",
"test_24": "npx . --init > ./input/config-cli/arg-init/conf.gitignore.json && npx . --config ./input/config-cli/arg-init/conf.gitignore.json --shallow \"{ 'outDir': '../../../../output-actual/config-cli/arg-init/' }\"",
"test_25": "npx . --config ./input/config-indexFile/glossary-in-subdir/glossarify-md.conf.json",
"test_26": "npx . --config ./input/config-indexFile/index-in-subdir/glossarify-md.conf.json",
"test_27": "npx . --config ./input/config-indexFile/term-link-to-section/glossarify-md.conf.json",
"test_28": "npx . --config ./input/config-indexFile/multiple-glossaries/glossarify-md.conf.json",
"test_29": "npx . --config ./input/config-indexFile/config-title/glossarify-md.conf.json",
"test_30": "npx . --config ./input/count-term-occurrences/glossarify-md.conf.json",
"test_31": "npx . --config ./input/glossary-crosslinks/glossarify-md.conf.json",
"test_32": "npx . --config ./input/config-indexing/groupByHeadingDepth-missing/glossarify-md.conf.json",
"test_33": "npx . --config ./input/config-indexing/groupByHeadingDepth-0/glossarify-md.conf.json",
"test_34": "npx . --config ./input/config-indexing/groupByHeadingDepth-1/glossarify-md.conf.json",
"test_35": "npx . --config ./input/config-indexing/groupByHeadingDepth-2/glossarify-md.conf.json",
"test_36": "npx . --config ./input/config-listOfFigures/image-reference/glossarify-md.conf.json",
"test_37": "npx . --config ./input/config-listOfFigures/option-title-missing/glossarify-md.conf.json",
"test_38": "npx . --config ./input/config-listOfFigures/option-with-listOf-combined/glossarify-md.conf.json",
"test_39": "npx . --config ./input/config-listOfTables/glossarify-md.conf.json",
"test_40": "npx . --config ./input/config-listOf/glossarify-md.conf.json",
"test_41": "npx . --config ./input/config-indexFile/issue-75-formatted-headings/glossarify-md.conf.json",
"test_20": "npx . --config ./input/config-linking/terms-first-in-paragraph/glossarify-md.conf.json",
"test_21": "npx . --init > ./input/config-cli/arg-init/conf.gitignore.json && npx . --config ./input/config-cli/arg-init/conf.gitignore.json --shallow \"{ 'outDir': '../../../../output-actual/config-cli/arg-init/' }\"",
"test_22": "npx . --shallow \"{'baseDir':'./input/config-cli/arg-config-skip', 'outDir':'../../../output-actual/config-cli/arg-config-skip', 'includeFiles':['.'], 'glossaries':[{'file':'./glossary.md'}] }\"",
"test_23": "npx . --config ./input/config-cli/arg-shallow/glossarify-md.conf.json --shallow \"{'baseUrl': 'cli://localhost', 'linking': 'absolute', 'glossaries':[{'file':'./glossary2.md'}] }\"",
"test_24": "npx . --config ./input/config-cli/arg-deep/glossarify-md.conf.json --deep \"{'glossaries':[{'file':'./glossary2.md'}]}\"",
"test_25": "npx . --config ./input/config-cli/deep-defaults/glossarify-md.conf.json",
"test_26": "npx . --config ./input/config-indexFile/glossary-in-subdir/glossarify-md.conf.json",
"test_27": "npx . --config ./input/config-indexFile/index-in-subdir/glossarify-md.conf.json",
"test_28": "npx . --config ./input/config-indexFile/term-link-to-section/glossarify-md.conf.json",
"test_29": "npx . --config ./input/config-indexFile/multiple-glossaries/glossarify-md.conf.json",
"test_30": "npx . --config ./input/config-indexFile/config-title/glossarify-md.conf.json",
"test_31": "npx . --config ./input/count-term-occurrences/glossarify-md.conf.json",
"test_32": "npx . --config ./input/glossary-crosslinks/glossarify-md.conf.json",
"test_33": "npx . --config ./input/config-indexing/groupByHeadingDepth-missing/glossarify-md.conf.json",
"test_34": "npx . --config ./input/config-indexing/groupByHeadingDepth-0/glossarify-md.conf.json",
"test_35": "npx . --config ./input/config-indexing/groupByHeadingDepth-1/glossarify-md.conf.json",
"test_36": "npx . --config ./input/config-indexing/groupByHeadingDepth-2/glossarify-md.conf.json",
"test_37": "npx . --config ./input/config-listOfFigures/image-reference/glossarify-md.conf.json",
"test_38": "npx . --config ./input/config-listOfFigures/option-title-missing/glossarify-md.conf.json",
"test_39": "npx . --config ./input/config-listOfFigures/option-with-listOf-combined/glossarify-md.conf.json",
"test_40": "npx . --config ./input/config-listOfTables/glossarify-md.conf.json",
"test_41": "npx . --config ./input/config-listOf/glossarify-md.conf.json",
"test_42": "npx . --config ./input/config-indexFile/issue-75-formatted-headings/glossarify-md.conf.json",
"postsuite": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node ../bin/test.js",
"postat": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node ../bin/test.js",
"new-baseline": "rm -r ./output-expected && mv ./output-actual ./output-expected",
Expand Down

0 comments on commit 0310e93

Please sign in to comment.