Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | 5x 5x 5x 5x 5x 5x 5x 4x 4x 4x 4x 5x | /**
* Utility functions for rendering and processing specs.
* This module centralizes helper functions to reduce complexity in index.js.
* These functions handle tasks like path normalization, term lookups, and markdown processing.
*/
const fs = require('fs-extra');
const path = require('node:path');
const { templateTags, paths, whitespace } = require('../../utils/regex-patterns.js');
// Constants used in rendering and processing
const katexRules = ['math_block', 'math_inline'];
const replacerRegex = templateTags.replacer;
const replacerArgsRegex = templateTags.argsSeparator;
const replacers = [
{
test: 'insert',
transform: function (originalMatch, type, path) {
if (!path) return '';
return fs.readFileSync(path, 'utf8');
}
}
];
/**
* Creates a script element containing XTref data for embedding in HTML.
* Tests if xtrefs-data.js exists; if not, returns an empty string.
* @returns {string} The script element or empty string.
*/
function createScriptElementWithXTrefDataForEmbeddingInHtml() {
const inputPath = path.join('.cache', 'xtrefs-data.js');
let xtrefsData = '';
if (fs.existsSync(inputPath)) {
xtrefsData = '<script>' + fs.readFileSync(inputPath, 'utf8') + '</script>';
}
return xtrefsData;
}
/**
* Looks up an xref term from the allXTrefs data.
* @param {string} externalSpec - The external spec identifier.
* @param {string} termName - The term name to look up.
* @returns {Object|null} The term object if found, null otherwise.
*/
function lookupXrefTerm(externalSpec, termName) {
try {
const xtrefsPath = path.join('.cache', 'xtrefs-data.json');
Eif (!fs.existsSync(xtrefsPath)) {
return null;
}
const allXTrefs = fs.readJsonSync(xtrefsPath);
if (!allXTrefs || !allXTrefs.xtrefs) {
return null;
}
const termKey = termName.replace(whitespace.oneOrMore, '-').toLowerCase();
const foundTerm = allXTrefs.xtrefs.find(xtref =>
xtref.externalSpec === externalSpec &&
xtref.term === termKey &&
xtref.source === 'xref'
);
return foundTerm || null;
} catch (error) {
console.warn(`Error looking up xref term ${externalSpec}:${termName}:`, error.message);
return null;
}
}
/**
* Processes custom tag patterns in markdown content and applies transformation functions.
* Scans for patterns like [[tref:spec,term]] and replaces them with HTML equivalents.
* @param {string} doc - The markdown document to process.
* @returns {string} The processed document with tags replaced.
*/
function applyReplacers(doc) {
const { processWithEscapes } = require('../preprocessing/escape-processor.js');
return processWithEscapes(doc, function (content) {
return content.replace(replacerRegex, function (match, type, args) {
let replacer = replacers.find(r => type.trim().match(r.test));
if (replacer) {
let argsArray = args ? args.trim().split(replacerArgsRegex) : [];
return replacer.transform(match, type, ...argsArray);
}
return match;
});
});
}
/**
* Normalizes a path by trimming trailing slashes and adding a leading slash.
* @param {string} path - The path to normalize.
* @returns {string} The normalized path.
*/
function normalizePath(path) {
return path.trim().replace(paths.trailingSlash, '') + '/';
}
/**
* Renders a reference group for a given type.
* @param {string} type - The type of reference group.
* @param {Object} specGroups - The spec groups object.
* @returns {string} The rendered HTML for the reference group.
*/
function renderRefGroup(type, specGroups) {
let group = specGroups[type];
if (!group) return '';
let html = Object.keys(group).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((html, name) => {
let ref = group[name];
return html += `
<dt id="ref:${name}">${name}</dt>
<dd>
<cite><a href="${ref.href}">${ref.title}</a></cite>.
${ref.authors.join('; ')}; ${ref.rawDate}. <span class="reference-status">Status: ${ref.status}</span>.
</dd>
`;
}, '<dl class="reference-list">');
return `\n${html}\n</dl>\n`;
}
/**
* Finds the KaTeX distribution path.
* Uses Node's require.resolve to reliably locate the package across different installation scenarios.
* @returns {string} The path to the KaTeX distribution.
* @throws {Error} If KaTeX distribution cannot be located.
*/
function findKatexDist() {
try {
// Use require.resolve to find the katex package.json, then get the dist folder
// This works with npm link, normal installs, and hoisted dependencies
const katexPackageJsonPath = require.resolve('katex/package.json', {
paths: [__dirname, process.cwd()]
});
const katexDistPath = path.join(path.dirname(katexPackageJsonPath), 'dist');
if (fs.existsSync(katexDistPath)) {
return katexDistPath;
}
} catch (error) {
// Fallback to old behavior if require.resolve fails
}
// Fallback: check common locations
const relpath = "node_modules/katex/dist";
const paths = [
path.join(process.cwd(), relpath),
path.join(__dirname, relpath),
];
for (const abspath of paths) {
if (fs.existsSync(abspath)) {
return abspath;
}
}
throw new Error("katex distribution could not be located");
}
module.exports = {
katexRules,
replacerRegex,
replacerArgsRegex,
replacers,
createScriptElementWithXTrefDataForEmbeddingInHtml,
lookupXrefTerm,
applyReplacers,
normalizePath,
renderRefGroup,
findKatexDist
}; |