ebnf2railroad
Advanced tools
Comparing version 1.13.0 to 1.13.1
{ | ||
"name": "ebnf2railroad", | ||
"version": "1.13.0", | ||
"version": "1.13.1", | ||
"description": "EBNF to Railroad diagram", | ||
@@ -31,6 +31,9 @@ "keywords": [ | ||
"private": false, | ||
"files": ["src/*", "bin/*"], | ||
"files": [ | ||
"src/*", | ||
"bin/*" | ||
], | ||
"dependencies": { | ||
"commander": "^2.19.0", | ||
"prettier": "^1.14.3", | ||
"prettier": "2.8.4", | ||
"railroad-diagrams": "https://github.com/tabatkins/railroad-diagrams#c7730b8fab6cb0fd55fc3c3b0a81ce355fdbf963", | ||
@@ -37,0 +40,0 @@ "showdown": "^1.0.0", |
# EBNF 2 RailRoad | ||
[![travis](https://badgen.now.sh/travis/matthijsgroen/ebnf2railroad?icon=travis)](https://travis-ci.org/matthijsgroen/ebnf2railroad) | ||
[![npm](https://badgen.now.sh/npm/v/ebnf2railroad?icon=npm)](http://npm.im/ebnf2railroad) | ||
[![code style: prettier](https://badgen.now.sh/badge/code%20style/prettier/ff69b4)](https://github.com/prettier/prettier) | ||
[![publishsize](https://badgen.now.sh/packagephobia/publish/ebnf2railroad)](https://packagephobia.now.sh/result?p=ebnf2railroad) | ||
[![license](https://badgen.now.sh/github/license/matthijsgroen/ebnf2railroad)](https://github.com/matthijsgroen/ebnf2railroad) | ||
@@ -113,5 +111,3 @@ | ||
[example-ebnf]: | ||
http://htmlpreview.github.io/?https://github.com/matthijsgroen/ebnf2railroad/blob/master/examples/ebnf.html | ||
[example-json]: | ||
http://htmlpreview.github.io/?https://github.com/matthijsgroen/ebnf2railroad/blob/master/examples/json.html | ||
[example-ebnf]: http://htmlpreview.github.io/?https://github.com/matthijsgroen/ebnf2railroad/blob/master/examples/ebnf.html | ||
[example-json]: http://htmlpreview.github.io/?https://github.com/matthijsgroen/ebnf2railroad/blob/master/examples/json.html |
@@ -16,6 +16,6 @@ const { traverse } = require("./traverse"); | ||
ExceptTerminal: 11, | ||
ExceptNonTerminal: 12 | ||
ExceptNonTerminal: 12, | ||
}; | ||
const identifyNode = node => { | ||
const identifyNode = (node) => { | ||
if (Array.isArray(node)) return NodeTypes.Root; | ||
@@ -41,24 +41,24 @@ if (node.definition) return NodeTypes.Production; | ||
...node, | ||
definition: next(node.definition) | ||
definition: next(node.definition), | ||
}), | ||
[NodeTypes.Choice]: (node, next) => ({ | ||
...node, | ||
choice: node.choice.map(next) | ||
choice: node.choice.map(next), | ||
}), | ||
[NodeTypes.Group]: (node, next) => ({ | ||
...node, | ||
group: next(node.group) | ||
group: next(node.group), | ||
}), | ||
[NodeTypes.Sequence]: (node, next) => ({ | ||
...node, | ||
sequence: node.sequence.map(next) | ||
sequence: node.sequence.map(next), | ||
}), | ||
[NodeTypes.Optional]: (node, next) => ({ | ||
...node, | ||
optional: next(node.optional) | ||
optional: next(node.optional), | ||
}), | ||
[NodeTypes.Repetition]: (node, next) => ({ | ||
...node, | ||
repetition: next(node.repetition) | ||
}) | ||
repetition: next(node.repetition), | ||
}), | ||
}; | ||
@@ -68,3 +68,3 @@ | ||
const ebnfOptimizer = transformers => ast => { | ||
const ebnfOptimizer = (transformers) => (ast) => { | ||
const optimize = ebnfTransform(transformers); | ||
@@ -85,3 +85,3 @@ let current = ast; | ||
identifyNode, | ||
travelers | ||
travelers, | ||
}; |
const { NodeTypes } = require("../ebnf-transform"); | ||
const skipFirst = list => | ||
const skipFirst = (list) => | ||
[ | ||
list.some(e => e === "skip" || e.skip) && { skip: true }, | ||
...list.filter(e => e !== "skip" && !e.skip) | ||
list.some((e) => e === "skip" || e.skip) && { skip: true }, | ||
...list.filter((e) => e !== "skip" && !e.skip), | ||
].filter(Boolean); | ||
@@ -13,10 +13,10 @@ | ||
module.exports = { | ||
[NodeTypes.Choice]: current => { | ||
[NodeTypes.Choice]: (current) => { | ||
if (!current.choice) return current; | ||
const isCertain = elem => | ||
const isCertain = (elem) => | ||
(elem.terminal && elem) || (elem.nonTerminal && elem); | ||
const groupElements = elements => { | ||
const allSet = elements.every(f => f); | ||
const groupElements = (elements) => { | ||
const allSet = elements.every((f) => f); | ||
if (!allSet) return {}; | ||
@@ -29,3 +29,3 @@ return elements.reduce((acc, elem) => { | ||
}; | ||
const countSame = groupElements => { | ||
const countSame = (groupElements) => { | ||
const amounts = Object.values(groupElements); | ||
@@ -36,6 +36,7 @@ return Math.max(...amounts); | ||
const collectCertainFirstElements = current.choice.map( | ||
elem => isCertain(elem) || (elem.sequence && isCertain(elem.sequence[0])) | ||
(elem) => | ||
isCertain(elem) || (elem.sequence && isCertain(elem.sequence[0])) | ||
); | ||
const collectCertainLastElements = current.choice.map( | ||
elem => | ||
(elem) => | ||
isCertain(elem) || | ||
@@ -86,7 +87,7 @@ (elem.sequence && isCertain(elem.sequence[elem.sequence.length - 1])) | ||
optional: | ||
newChoices.length == 1 ? newChoices[0] : { choice: newChoices } | ||
newChoices.length == 1 ? newChoices[0] : { choice: newChoices }, | ||
}, | ||
newChoices.length > 0 && | ||
!hasEmpty && | ||
(newChoices.length == 1 ? newChoices[0] : { choice: newChoices }) | ||
(newChoices.length == 1 ? newChoices[0] : { choice: newChoices }), | ||
].filter(Boolean); | ||
@@ -102,3 +103,3 @@ const replacementElement = | ||
.concat(replacementElement) | ||
.concat(afterChoices) | ||
.concat(afterChoices), | ||
} | ||
@@ -140,3 +141,3 @@ : replacementElement; | ||
optional: | ||
newChoices.length == 1 ? newChoices[0] : { choice: newChoices } | ||
newChoices.length == 1 ? newChoices[0] : { choice: newChoices }, | ||
}, | ||
@@ -146,3 +147,3 @@ newChoices.length > 0 && | ||
(newChoices.length == 1 ? newChoices[0] : { choice: newChoices }), | ||
JSON.parse(lastElement) | ||
JSON.parse(lastElement), | ||
].filter(Boolean); | ||
@@ -158,3 +159,3 @@ const replacementElement = | ||
.concat(replacementElement) | ||
.concat(afterChoices) | ||
.concat(afterChoices), | ||
} | ||
@@ -172,3 +173,3 @@ : replacementElement; | ||
current.choice | ||
.map(item => { | ||
.map((item) => { | ||
const optimizedItem = item; | ||
@@ -182,3 +183,3 @@ if (optimizedItem.choice) { | ||
.reduce((acc, item) => acc.concat(item), []) | ||
) | ||
), | ||
}; | ||
@@ -189,3 +190,3 @@ if (equalElements(result, current)) { | ||
return result; | ||
} | ||
}, | ||
}; |
const { NodeTypes } = require("../ebnf-transform"); | ||
module.exports = { | ||
[NodeTypes.Optional]: current => { | ||
[NodeTypes.Optional]: (current) => { | ||
if (!current.optional || !current.optional.choice) { | ||
@@ -11,8 +11,10 @@ return current; | ||
current.optional.choice | ||
.filter(node => !node.skip) | ||
.map(node => (node.repetition ? { ...node, skippable: false } : node)) | ||
) | ||
.filter((node) => !node.skip) | ||
.map((node) => | ||
node.repetition ? { ...node, skippable: false } : node | ||
) | ||
), | ||
}; | ||
}, | ||
[NodeTypes.Choice]: current => { | ||
[NodeTypes.Choice]: (current) => { | ||
if (!current.choice) { | ||
@@ -22,3 +24,3 @@ return current; | ||
const hasSkippableRepetition = current.choice.some( | ||
node => node.repetition && node.skippable | ||
(node) => node.repetition && node.skippable | ||
); | ||
@@ -29,11 +31,11 @@ if (hasSkippableRepetition) { | ||
current.choice | ||
.filter(node => !node.skip) | ||
.map( | ||
node => (node.repetition ? { ...node, skippable: false } : node) | ||
.filter((node) => !node.skip) | ||
.map((node) => | ||
node.repetition ? { ...node, skippable: false } : node | ||
) | ||
) | ||
), | ||
}; | ||
} | ||
return current; | ||
} | ||
}, | ||
}; |
const { NodeTypes } = require("../ebnf-transform"); | ||
module.exports = { | ||
[NodeTypes.Choice]: current => { | ||
[NodeTypes.Choice]: (current) => { | ||
if (!current.choice) { | ||
return current; | ||
} | ||
const stringChoices = current.choice.map(item => JSON.stringify(item)); | ||
const stringChoices = current.choice.map((item) => JSON.stringify(item)); | ||
const uniqueDirectChoices = current.choice.filter( | ||
@@ -13,7 +13,7 @@ (item, idx) => !(stringChoices.indexOf(JSON.stringify(item)) < idx) | ||
const stringChoicesComments = current.choice.map( | ||
item => (item.group && item.comment ? JSON.stringify(item.group) : null) | ||
const stringChoicesComments = current.choice.map((item) => | ||
item.group && item.comment ? JSON.stringify(item.group) : null | ||
); | ||
const uniqueChoices = uniqueDirectChoices.filter( | ||
item => | ||
(item) => | ||
(!item.comment && | ||
@@ -31,3 +31,3 @@ stringChoicesComments.indexOf(JSON.stringify(item)) === -1) || | ||
return current; | ||
} | ||
}, | ||
}; |
const { NodeTypes } = require("../ebnf-transform"); | ||
module.exports = { | ||
[NodeTypes.Choice]: current => { | ||
[NodeTypes.Choice]: (current) => { | ||
if (!current.choice) { | ||
return current; | ||
} | ||
const hasOptional = current.choice.some(node => node.optional); | ||
const hasOptional = current.choice.some((node) => node.optional); | ||
if (hasOptional) { | ||
@@ -18,8 +18,8 @@ return { | ||
[] | ||
) | ||
} | ||
), | ||
}, | ||
}; | ||
} | ||
return current; | ||
} | ||
}, | ||
}; |
@@ -6,9 +6,9 @@ const { NodeTypes } = require("../ebnf-transform"); | ||
const ungroup = item => (item.group && !item.comment ? item.group : item); | ||
const ungroup = (item) => (item.group && !item.comment ? item.group : item); | ||
module.exports = { | ||
[NodeTypes.Sequence]: current => { | ||
[NodeTypes.Sequence]: (current) => { | ||
if (!current.sequence) return current; | ||
const hasRepeats = current.sequence.some( | ||
item => item.repetition || (item.group && item.group.repetition) | ||
(item) => item.repetition || (item.group && item.group.repetition) | ||
); | ||
@@ -26,3 +26,3 @@ if (!hasRepeats) return current; | ||
repetition: ungroup(lastElem), | ||
skippable: false | ||
skippable: false, | ||
}; | ||
@@ -60,3 +60,3 @@ } | ||
repetition: { sequence: matches.reverse() }, | ||
skippable: false | ||
skippable: false, | ||
}; | ||
@@ -98,9 +98,8 @@ | ||
// pass 1: unpack comments | ||
.map( | ||
item => | ||
item.comment && item.group && !item.group.optional | ||
? item.before | ||
? [{ comment: item.comment }, item.group] | ||
: [item.group, { comment: item.comment }] | ||
: [item] | ||
.map((item) => | ||
item.comment && item.group && !item.group.optional | ||
? item.before | ||
? [{ comment: item.comment }, item.group] | ||
: [item.group, { comment: item.comment }] | ||
: [item] | ||
) | ||
@@ -111,4 +110,4 @@ .reduce((acc, item) => acc.concat(item), []) | ||
.filter(vacuumResults) | ||
.map(elem => (elem.sequence ? elem.sequence : [elem])) | ||
.reduce((acc, elem) => acc.concat(elem), []) | ||
.map((elem) => (elem.sequence ? elem.sequence : [elem])) | ||
.reduce((acc, elem) => acc.concat(elem), []), | ||
}; | ||
@@ -122,3 +121,3 @@ if (equalElements(optimizedSequence, current)) { | ||
: optimizedSequence; | ||
} | ||
}, | ||
}; |
@@ -13,5 +13,5 @@ const { NodeTypes } = require("../ebnf-transform"); | ||
}, | ||
[NodeTypes.Sequence]: current => { | ||
[NodeTypes.Sequence]: (current) => { | ||
if (!current.sequence) return current; | ||
const hasSubSequence = current.sequence.some(node => node.sequence); | ||
const hasSubSequence = current.sequence.some((node) => node.sequence); | ||
if (hasSubSequence) { | ||
@@ -24,3 +24,3 @@ return { | ||
[] | ||
) | ||
), | ||
}; | ||
@@ -33,4 +33,4 @@ } | ||
}, | ||
[NodeTypes.Choice]: current => { | ||
const hasSubChoice = current.choice.some(node => node.choice); | ||
[NodeTypes.Choice]: (current) => { | ||
const hasSubChoice = current.choice.some((node) => node.choice); | ||
if (hasSubChoice) { | ||
@@ -43,7 +43,7 @@ return { | ||
[] | ||
) | ||
), | ||
}; | ||
} | ||
return current; | ||
} | ||
}, | ||
}; |
const { NodeTypes } = require("../ebnf-transform"); | ||
module.exports = { | ||
[NodeTypes.Optional]: current => { | ||
[NodeTypes.Optional]: (current) => { | ||
if (current.optional.optional) { | ||
@@ -12,3 +12,3 @@ return current.optional; | ||
return current; | ||
} | ||
}, | ||
}; |
@@ -1,2 +0,2 @@ | ||
const traverse = classifier => travelers => transformers => { | ||
const traverse = (classifier) => (travelers) => (transformers) => { | ||
const transform = (node, initialResult = node, parents = []) => { | ||
@@ -9,3 +9,3 @@ const nodeType = classifier(node); | ||
const updatedNode = traveler | ||
? traveler(node, aNext => { | ||
? traveler(node, (aNext) => { | ||
const result = transform(aNext, aNext, [node, ...parents]); | ||
@@ -27,4 +27,4 @@ if (result !== aNext) { | ||
: transformer[nodeType] | ||
? transformer[nodeType](res, node, parents) | ||
: res, | ||
? transformer[nodeType](res, node, parents) | ||
: res, | ||
startResult | ||
@@ -31,0 +31,0 @@ ); |
@@ -18,7 +18,7 @@ const { travelers, identifyNode, NodeTypes } = require("./ast/ebnf-transform"); | ||
stack, | ||
terminal | ||
terminal, | ||
} = require("utf-railroad"); | ||
const ExtraNodeTypes = { | ||
Skip: 100 | ||
Skip: 100, | ||
}; | ||
@@ -28,6 +28,6 @@ | ||
const identity = x => x; | ||
const dot = f => g => x => f(g(x)); | ||
const identity = (x) => x; | ||
const dot = (f) => (g) => (x) => f(g(x)); | ||
const diagramTraverse = traverse(node => { | ||
const diagramTraverse = traverse((node) => { | ||
const result = identifyNode(node); | ||
@@ -41,21 +41,21 @@ if (result !== undefined) return result; | ||
repetition: next(node.repetition), | ||
...(node.repeater && { repeater: next(node.repeater) }) | ||
}) | ||
...(node.repeater && { repeater: next(node.repeater) }), | ||
}), | ||
}); | ||
const baseDiagramRendering = { | ||
[NodeTypes.Production]: node => diagram(node.definition, node.complex), | ||
[NodeTypes.ExceptNonTerminal]: node => | ||
[NodeTypes.Production]: (node) => diagram(node.definition, node.complex), | ||
[NodeTypes.ExceptNonTerminal]: (node) => | ||
nonTerminal(`${node.include} - ${node.exceptNonTerminal}`), | ||
[NodeTypes.ExceptTerminal]: node => | ||
[NodeTypes.ExceptTerminal]: (node) => | ||
nonTerminal(`${node.include} - ${node.exceptTerminal}`), | ||
[NodeTypes.Terminal]: node => terminal(node.terminal), | ||
[NodeTypes.NonTerminal]: node => nonTerminal(node.nonTerminal), | ||
[NodeTypes.Special]: node => { | ||
[NodeTypes.Terminal]: (node) => terminal(node.terminal), | ||
[NodeTypes.NonTerminal]: (node) => nonTerminal(node.nonTerminal), | ||
[NodeTypes.Special]: (node) => { | ||
const sequence = nonTerminal(" " + node.specialSequence + " "); | ||
return sequence; | ||
}, | ||
[NodeTypes.Choice]: node => choice(node.choice, 0), | ||
[NodeTypes.Sequence]: node => sequence(node.sequence), | ||
[NodeTypes.Comment]: node => commentWithLine(node.comment), | ||
[NodeTypes.Choice]: (node) => choice(node.choice, 0), | ||
[NodeTypes.Sequence]: (node) => sequence(node.sequence), | ||
[NodeTypes.Comment]: (node) => commentWithLine(node.comment), | ||
[NodeTypes.Group]: (node, production) => { | ||
@@ -74,5 +74,5 @@ if (node.comment) { | ||
}, | ||
[NodeTypes.Optional]: node => optional(node.optional), | ||
[NodeTypes.Optional]: (node) => optional(node.optional), | ||
[ExtraNodeTypes.Skip]: () => skip(), | ||
[NodeTypes.Repetition]: node => { | ||
[NodeTypes.Repetition]: (node) => { | ||
if (node.skippable === true) { | ||
@@ -89,8 +89,8 @@ return choice([skip(), repeater(node.repetition)], 1); | ||
} | ||
} | ||
}, | ||
}; | ||
const maxChoiceLength = max => ({ | ||
[NodeTypes.Choice]: node => { | ||
const makeChoice = items => choice(items, 0); | ||
const maxChoiceLength = (max) => ({ | ||
[NodeTypes.Choice]: (node) => { | ||
const makeChoice = (items) => choice(items, 0); | ||
const choiceOptions = node.items; | ||
@@ -106,7 +106,7 @@ const choiceLists = []; | ||
: choiceLists[0]; | ||
} | ||
}, | ||
}); | ||
const optimizeSequenceLength = { | ||
[NodeTypes.Sequence]: node => { | ||
[NodeTypes.Sequence]: (node) => { | ||
if (node.width > 450) { | ||
@@ -136,7 +136,7 @@ const subSequences = node.items | ||
) | ||
.filter(array => array.length > 0); | ||
return stack(subSequences.map(subSequence => sequence(subSequence))); | ||
.filter((array) => array.length > 0); | ||
return stack(subSequences.map((subSequence) => sequence(subSequence))); | ||
} | ||
return node; | ||
} | ||
}, | ||
}; | ||
@@ -163,3 +163,3 @@ | ||
const nested = ast.find( | ||
item => item.identifier === production.nonTerminal | ||
(item) => item.identifier === production.nonTerminal | ||
); | ||
@@ -175,4 +175,4 @@ if (!expand || !nested) { | ||
); | ||
} | ||
} | ||
}, | ||
}, | ||
].filter(Boolean) | ||
@@ -184,3 +184,3 @@ ) | ||
...production, | ||
complex: options.complex | ||
complex: options.complex, | ||
}); | ||
@@ -192,3 +192,3 @@ | ||
module.exports = { | ||
createDiagram | ||
createDiagram, | ||
}; |
@@ -5,3 +5,2 @@ const { travelers, identifyNode, NodeTypes } = require("./ast/ebnf-transform"); | ||
const { | ||
Choice, | ||
Comment, | ||
@@ -16,13 +15,19 @@ ComplexDiagram, | ||
Stack, | ||
Terminal | ||
Terminal, | ||
} = require("railroad-diagrams"); | ||
const { CommentWithLine, Group } = require("./extra-diagram-elements"); | ||
const { CommentWithLine, Group, Choice } = require("./extra-diagram-elements"); | ||
const dasherize = str => str.replace(/\s+/g, "-"); | ||
/** | ||
* Replaces one or multiple spaces with a dash | ||
* | ||
* @param {string} str | ||
* @returns {string} | ||
*/ | ||
const dasherize = (str) => str.replace(/\s+/g, "-"); | ||
const ExtraNodeTypes = { | ||
Skip: 100 | ||
Skip: 100, | ||
}; | ||
const diagramTraverse = traverse(node => { | ||
const diagramTraverse = traverse((node) => { | ||
const result = identifyNode(node); | ||
@@ -36,19 +41,19 @@ if (result !== undefined) return result; | ||
repetition: next(node.repetition), | ||
...(node.repeater && { repeater: next(node.repeater) }) | ||
}) | ||
...(node.repeater && { repeater: next(node.repeater) }), | ||
}), | ||
}); | ||
const baseDiagramRendering = { | ||
[NodeTypes.Production]: node => | ||
[NodeTypes.Production]: (node) => | ||
node.complex ? ComplexDiagram(node.definition) : Diagram(node.definition), | ||
[NodeTypes.ExceptNonTerminal]: node => | ||
[NodeTypes.ExceptNonTerminal]: (node) => | ||
NonTerminal(`${node.include} - ${node.exceptNonTerminal}`, {}), | ||
[NodeTypes.ExceptTerminal]: node => | ||
[NodeTypes.ExceptTerminal]: (node) => | ||
NonTerminal(`${node.include} - ${node.exceptTerminal}`, {}), | ||
[NodeTypes.Terminal]: node => Terminal(node.terminal), | ||
[NodeTypes.NonTerminal]: node => | ||
[NodeTypes.Terminal]: (node) => Terminal(node.terminal), | ||
[NodeTypes.NonTerminal]: (node) => | ||
NonTerminal(node.nonTerminal, { | ||
href: `#${dasherize(node.nonTerminal)}` | ||
href: `#${dasherize(node.nonTerminal)}`, | ||
}), | ||
[NodeTypes.Special]: node => { | ||
[NodeTypes.Special]: (node) => { | ||
const sequence = NonTerminal(" " + node.specialSequence + " ", {}); | ||
@@ -58,5 +63,5 @@ sequence.attrs.class = "special-sequence"; | ||
}, | ||
[NodeTypes.Choice]: node => Choice(0, ...node.choice), | ||
[NodeTypes.Sequence]: node => Sequence(...node.sequence), | ||
[NodeTypes.Comment]: node => CommentWithLine(node.comment, {}), | ||
[NodeTypes.Choice]: (node) => Choice(0, ...node.choice), | ||
[NodeTypes.Sequence]: (node) => Sequence(...node.sequence), | ||
[NodeTypes.Comment]: (node) => CommentWithLine(node.comment, {}), | ||
[NodeTypes.Group]: (node, production) => { | ||
@@ -79,5 +84,5 @@ if (node.comment) { | ||
}, | ||
[NodeTypes.Optional]: node => Choice(1, Skip(), node.optional), | ||
[NodeTypes.Optional]: (node) => Choice(1, Skip(), node.optional), | ||
[ExtraNodeTypes.Skip]: () => Skip(), | ||
[NodeTypes.Repetition]: node => { | ||
[NodeTypes.Repetition]: (node) => { | ||
if (node.skippable === true) { | ||
@@ -94,8 +99,8 @@ return Choice(1, Skip(), OneOrMore(node.repetition)); | ||
} | ||
} | ||
}, | ||
}; | ||
const maxChoiceLength = max => ({ | ||
[NodeTypes.Choice]: node => { | ||
const makeChoice = items => new Choice(0, items); | ||
const maxChoiceLength = (max) => ({ | ||
[NodeTypes.Choice]: (node) => { | ||
const makeChoice = (items) => new Choice(0, items); | ||
const choiceOptions = node.items; | ||
@@ -111,7 +116,7 @@ const choiceLists = []; | ||
: choiceLists[0]; | ||
} | ||
}, | ||
}); | ||
const optimizeSequenceLength = { | ||
[NodeTypes.Sequence]: node => { | ||
[NodeTypes.Sequence]: (node) => { | ||
if (node.width > 450) { | ||
@@ -141,9 +146,12 @@ const subSequences = node.items | ||
) | ||
.filter(array => array.length > 0); | ||
.filter((array) => array.length > 0); | ||
if (subSequences.length === 1) { | ||
return Sequence(...subSequences[0]); | ||
} | ||
return Stack( | ||
...subSequences.map(subSequence => Sequence(...subSequence)) | ||
...subSequences.map((subSequence) => Sequence(...subSequence)) | ||
); | ||
} | ||
return node; | ||
} | ||
}, | ||
}; | ||
@@ -153,4 +161,4 @@ | ||
const identity = x => x; | ||
const dot = f => g => x => f(g(x)); | ||
const identity = (x) => x; | ||
const dot = (f) => (g) => (x) => f(g(x)); | ||
@@ -169,3 +177,3 @@ const createDiagram = (production, metadata, ast, options) => { | ||
options.overview && { | ||
[NodeTypes.NonTerminal]: node => { | ||
[NodeTypes.NonTerminal]: (node) => { | ||
const expand = | ||
@@ -176,3 +184,3 @@ !expanded.includes(node.text) && | ||
const nested = ast.find(item => item.identifier === node.text); | ||
const nested = ast.find((item) => item.identifier === node.text); | ||
if (!expand || !nested) { | ||
@@ -187,4 +195,4 @@ return node; | ||
); | ||
} | ||
} | ||
}, | ||
}, | ||
].filter(Boolean) | ||
@@ -196,3 +204,3 @@ ) | ||
...production, | ||
complex: options.complex | ||
complex: options.complex, | ||
}); | ||
@@ -206,3 +214,3 @@ | ||
module.exports = { | ||
createDiagram | ||
createDiagram, | ||
}; |
@@ -7,6 +7,6 @@ const program = require("commander"); | ||
const { | ||
createDocumentation: createHtmlDocumentation | ||
createDocumentation: createHtmlDocumentation, | ||
} = require("./html-report-builder"); | ||
const { | ||
createDocumentation: createMarkdownDocumentation | ||
createDocumentation: createMarkdownDocumentation, | ||
} = require("./markdown-report-builder"); | ||
@@ -64,9 +64,10 @@ const { validateEbnf } = require("./validate"); | ||
const diagramWrap = program.diagramWrap; | ||
const output = text => allowOutput && process.stdout.write(text + "\n"); | ||
const outputError = text => allowOutput && process.stderr.write(text + "\n"); | ||
const errLocation = struct => | ||
const output = (text) => allowOutput && process.stdout.write(text + "\n"); | ||
const outputError = (text) => | ||
allowOutput && process.stderr.write(text + "\n"); | ||
const errLocation = (struct) => | ||
struct.pos !== undefined | ||
? `${struct.line}:${struct.pos}` | ||
: `${struct.line}`; | ||
const outputErrorStruct = struct => | ||
const outputErrorStruct = (struct) => | ||
allowOutput && | ||
@@ -81,6 +82,3 @@ process.stderr.write( | ||
const basename = filename | ||
.split(".") | ||
.slice(0, -1) | ||
.join("."); | ||
const basename = filename.split(".").slice(0, -1).join("."); | ||
const defaultOutputFilename = basename + ".html"; | ||
@@ -105,3 +103,3 @@ const documentTitle = program.title || basename; | ||
allowOutput && | ||
warnings.forEach(warning => outputErrorStruct(warning)); | ||
warnings.forEach((warning) => outputErrorStruct(warning)); | ||
@@ -113,3 +111,3 @@ if (program.writeStyle || program.rewrite) { | ||
markup: false, | ||
format: true | ||
format: true, | ||
}); | ||
@@ -127,3 +125,3 @@ await writeFile(filename, prettyOutput, "utf8"); | ||
overviewDiagram, | ||
diagramWrap | ||
diagramWrap, | ||
}); | ||
@@ -140,3 +138,3 @@ await writeFile(targetFilename, report, "utf8"); | ||
overviewDiagram, | ||
diagramWrap | ||
diagramWrap, | ||
}); | ||
@@ -154,5 +152,6 @@ await writeFile(targetFilename, report, "utf8"); | ||
type: "Parse error", | ||
message: `Expected ${expected}, got ${token}` | ||
message: `Expected ${expected}, got ${token}`, | ||
}); | ||
} else { | ||
console.log(e); | ||
outputError(e.message); | ||
@@ -166,3 +165,3 @@ output(""); | ||
module.exports = { | ||
run | ||
run, | ||
}; |
@@ -1,2 +0,2 @@ | ||
const dedent = text => { | ||
const dedent = (text) => { | ||
const lines = text.split("\n"); | ||
@@ -17,3 +17,3 @@ let minimalIndent = Infinity; | ||
.split("\n") | ||
.map(v => v.slice(minimalIndent)) | ||
.map((v) => v.slice(minimalIndent)) | ||
.reduce((r, l) => r + l + "\n", ""); | ||
@@ -23,3 +23,3 @@ }; | ||
module.exports = { | ||
dedent | ||
dedent, | ||
}; |
@@ -1,11 +0,8 @@ | ||
const dasherize = str => str.replace(/\s+/g, "-"); | ||
const dasherize = (str) => str.replace(/\s+/g, "-"); | ||
const sanitize = (str, markup) => | ||
markup | ||
? str | ||
.replace(/&/g, "&") | ||
.replace(/</g, "<") | ||
.replace(/>/g, ">") | ||
? str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") | ||
: str; | ||
const lineIndent = indent => "\n" + " ".repeat(indent); | ||
const lineIndent = (indent) => "\n" + " ".repeat(indent); | ||
@@ -30,3 +27,3 @@ const wrapTag = (tag, attributes, content, markup) => | ||
lineMargin: LINE_MARGIN_LENGTH, | ||
indent: 0 | ||
indent: 0, | ||
}; | ||
@@ -48,3 +45,3 @@ | ||
indent: 1, | ||
rowCount: 1 | ||
rowCount: 1, | ||
}; | ||
@@ -57,3 +54,5 @@ } | ||
const longestChoice = item.choice | ||
.map(choice => productionToEBNF(choice, { format: false, markup: false })) | ||
.map((choice) => | ||
productionToEBNF(choice, { format: false, markup: false }) | ||
) | ||
.reduce((acc, elem) => (acc.length > elem.length ? acc : elem)); | ||
@@ -71,3 +70,3 @@ const padding = longestChoice.length; | ||
padding: true, | ||
indent: options.indent + 1 | ||
indent: options.indent + 1, | ||
}; | ||
@@ -88,7 +87,9 @@ } | ||
...defaultOptions, | ||
...setOptions | ||
...setOptions, | ||
}; | ||
if (Array.isArray(production)) { | ||
return production.map(item => productionToEBNF(item, options)).join("\n\n"); | ||
return production | ||
.map((item) => productionToEBNF(item, options)) | ||
.join("\n\n"); | ||
} | ||
@@ -98,3 +99,3 @@ if (production.identifier) { | ||
...options, | ||
offsetLength: production.identifier.length + 3 | ||
offsetLength: production.identifier.length + 3, | ||
}); | ||
@@ -130,3 +131,3 @@ | ||
class: "ebnf-non-terminal", | ||
href: `#${dasherize(production.nonTerminal)}` | ||
href: `#${dasherize(production.nonTerminal)}`, | ||
}, | ||
@@ -149,3 +150,3 @@ production.nonTerminal, | ||
.map( | ||
elem => | ||
(elem) => | ||
productionToEBNF(elem, { format: false, markup: false }) | ||
@@ -158,3 +159,3 @@ .length | ||
markup: false, | ||
format: false | ||
format: false, | ||
}).length; | ||
@@ -177,3 +178,3 @@ const padding = " ".repeat(Math.max(longestOfColumn - length, 0)); | ||
.split("\n") | ||
.map(line => line.trimEnd()) | ||
.map((line) => line.trimEnd()) | ||
.join("\n") | ||
@@ -183,3 +184,3 @@ ); | ||
return production.choice | ||
.map(choice => productionToEBNF(choice, options)) | ||
.map((choice) => productionToEBNF(choice, options)) | ||
.join(" | "); | ||
@@ -198,5 +199,5 @@ } | ||
production.sequence | ||
.map(element => ({ | ||
.map((element) => ({ | ||
element, | ||
length: calculateMaxLength(element, options.format) | ||
length: calculateMaxLength(element, options.format), | ||
})) | ||
@@ -229,3 +230,3 @@ .map(({ element }, index, list) => { | ||
...options, | ||
offsetLength | ||
offsetLength, | ||
}); | ||
@@ -242,3 +243,3 @@ if (options.format && output.indexOf("\n") !== -1) { | ||
.split("\n") | ||
.map(line => line.trimEnd()) | ||
.map((line) => line.trimEnd()) | ||
.join("\n") | ||
@@ -308,3 +309,3 @@ ); | ||
{ | ||
nonTerminal: production.include | ||
nonTerminal: production.include, | ||
}, | ||
@@ -320,3 +321,3 @@ options | ||
{ | ||
nonTerminal: production.include | ||
nonTerminal: production.include, | ||
}, | ||
@@ -330,3 +331,3 @@ options | ||
module.exports = { | ||
productionToEBNF | ||
productionToEBNF, | ||
}; |
@@ -6,3 +6,4 @@ const { | ||
Comment, | ||
Terminal | ||
Terminal, | ||
DiagramMultiContainer, | ||
} = require("railroad-diagrams"); | ||
@@ -46,11 +47,7 @@ | ||
CommentWithLine.prototype.needsSpace = true; | ||
CommentWithLine.prototype.format = function(x, y, width) { | ||
CommentWithLine.prototype.format = function (x, y, width) { | ||
// Hook up the two sides if this is narrower than its stated width. | ||
var gaps = determineGaps(width, this.width); | ||
Path(x, y) | ||
.h(gaps[0]) | ||
.addTo(this); | ||
Path(x, y) | ||
.right(width) | ||
.addTo(this); | ||
Path(x, y).h(gaps[0]).addTo(this); | ||
Path(x, y).right(width).addTo(this); | ||
Path(x + gaps[0] + this.width, y + this.height) | ||
@@ -108,3 +105,3 @@ .h(gaps[1]) | ||
Group.prototype.needsSpace = true; | ||
Group.prototype.format = function(x, y, width) { | ||
Group.prototype.format = function (x, y, width) { | ||
var gaps = determineGaps(width, this.width); | ||
@@ -122,3 +119,3 @@ new Path(x, y).h(gaps[0]).addTo(this); | ||
ry: Diagram.ARC_RADIUS, | ||
class: "group-box" | ||
class: "group-box", | ||
}).addTo(this); | ||
@@ -140,5 +137,161 @@ | ||
var Choice = function Choice(normal, items) { | ||
if (!(this instanceof Choice)) | ||
return new Choice(normal, [].slice.call(arguments, 1)); | ||
DiagramMultiContainer.call(this, "g", items); | ||
if (typeof normal !== "number" || normal !== Math.floor(normal)) { | ||
throw new TypeError("The first argument of Choice() must be an integer."); | ||
} else if (normal < 0 || normal >= items.length) { | ||
throw new RangeError( | ||
"The first argument of Choice() must be an index for one of the items." | ||
); | ||
} else { | ||
this.normal = normal; | ||
} | ||
var first = 0; | ||
var last = items.length - 1; | ||
this.width = | ||
Math.max.apply( | ||
null, | ||
this.items.map(function (el) { | ||
return el.width; | ||
}) | ||
) + | ||
Diagram.ARC_RADIUS * 4; | ||
this.height = this.items[normal].height; | ||
this.up = this.items[first].up; | ||
for (var i = first; i < normal; i++) { | ||
let arcs = i == normal + 1 ? Diagram.ARC_RADIUS * 2 : Diagram.ARC_RADIUS; | ||
this.up += Math.max( | ||
arcs, | ||
this.items[i].height + | ||
this.items[i].down + | ||
Diagram.VERTICAL_SEPARATION + | ||
this.items[i + 1].up | ||
); | ||
} | ||
// Fix over the Choice of 'railroad-diagrams': height of the last item had to be added as well. | ||
this.down = this.items[last].down + this.items[last].height; | ||
for (let i = normal + 1; i <= last; i++) { | ||
let arcs = i == normal + 1 ? Diagram.ARC_RADIUS * 2 : Diagram.ARC_RADIUS; | ||
this.down += Math.max( | ||
arcs, | ||
this.items[i - 1].height + | ||
this.items[i - 1].down + | ||
Diagram.VERTICAL_SEPARATION + | ||
this.items[i].up | ||
); | ||
} | ||
this.down -= this.items[normal].height; // already counted in Choice.height | ||
if (Diagram.DEBUG) { | ||
this.attrs["data-updown"] = this.up + " " + this.height + " " + this.down; | ||
this.attrs["data-type"] = "choice"; | ||
} | ||
}; | ||
subclassOf(Choice, DiagramMultiContainer); | ||
Choice.prototype.format = function (x, y, width) { | ||
// Hook up the two sides if this is narrower than its stated width. | ||
var gaps = determineGaps(width, this.width); | ||
Path(x, y).h(gaps[0]).addTo(this); | ||
Path(x + gaps[0] + this.width, y + this.height) | ||
.h(gaps[1]) | ||
.addTo(this); | ||
x += gaps[0]; | ||
var last = this.items.length - 1; | ||
var innerWidth = this.width - Diagram.ARC_RADIUS * 4; | ||
let distanceFromY = 0; | ||
// Do the elements that curve above | ||
for (var i = this.normal - 1; i >= 0; i--) { | ||
var item = this.items[i]; | ||
if (i == this.normal - 1) { | ||
distanceFromY = Math.max( | ||
Diagram.ARC_RADIUS * 2, | ||
this.items[this.normal].up + | ||
Diagram.VERTICAL_SEPARATION + | ||
item.down + | ||
item.height | ||
); | ||
} | ||
Path(x, y) | ||
.arc("se") | ||
.up(distanceFromY - Diagram.ARC_RADIUS * 2) | ||
.arc("wn") | ||
.addTo(this); | ||
item | ||
.format(x + Diagram.ARC_RADIUS * 2, y - distanceFromY, innerWidth) | ||
.addTo(this); | ||
Path( | ||
x + Diagram.ARC_RADIUS * 2 + innerWidth, | ||
y - distanceFromY + item.height | ||
) | ||
.arc("ne") | ||
.down(distanceFromY - item.height + this.height - Diagram.ARC_RADIUS * 2) | ||
.arc("ws") | ||
.addTo(this); | ||
distanceFromY += Math.max( | ||
Diagram.ARC_RADIUS, | ||
item.up + | ||
Diagram.VERTICAL_SEPARATION + | ||
(i == 0 ? 0 : this.items[i - 1].down + this.items[i - 1].height) | ||
); | ||
} | ||
// Do the straight-line path. | ||
Path(x, y) | ||
.right(Diagram.ARC_RADIUS * 2) | ||
.addTo(this); | ||
this.items[this.normal] | ||
.format(x + Diagram.ARC_RADIUS * 2, y, innerWidth) | ||
.addTo(this); | ||
Path(x + Diagram.ARC_RADIUS * 2 + innerWidth, y + this.height) | ||
.right(Diagram.ARC_RADIUS * 2) | ||
.addTo(this); | ||
// Do the elements that curve below | ||
distanceFromY = 0; | ||
for (let i = this.normal + 1; i <= last; i++) { | ||
let item = this.items[i]; | ||
if (i == this.normal + 1) { | ||
distanceFromY = Math.max( | ||
Diagram.ARC_RADIUS * 2, | ||
this.height + | ||
this.items[this.normal].down + | ||
Diagram.VERTICAL_SEPARATION + | ||
item.up | ||
); | ||
} | ||
Path(x, y) | ||
.arc("ne") | ||
.down(distanceFromY - Diagram.ARC_RADIUS * 2) | ||
.arc("ws") | ||
.addTo(this); | ||
item | ||
.format(x + Diagram.ARC_RADIUS * 2, y + distanceFromY, innerWidth) | ||
.addTo(this); | ||
Path( | ||
x + Diagram.ARC_RADIUS * 2 + innerWidth, | ||
y + distanceFromY + item.height | ||
) | ||
.arc("se") | ||
.up(distanceFromY - Diagram.ARC_RADIUS * 2 + item.height - this.height) | ||
.arc("wn") | ||
.addTo(this); | ||
distanceFromY += Math.max( | ||
Diagram.ARC_RADIUS, | ||
item.height + | ||
item.down + | ||
Diagram.VERTICAL_SEPARATION + | ||
(i == last ? 0 : this.items[i + 1].up) | ||
); | ||
} | ||
return this; | ||
}; | ||
module.exports = { | ||
Choice, | ||
CommentWithLine, | ||
Group | ||
Group, | ||
}; |
@@ -7,7 +7,7 @@ const { optimizeText } = require("./structure-optimizer"); | ||
ebnfTemplate, | ||
commentTemplate | ||
commentTemplate, | ||
} = require("./report-html-template"); | ||
const { | ||
searchReferencesFromIdentifier, | ||
searchReferencesToIdentifier | ||
searchReferencesToIdentifier, | ||
} = require("./references"); | ||
@@ -17,3 +17,3 @@ const { | ||
createStructuralToc, | ||
createDefinitionMetadata | ||
createDefinitionMetadata, | ||
} = require("./toc"); | ||
@@ -23,4 +23,4 @@ const { productionToEBNF } = require("./ebnf-builder"); | ||
const dasherize = str => str.replace(/\s+/g, "-"); | ||
const vacuum = htmlContents => htmlContents.replace(/>\s+</g, "><"); | ||
const dasherize = (str) => str.replace(/\s+/g, "-"); | ||
const vacuum = (htmlContents) => htmlContents.replace(/>\s+</g, "><"); | ||
@@ -30,3 +30,3 @@ const createTocStructure = (tocData, metadata) => | ||
.map( | ||
tocNode => | ||
(tocNode) => | ||
`<li${ | ||
@@ -36,4 +36,4 @@ (metadata[tocNode.name] || {}).root | ||
: (metadata[tocNode.name] || {}).common | ||
? ' class="common-node"' | ||
: "" | ||
? ' class="common-node"' | ||
: "" | ||
}><a href="#${dasherize( | ||
@@ -61,3 +61,3 @@ tocNode.name.trim() | ||
const contents = ast | ||
.map(production => { | ||
.map((production) => { | ||
if (production.comment) { | ||
@@ -76,3 +76,3 @@ return commentTemplate(production.comment); | ||
metadata[production.identifier].root && options.overviewDiagram, | ||
complex: outgoingReferences.length > 0 | ||
complex: outgoingReferences.length > 0, | ||
}); | ||
@@ -86,3 +86,3 @@ | ||
markup: true, | ||
format: options.textFormatting | ||
format: options.textFormatting, | ||
} | ||
@@ -92,3 +92,3 @@ ), | ||
referencesTo: outgoingReferences, | ||
diagram: vacuum(diagram) | ||
diagram: vacuum(diagram), | ||
}); | ||
@@ -99,14 +99,14 @@ }) | ||
const alphabetical = createAlphabeticalToc(ast); | ||
const isRoot = item => (metadata[item.name] || {}).root; | ||
const isCommon = item => (metadata[item.name] || {}).common; | ||
const isCharacterSet = item => (metadata[item.name] || {}).characterSet; | ||
const isRoot = (item) => (metadata[item.name] || {}).root; | ||
const isCommon = (item) => (metadata[item.name] || {}).common; | ||
const isCharacterSet = (item) => (metadata[item.name] || {}).characterSet; | ||
const rootItems = alphabetical.filter( | ||
item => isRoot(item) && !isCharacterSet(item) | ||
(item) => isRoot(item) && !isCharacterSet(item) | ||
); | ||
const characterSetItems = alphabetical.filter(item => isCharacterSet(item)); | ||
const characterSetItems = alphabetical.filter((item) => isCharacterSet(item)); | ||
const commonItems = alphabetical.filter( | ||
item => !isRoot(item) && !isCharacterSet(item) && isCommon(item) | ||
(item) => !isRoot(item) && !isCharacterSet(item) && isCommon(item) | ||
); | ||
const otherItems = alphabetical.filter( | ||
item => !isRoot(item) && !isCommon(item) && !isCharacterSet(item) | ||
(item) => !isRoot(item) && !isCommon(item) && !isCharacterSet(item) | ||
); | ||
@@ -124,4 +124,4 @@ const hierarchicalToc = createTocStructure(structuralToc, metadata); | ||
characterSets: createTocStructure(characterSetItems, metadata), | ||
other: createTocStructure(otherItems, metadata) | ||
} | ||
other: createTocStructure(otherItems, metadata), | ||
}, | ||
}); | ||
@@ -132,3 +132,3 @@ return options.full !== false | ||
head: `<style type="text/css">${documentStyle()}</style>`, | ||
title: options.title | ||
title: options.title, | ||
}) | ||
@@ -140,3 +140,3 @@ : htmlContent; | ||
createDocumentation, | ||
documentStyle | ||
documentStyle, | ||
}; |
const { parse } = require("./ebnf-parser"); | ||
const { createDocumentation, documentStyle } = require("./html-report-builder"); | ||
const { | ||
createDocumentation: createMarkdownDocumentation | ||
createDocumentation: createMarkdownDocumentation, | ||
} = require("./markdown-report-builder"); | ||
@@ -11,6 +11,6 @@ const { validateEbnf } = require("./validate"); | ||
searchReferencesFromIdentifier, | ||
searchReferencesToIdentifier | ||
searchReferencesToIdentifier, | ||
} = require("./references"); | ||
const improveErrors = parser => input => { | ||
const improveErrors = (parser) => (input) => { | ||
try { | ||
@@ -26,3 +26,3 @@ return parser(input); | ||
line: e.hash.line + 1, | ||
pos: e.hash.loc.last_column + 1 | ||
pos: e.hash.loc.last_column + 1, | ||
}; | ||
@@ -43,3 +43,3 @@ } | ||
searchReferencesFromIdentifier, | ||
searchReferencesToIdentifier | ||
searchReferencesToIdentifier, | ||
}; |
@@ -9,3 +9,3 @@ const { searchReferencesFromIdentifier } = require("./references"); | ||
const dedent = text => { | ||
const dedent = (text) => { | ||
const lines = text.split("\n"); | ||
@@ -16,3 +16,3 @@ const minimalIndentation = lines.reduce((acc, line) => { | ||
}, Infinity); | ||
return lines.map(line => line.slice(minimalIndentation)).join("\n"); | ||
return lines.map((line) => line.slice(minimalIndentation)).join("\n"); | ||
}; | ||
@@ -28,3 +28,3 @@ | ||
const contents = ast | ||
.map(production => { | ||
.map((production) => { | ||
if (production.comment) { | ||
@@ -40,3 +40,3 @@ return dedent(production.comment); | ||
{ | ||
format: options.textFormatting | ||
format: options.textFormatting, | ||
} | ||
@@ -49,7 +49,7 @@ ); | ||
metadata[production.identifier].root && options.overviewDiagram, | ||
complex: outgoingReferences.length > 0 | ||
complex: outgoingReferences.length > 0, | ||
}) | ||
) | ||
.split("\n") | ||
.map(line => line.trimRight()) | ||
.map((line) => line.trimRight()) | ||
.join("\n"); | ||
@@ -67,3 +67,3 @@ | ||
module.exports = { | ||
createDocumentation | ||
createDocumentation, | ||
}; |
@@ -1,2 +0,2 @@ | ||
const getReferences = production => { | ||
const getReferences = (production) => { | ||
if (production.definition) { | ||
@@ -13,3 +13,3 @@ return getReferences(production.definition); | ||
return production.choice | ||
.map(item => getReferences(item)) | ||
.map((item) => getReferences(item)) | ||
.reduce((acc, item) => acc.concat(item), []) | ||
@@ -20,3 +20,3 @@ .filter(Boolean); | ||
return production.sequence | ||
.map(item => getReferences(item)) | ||
.map((item) => getReferences(item)) | ||
.reduce((acc, item) => acc.concat(item), []) | ||
@@ -45,11 +45,11 @@ .filter(Boolean); | ||
productions | ||
.filter(production => | ||
getReferences(production).some(ref => ref === identifier) | ||
.filter((production) => | ||
getReferences(production).some((ref) => ref === identifier) | ||
) | ||
.map(production => production.identifier); | ||
.map((production) => production.identifier); | ||
const searchReferencesFromIdentifier = (identifier, ast) => | ||
ast | ||
.filter(production => production.identifier === identifier) | ||
.map(production => getReferences(production)) | ||
.filter((production) => production.identifier === identifier) | ||
.map((production) => getReferences(production)) | ||
.reduce((acc, item) => acc.concat(item), []) | ||
@@ -62,3 +62,3 @@ .filter(Boolean) | ||
searchReferencesFromIdentifier, | ||
searchReferencesToIdentifier | ||
searchReferencesToIdentifier, | ||
}; |
@@ -7,3 +7,3 @@ const { Converter } = require("showdown"); | ||
tasklists: true, | ||
tables: true | ||
tables: true, | ||
}); | ||
@@ -29,3 +29,3 @@ | ||
const date = new Date(); | ||
const pad = number => (number < 10 ? "0" + number : number); | ||
const pad = (number) => (number < 10 ? "0" + number : number); | ||
@@ -68,15 +68,15 @@ return `${date.getUTCFullYear()}-${pad(date.getUTCMonth() + 1)}-${pad( | ||
title: singleRoot ? "Root element" : "Root elements", | ||
content: toc.roots | ||
content: toc.roots, | ||
})} | ||
${navigation({ | ||
title: "Quick navigation", | ||
content: toc.other | ||
content: toc.other, | ||
})} | ||
${navigation({ | ||
title: "Common elements", | ||
content: toc.common | ||
content: toc.common, | ||
})} | ||
${navigation({ | ||
title: "Character sets", | ||
content: toc.characterSets | ||
content: toc.characterSets, | ||
})} | ||
@@ -450,3 +450,3 @@ </nav> | ||
const dasherize = str => str.replace(/\s+/g, "-"); | ||
const dasherize = (str) => str.replace(/\s+/g, "-"); | ||
@@ -457,9 +457,9 @@ const referencesTemplate = (identifier, references) => | ||
${references | ||
.map( | ||
reference => | ||
`<li><a href="#${dasherize( | ||
reference.trim() | ||
)}">${reference.trim()}</a></li>` | ||
) | ||
.join("")} | ||
.map( | ||
(reference) => | ||
`<li><a href="#${dasherize( | ||
reference.trim() | ||
)}">${reference.trim()}</a></li>` | ||
) | ||
.join("")} | ||
</ul>`; | ||
@@ -471,9 +471,9 @@ | ||
${references | ||
.map( | ||
reference => | ||
`<li><a href="#${dasherize( | ||
reference.trim() | ||
)}">${reference.trim()}</a></li>` | ||
) | ||
.join("")} | ||
.map( | ||
(reference) => | ||
`<li><a href="#${dasherize( | ||
reference.trim() | ||
)}">${reference.trim()}</a></li>` | ||
) | ||
.join("")} | ||
</ul>`; | ||
@@ -486,3 +486,3 @@ | ||
referencedBy, | ||
referencesTo | ||
referencesTo, | ||
}) => | ||
@@ -492,12 +492,14 @@ `<section> | ||
<div class="diagram-container">${diagram}</div> | ||
<code class="ebnf">${ebnf}</code>${(referencedBy.length > 0 | ||
? "\n " + referencesTemplate(identifier, referencedBy) | ||
: "") + | ||
<code class="ebnf">${ebnf}</code>${ | ||
(referencedBy.length > 0 | ||
? "\n " + referencesTemplate(identifier, referencedBy) | ||
: "") + | ||
(referencesTo.length > 0 | ||
? "\n " + referencesToTemplate(identifier, referencesTo) | ||
: "")} | ||
: "") | ||
} | ||
</section> | ||
`; | ||
const commentTemplate = comment => converter.makeHtml(dedent(comment)); | ||
const commentTemplate = (comment) => converter.makeHtml(dedent(comment)); | ||
@@ -509,3 +511,3 @@ module.exports = { | ||
ebnfTemplate, | ||
commentTemplate | ||
commentTemplate, | ||
}; |
@@ -17,3 +17,3 @@ const { ebnfOptimizer } = require("./ast/ebnf-transform"); | ||
repetition, | ||
choiceClustering | ||
choiceClustering, | ||
]); | ||
@@ -25,3 +25,3 @@ | ||
unwrapOptional, | ||
optionalChoices | ||
optionalChoices, | ||
]); | ||
@@ -31,3 +31,3 @@ | ||
optimizeAST, | ||
optimizeText | ||
optimizeText, | ||
}; |
const { | ||
searchReferencesFromIdentifier, | ||
searchReferencesToIdentifier | ||
searchReferencesToIdentifier, | ||
} = require("./references"); | ||
const createAlphabeticalToc = ast => | ||
const createAlphabeticalToc = (ast) => | ||
ast | ||
.filter(production => production.identifier) | ||
.map(production => production.identifier) | ||
.filter((production) => production.identifier) | ||
.map((production) => production.identifier) | ||
.reduce((acc, item) => acc.concat(item), []) | ||
.filter((item, index, list) => list.indexOf(item) === index) | ||
.sort() | ||
.map(node => ({ name: node })); | ||
.map((node) => ({ name: node })); | ||
const isCharacterSet = production => { | ||
const isCharacterSet = (production) => { | ||
const rootChoice = production.definition && production.definition.choice; | ||
@@ -20,3 +20,3 @@ if (!rootChoice) { | ||
} | ||
return rootChoice.every(element => element.terminal); | ||
return rootChoice.every((element) => element.terminal); | ||
}; | ||
@@ -27,3 +27,3 @@ | ||
name: production.identifier, | ||
characterSet: isCharacterSet(production) | ||
characterSet: isCharacterSet(production), | ||
}; | ||
@@ -40,8 +40,8 @@ if (path.includes(leaf.name)) { | ||
// Protect against missing references | ||
.filter(child => | ||
ast.find(production => production.identifier === child) | ||
.filter((child) => | ||
ast.find((production) => production.identifier === child) | ||
) | ||
.map(child => | ||
.map((child) => | ||
createPath( | ||
ast.find(production => production.identifier === child), | ||
ast.find((production) => production.identifier === child), | ||
ast, | ||
@@ -60,4 +60,6 @@ subPath, | ||
rootChoice && | ||
rootChoice.every(element => element.terminal || element.nonTerminal) && | ||
children.every(child => child.characterSet) | ||
rootChoice.every( | ||
(element) => element.terminal || element.nonTerminal | ||
) && | ||
children.every((child) => child.characterSet) | ||
) { | ||
@@ -72,10 +74,10 @@ leaf.characterSet = true; | ||
const flatList = children => | ||
const flatList = (children) => | ||
children | ||
.map(child => [child.name].concat(flatList(child.children || []))) | ||
.map((child) => [child.name].concat(flatList(child.children || []))) | ||
.reduce((acc, elem) => acc.concat(elem), []); | ||
const createStructuralToc = ast => { | ||
const productions = ast.filter(production => production.identifier); | ||
const declarations = productions.map(production => production.identifier); | ||
const createStructuralToc = (ast) => { | ||
const productions = ast.filter((production) => production.identifier); | ||
const declarations = productions.map((production) => production.identifier); | ||
const cache = {}; | ||
@@ -85,18 +87,18 @@ | ||
.filter( | ||
production => | ||
(production) => | ||
searchReferencesToIdentifier(production.identifier, productions) | ||
.length === 0 | ||
) | ||
.map(production => createPath(production, productions, [], cache)); | ||
.map((production) => createPath(production, productions, [], cache)); | ||
const recursiveTrees = productions | ||
.map(production => createPath(production, productions, [], cache)) | ||
.map((production) => createPath(production, productions, [], cache)) | ||
// Check if tree is recursive | ||
.filter(tree => flatList(tree.children || []).includes(tree.name)) | ||
.filter((tree) => flatList(tree.children || []).includes(tree.name)) | ||
// Tree contained in a clean (non-recursive) root? remove. | ||
.filter( | ||
recursiveTree => | ||
(recursiveTree) => | ||
!cleanRoots | ||
.map(root => flatList(root.children || [])) | ||
.some(list => list.includes(recursiveTree.name)) | ||
.map((root) => flatList(root.children || [])) | ||
.some((list) => list.includes(recursiveTree.name)) | ||
) | ||
@@ -109,5 +111,5 @@ // The trees left are now | ||
const indices = flatList(root.children || []) | ||
.filter(node => node !== root.name) | ||
.map(node => list.map(p => p.name).indexOf(node)) | ||
.filter(e => e !== -1); | ||
.filter((node) => node !== root.name) | ||
.map((node) => list.map((p) => p.name).indexOf(node)) | ||
.filter((e) => e !== -1); | ||
const childIndex = Math.min(...indices); | ||
@@ -127,3 +129,3 @@ | ||
const metadata = {}; | ||
structuralToc.forEach(item => { | ||
structuralToc.forEach((item) => { | ||
const data = metadata[item.name] || { counted: 0 }; | ||
@@ -149,3 +151,3 @@ if (level === 0) { | ||
...cData, | ||
counted: cData.counted + data.counted | ||
counted: cData.counted + data.counted, | ||
}; | ||
@@ -167,3 +169,3 @@ }); | ||
createDefinitionMetadata, | ||
createStructuralToc | ||
createStructuralToc, | ||
}; |
const { getReferences } = require("./references"); | ||
const validateEbnf = ast => { | ||
const validateEbnf = (ast) => { | ||
const identifiers = ast.map( | ||
production => production && production.identifier | ||
(production) => production && production.identifier | ||
); | ||
@@ -17,5 +17,3 @@ | ||
type: "Duplicate declaration", | ||
message: `"${declaration.identifier}" already declared on line ${ | ||
ast[firstDeclaration].location | ||
}` | ||
message: `"${declaration.identifier}" already declared on line ${ast[firstDeclaration].location}`, | ||
}; | ||
@@ -26,14 +24,14 @@ }) | ||
const missingReferences = ast | ||
.filter(declaration => declaration.identifier) | ||
.map(declaration => | ||
.filter((declaration) => declaration.identifier) | ||
.map((declaration) => | ||
getReferences(declaration) | ||
.filter((item, index, list) => list.indexOf(item) === index) | ||
.filter(reference => !identifiers.includes(reference)) | ||
.map(missingReference => ({ | ||
.filter((reference) => !identifiers.includes(reference)) | ||
.map((missingReference) => ({ | ||
line: declaration.location, | ||
type: "Missing reference", | ||
message: `"${missingReference}" is not declared` | ||
message: `"${missingReference}" is not declared`, | ||
})) | ||
) | ||
.filter(m => m.length > 0) | ||
.filter((m) => m.length > 0) | ||
.reduce((acc, elem) => acc.concat(elem), []); | ||
@@ -46,3 +44,3 @@ return doubleDeclarations | ||
module.exports = { | ||
validateEbnf | ||
validateEbnf, | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3218
112620
29
113
+ Addedprettier@2.8.4(transitive)
- Removedprettier@1.19.1(transitive)
Updatedprettier@2.8.4