1 | "use strict";
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4 | return new (P || (P = Promise))(function (resolve, reject) {
|
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9 | });
|
10 | };
|
11 | Object.defineProperty(exports, "__esModule", { value: true });
|
12 | const Builder_1 = require("./Builder");
|
13 | const utils_1 = require("./utils");
|
14 | const utils_2 = require("./lint/utils");
|
15 | const emd = require("ecmarkdown");
|
16 | function findLabeledSteps(root) {
|
17 | const steps = [];
|
18 | emd.visit(root, {
|
19 | enter(node) {
|
20 | if (node.name === 'ordered-list-item' && node.id != null) {
|
21 | steps.push(node);
|
22 | }
|
23 | },
|
24 | });
|
25 | return steps;
|
26 | }
|
27 |
|
28 | class Algorithm extends Builder_1.default {
|
29 | static enter(context) {
|
30 | return __awaiter(this, void 0, void 0, function* () {
|
31 | context.inAlg = true;
|
32 | const { spec, node, clauseStack } = context;
|
33 | const innerHTML = node.innerHTML;
|
34 | let emdTree;
|
35 | if ('ecmarkdownTree' in node) {
|
36 | emdTree = node.ecmarkdownTree;
|
37 | }
|
38 | else {
|
39 | try {
|
40 | emdTree = emd.parseAlgorithm(innerHTML);
|
41 | }
|
42 | catch (e) {
|
43 | utils_1.warnEmdFailure(spec.warn, node, e);
|
44 | }
|
45 | }
|
46 | if (emdTree == null) {
|
47 | node.innerHTML = utils_1.wrapEmdFailure(innerHTML);
|
48 | return;
|
49 | }
|
50 | if (spec.opts.lintSpec && spec.locate(node) != null && !node.hasAttribute('example')) {
|
51 | const clause = clauseStack[clauseStack.length - 1];
|
52 | const namespace = clause ? clause.namespace : spec.namespace;
|
53 | const nonterminals = utils_2.collectNonterminalsFromEmd(emdTree).map(({ name, loc }) => ({
|
54 | name,
|
55 | loc,
|
56 | node,
|
57 | namespace,
|
58 | }));
|
59 | spec._ntStringRefs = spec._ntStringRefs.concat(nonterminals);
|
60 | }
|
61 | const rawHtml = emd.emit(emdTree);
|
62 |
|
63 | const html = rawHtml.replace(/((?:\s+|>)[!?])\s+(\w+\s*\()/g, '$1 $2');
|
64 | node.innerHTML = html;
|
65 | const labeledStepEntries = [];
|
66 | const replaces = node.getAttribute('replaces-step');
|
67 | if (replaces) {
|
68 | context.spec.replacementAlgorithms.push({
|
69 | element: node,
|
70 | target: replaces,
|
71 | });
|
72 | context.spec.replacementAlgorithmToContainedLabeledStepEntries.set(node, labeledStepEntries);
|
73 | }
|
74 | if (replaces && node.firstElementChild.children.length > 1) {
|
75 | const labeledSteps = findLabeledSteps(emdTree);
|
76 | for (const step of labeledSteps) {
|
77 | const itemSource = innerHTML.slice(step.location.start.offset, step.location.end.offset);
|
78 | const offset = itemSource.match(/^\s*\d+\. \[id="/)[0].length;
|
79 | spec.warn({
|
80 | type: 'contents',
|
81 | ruleId: 'labeled-step-in-replacement',
|
82 | message: 'labeling a step in a replacement algorithm which has multiple top-level steps is unsupported because the resulting step number would be ambiguous',
|
83 | node,
|
84 | nodeRelativeLine: step.location.start.line,
|
85 | nodeRelativeColumn: step.location.start.column + offset,
|
86 | });
|
87 | }
|
88 | }
|
89 | for (const step of node.querySelectorAll('li[id]')) {
|
90 | const entry = {
|
91 | type: 'step',
|
92 | id: step.id,
|
93 | stepNumbers: getStepNumbers(step),
|
94 | };
|
95 | context.spec.biblio.add(entry);
|
96 | if (replaces) {
|
97 |
|
98 | labeledStepEntries.push(entry);
|
99 | context.spec.labeledStepsToBeRectified.add(step.id);
|
100 | }
|
101 | }
|
102 | });
|
103 | }
|
104 | static exit(context) {
|
105 | context.inAlg = false;
|
106 | }
|
107 | }
|
108 | exports.default = Algorithm;
|
109 | Algorithm.elements = ['EMU-ALG'];
|
110 | function getStepNumbers(item) {
|
111 | var _a;
|
112 | const { indexOf } = Array.prototype;
|
113 | const counts = [];
|
114 | while (((_a = item.parentElement) === null || _a === void 0 ? void 0 : _a.tagName) === 'OL') {
|
115 | counts.unshift(1 + indexOf.call(item.parentElement.children, item));
|
116 | item = item.parentElement.parentElement;
|
117 | }
|
118 | return counts;
|
119 | }
|