UNPKG

litvis-integration-mume

Version:

Enables litvis functionality in mume and markdown-preview-enhanced

143 lines 6.19 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.postEnhanceWithLitvis = void 0; const cheerio_1 = __importDefault(require("cheerio")); const html_entities_1 = require("html-entities"); const litvis_1 = require("litvis"); const lodash_1 = __importDefault(require("lodash")); const findOrFilter = ($, func, selector) => { const cheerioSelectorParts = []; if (selector) { cheerioSelectorParts.push(`[ns-role="label"]`); cheerioSelectorParts.push(`[ns-label-name="${selector.label}"]`); if (selector.kind) { cheerioSelectorParts.push(`[ns-label-kind="${selector.kind}"]`); } } let $result = func(cheerioSelectorParts.join("")); if (selector.trimmedContent) { $result = $result.filter((i, element) => $(element).text().trim() === selector.trimmedContent); } return $result; }; const find = ($, $where, selector) => { return findOrFilter($, $where.find.bind($where), selector); }; const filter = ($, $what, selector) => { return findOrFilter($, $what.filter.bind($what), selector); }; const ruleIsNotFollowed = (position) => { const result = new Error("rule is not followed"); if (position) { result.position = position; } return result; }; const elementPosition = ($el) => { const startColumn = parseInt($el.attr("ns-position-start-column") || "0", 10); const startLine = parseInt($el.attr("ns-position-start-line") || "0", 10); const endColumn = parseInt($el.attr("ns-position-end-column") || "0", 10); const endLine = parseInt($el.attr("ns-position-end-line") || "0", 10); if (Number.isFinite(startColumn) && Number.isFinite(startLine) && Number.isFinite(endColumn) && Number.isFinite(endLine)) { return { start: { column: startColumn, line: startLine, }, end: { column: endColumn, line: endLine, }, }; } return undefined; }; const postEnhanceWithLitvis = (processedNarrative, html, updateLintingReport) => { // hack labels // TODO: replace with a cleaner implementation const postEnhancedHtml = html // block labels .replace(/<p>(<litvis-narrative-schema-label>.*<\/litvis-narrative-schema-label>)<\/p>/g, "$1") // inline labels .replace(/<litvis-narrative-schema-label>(.*)<\/litvis-narrative-schema-label>/g, (outer, inner) => (0, html_entities_1.decode)(inner)); // apply rules const lastFile = lodash_1.default.last(processedNarrative.documents); if (processedNarrative.composedNarrativeSchema) { const $ = cheerio_1.default.load(postEnhancedHtml, { xmlMode: true }); const $root = $.root(); processedNarrative.composedNarrativeSchema.rules.forEach((ruleDefinition) => { const ruleData = ruleDefinition.data; try { const $selection = find($, $root, ruleData.selector); // occurrences if (Number.isFinite(ruleData.minimumOccurrences) && $selection.length < ruleData.minimumOccurrences) { throw ruleIsNotFollowed(); } if (Number.isFinite(ruleData.maximumOccurrences) && $selection.length > ruleData.maximumOccurrences) { throw ruleIsNotFollowed(); } // single-element rules $selection.each((i, el) => { const $el = $(el); // children.minimumTrimmedTextLength if (ruleData.children && Number.isFinite(ruleData.children.minimumTrimmedTextLength)) { const trimmedText = $el.text().trim(); if (trimmedText.length < ruleData.children.minimumTrimmedTextLength) { throw ruleIsNotFollowed(elementPosition($el)); } } // followedBy if (ruleData.followedBy && ruleData.followedBy.selector && filter($, $el.next(), ruleData.followedBy.selector).length === 0) { throw ruleIsNotFollowed(elementPosition($el)); } // notFollowedBy if (ruleData.notFollowedBy && ruleData.notFollowedBy.selector && filter($, $el.next(), ruleData.notFollowedBy.selector).length !== 0) { throw ruleIsNotFollowed(elementPosition($el)); } // before if (ruleData.before && ruleData.before.selector && filter($, $el.nextAll(), ruleData.before.selector).length === 0) { throw ruleIsNotFollowed(elementPosition($el)); } // after if (ruleData.after && ruleData.after.selector && filter($, $el.prevAll(), ruleData.after.selector).length !== 0) { throw ruleIsNotFollowed(elementPosition($el)); } }); } catch (e) { if (e.message === "rule is not followed") { lastFile.message(ruleData.description, e.position, "narrative-schema:rule-validation"); } else { // eslint-disable-next-line no-console console.error(e); } } }); } // update linting report if (updateLintingReport) { updateLintingReport((0, litvis_1.listNarrativeFiles)(processedNarrative)); } return postEnhancedHtml; }; exports.postEnhanceWithLitvis = postEnhanceWithLitvis; //# sourceMappingURL=postEnhanceWithLitvis.js.map