Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ebnf2railroad

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ebnf2railroad - npm Package Compare versions

Comparing version 1.13.0 to 1.13.1

9

package.json
{
"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, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
? str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
: 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,
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc