UNPKG

@diplodoc/translation

Version:
1,614 lines (1,582 loc) 183 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/experiment/plugins/attrs/markdown-it-attrs/utils.js var require_utils = __commonJS({ "src/experiment/plugins/attrs/markdown-it-attrs/utils.js"(exports2) { "use strict"; exports2.getAttrs = function(str, start, options) { const allowedKeyChars = /[^\t\n\f />"'=]/; const pairSeparator = " "; const keySeparator = "="; const classChar = "."; const idChar = "#"; const attrs2 = []; let key = ""; let value = ""; let parsingKey = true; let valueInsideQuotes = false; for (let i = start + options.leftDelimiter.length; i < str.length; i++) { if (str.slice(i, i + options.rightDelimiter.length) === options.rightDelimiter) { if (key !== "") { attrs2.push([key, value]); } break; } const char_ = str.charAt(i); if (char_ === keySeparator && parsingKey) { parsingKey = false; continue; } if (char_ === classChar && key === "") { if (str.charAt(i + 1) === classChar) { key = "css-module"; i += 1; } else { key = "class"; } parsingKey = false; continue; } if (char_ === idChar && key === "") { key = "id"; parsingKey = false; continue; } if (char_ === '"' && value === "" && !valueInsideQuotes) { valueInsideQuotes = true; continue; } if (char_ === '"' && valueInsideQuotes) { valueInsideQuotes = false; continue; } if (char_ === pairSeparator && !valueInsideQuotes) { if (key === "") { continue; } attrs2.push([key, value]); key = ""; value = ""; parsingKey = true; continue; } if (parsingKey && char_.search(allowedKeyChars) === -1) { continue; } if (parsingKey) { key += char_; continue; } value += char_; } if (options.allowedAttributes && options.allowedAttributes.length) { const allowedAttributes = options.allowedAttributes; return attrs2.filter(function(attrPair) { const attr2 = attrPair[0]; function isAllowedAttribute(allowedAttribute) { return attr2 === allowedAttribute || allowedAttribute instanceof RegExp && allowedAttribute.test(attr2); } return allowedAttributes.some(isAllowedAttribute); }); } return attrs2; }; exports2.addAttrs = function(attrs2, token2) { for (let j = 0, l = attrs2.length; j < l; ++j) { const key = attrs2[j][0]; if (key === "class") { token2.attrJoin("class", attrs2[j][1]); } else if (key === "css-module") { token2.attrJoin("css-module", attrs2[j][1]); } else { token2.attrPush(attrs2[j]); } } return token2; }; exports2.hasDelimiters = function(where, options) { if (!where) { throw new Error('Parameter `where` not passed. Should be "start", "end" or "only".'); } return function(str) { const minCurlyLength = options.leftDelimiter.length + 1 + options.rightDelimiter.length; if (!str || typeof str !== "string" || str.length < minCurlyLength) { return false; } function validCurlyLength(curly) { const isClass = curly.charAt(options.leftDelimiter.length) === "."; const isId = curly.charAt(options.leftDelimiter.length) === "#"; return isClass || isId ? curly.length >= minCurlyLength + 1 : curly.length >= minCurlyLength; } let start, end, slice, nextChar; const rightDelimiterMinimumShift = minCurlyLength - options.rightDelimiter.length; switch (where) { case "start": slice = str.slice(0, options.leftDelimiter.length); start = slice === options.leftDelimiter ? 0 : -1; end = start === -1 ? -1 : str.indexOf(options.rightDelimiter, rightDelimiterMinimumShift); nextChar = str.charAt(end + options.rightDelimiter.length); if (nextChar && options.rightDelimiter.indexOf(nextChar) !== -1) { end = -1; } break; case "end": start = str.lastIndexOf(options.leftDelimiter); end = start === -1 ? -1 : str.indexOf(options.rightDelimiter, start + rightDelimiterMinimumShift); end = end === str.length - options.rightDelimiter.length ? end : -1; break; case "only": slice = str.slice(0, options.leftDelimiter.length); start = slice === options.leftDelimiter ? 0 : -1; slice = str.slice(str.length - options.rightDelimiter.length); end = slice === options.rightDelimiter ? str.length - options.rightDelimiter.length : -1; break; default: throw new Error(`Unexpected case ${where}, expected 'start', 'end' or 'only'`); } return start !== -1 && end !== -1 && validCurlyLength(str.substring(start, end + options.rightDelimiter.length)); }; }; exports2.removeDelimiter = function(str, options) { const start = escapeRegExp(options.leftDelimiter); const end = escapeRegExp(options.rightDelimiter); const curly = new RegExp("[ \\n]?" + start + "[^" + start + end + "]+" + end + "$"); const pos = str.search(curly); return pos !== -1 ? str.slice(0, pos) : str; }; function escapeRegExp(s) { return s.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); } exports2.escapeRegExp = escapeRegExp; exports2.getMatchingOpeningToken = function(tokens, i) { if (tokens[i].type === "softbreak") { return false; } if (tokens[i].nesting === 0) { return tokens[i]; } const level = tokens[i].level; const type2 = tokens[i].type.replace("_close", "_open"); for (; i >= 0; --i) { if (tokens[i].type === type2 && tokens[i].level === level) { return tokens[i]; } } return false; }; var HTML_ESCAPE_TEST_RE = /[&<>"]/; var HTML_ESCAPE_REPLACE_RE = /[&<>"]/g; var HTML_REPLACEMENTS = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }; function replaceUnsafeChar(ch) { return HTML_REPLACEMENTS[ch]; } exports2.escapeHtml = function(str) { if (HTML_ESCAPE_TEST_RE.test(str)) { return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar); } return str; }; } }); // src/experiment/plugins/attrs/markdown-it-attrs/patterns.js var require_patterns = __commonJS({ "src/experiment/plugins/attrs/markdown-it-attrs/patterns.js"(exports2, module2) { "use strict"; var utils = require_utils(); var Token13 = require("markdown-it/lib/token"); module2.exports = (options) => { const __hr = new RegExp( "^ {0,3}[-*_]{3,} ?" + utils.escapeRegExp(options.leftDelimiter) + "[^" + utils.escapeRegExp(options.rightDelimiter) + "]" ); return [ { /** * ```python {.cls} * for i in range(10): * print(i) * ``` */ name: "fenced code blocks", tests: [ { shift: 0, block: true, info: utils.hasDelimiters("end", options) } ], transform: (tokens, i) => { const token2 = tokens[i]; const start = token2.info.lastIndexOf(options.leftDelimiter); const attrs2 = utils.getAttrs(token2.info, start, options); utils.addAttrs(attrs2, token2); token2.info = utils.removeDelimiter(token2.info, options); } }, { /** * bla `click()`{.c} ![](img.png){.d} * * differs from 'inline attributes' as it does * not have a closing tag (nesting: -1) */ name: "inline nesting 0", tests: [ { shift: 0, type: "inline", children: [ { shift: -1, type: (str) => str === "image" || str === "code_inline" }, { shift: 0, type: "text", content: utils.hasDelimiters("start", options), __attrPluginSkip: void 0 } ] } ], transform: (tokens, i, j) => { const token2 = tokens[i].children[j]; const endChar = token2.content.indexOf(options.rightDelimiter); const attrToken = tokens[i].children[j - 1]; const attrs2 = utils.getAttrs(token2.content, 0, options); utils.addAttrs(attrs2, attrToken); if (token2.content.length === endChar + options.rightDelimiter.length) { token2.__attrPluginSkip = true; } else { const startPos = endChar + options.rightDelimiter.length; token2.content = token2.content.slice(startPos); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "inline nesting 0" }; headerToken.content = token2.content.slice(0, startPos); tokens[i].children.splice(j, 0, headerToken); } } }, { /** * | h1 | * | -- | * | c1 | * * {.c} */ name: "tables", tests: [ { // let this token be i, such that for-loop continues at // next token after tokens.splice shift: 0, type: "table_close" }, { shift: 1, type: "paragraph_open" }, { shift: 2, type: "inline", content: utils.hasDelimiters("only", options) } ], transform: (tokens, i) => { const token2 = tokens[i + 2]; const tableOpen = utils.getMatchingOpeningToken(tokens, i); const attrs2 = utils.getAttrs(token2.content, 0, options); utils.addAttrs(attrs2, tableOpen); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "tables" }; headerToken.content = token2.content; tokens.splice(i + 2, 1, headerToken); } }, { /** * *emphasis*{.with attrs=1} */ name: "inline attributes", tests: [ { shift: 0, type: "inline", children: [ { shift: -1, nesting: -1 // closing inline tag, </em>{.a} }, { shift: 0, type: "text", content: utils.hasDelimiters("start", options) } ] } ], transform: (tokens, i, j) => { const token2 = tokens[i].children[j]; const content = token2.content; const attrs2 = utils.getAttrs(content, 0, options); const openingToken = utils.getMatchingOpeningToken(tokens[i].children, j - 1); utils.addAttrs(attrs2, openingToken); const startPos = content.indexOf(options.rightDelimiter) + options.rightDelimiter.length; token2.content = content.slice(startPos); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "inline attributes" }; headerToken.content = content.slice(0, startPos); tokens[i].children.splice(j, 0, headerToken); } }, { /** * - item * {.a} */ name: "list softbreak", tests: [ { shift: -2, type: "list_item_open" }, { shift: 0, type: "inline", children: [ { position: -2, type: "softbreak" }, { position: -1, type: "text", content: utils.hasDelimiters("only", options) } ] } ], transform: (tokens, i, j) => { const token2 = tokens[i].children[j]; const content = token2.content; const attrs2 = utils.getAttrs(content, 0, options); let ii = i - 2; while (tokens[ii - 1] && tokens[ii - 1].type !== "ordered_list_open" && tokens[ii - 1].type !== "bullet_list_open") { ii--; } utils.addAttrs(attrs2, tokens[ii - 1]); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "list softbreak" }; headerToken.content = content; tokens[i].children.splice(j, 1, headerToken); } }, { /** * - nested list * - with double \n * {.a} <-- apply to nested ul * * {.b} <-- apply to root <ul> */ name: "list double softbreak", tests: [ { // let this token be i = 0 so that we can erase // the <p>{.a}</p> tokens below shift: 0, type: (str) => str === "bullet_list_close" || str === "ordered_list_close" }, { shift: 1, type: "paragraph_open" }, { shift: 2, type: "inline", content: utils.hasDelimiters("only", options), children: (arr) => arr.length === 1 }, { shift: 3, type: "paragraph_close" } ], transform: (tokens, i) => { const token2 = tokens[i + 2]; const content = token2.content; const attrs2 = utils.getAttrs(content, 0, options); const openingToken = utils.getMatchingOpeningToken(tokens, i); utils.addAttrs(attrs2, openingToken); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "list double softbreak" }; headerToken.content = content; tokens.splice(i + 2, 1, headerToken); } }, { /** * - end of {.list-item} */ name: "list item end", tests: [ { shift: -2, type: "list_item_open" }, { shift: 0, type: "inline", children: [ { position: -1, type: "text", content: utils.hasDelimiters("end", options) } ] } ], transform: (tokens, i, j) => { const token2 = tokens[i].children[j]; const content = token2.content; const attrs2 = utils.getAttrs( content, content.lastIndexOf(options.leftDelimiter), options ); utils.addAttrs(attrs2, tokens[i - 2]); const startPos = content.lastIndexOf(options.leftDelimiter); token2.content = content.slice(0, startPos); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "end of" }; headerToken.content = content.slice(startPos); tokens[i].children.splice(j + 1, 0, headerToken); } }, { /** * something with softbreak * {.cls} */ name: "\n{.a} softbreak then curly in start", tests: [ { shift: 0, type: "inline", children: [ { position: -2, type: "softbreak" }, { position: -1, type: "text", content: utils.hasDelimiters("only", options) } ] } ], transform: (tokens, i, j) => { const token2 = tokens[i].children[j]; const attrs2 = utils.getAttrs(token2.content, 0, options); let ii = i + 1; while (tokens[ii + 1] && tokens[ii + 1].nesting === -1) { ii++; } const openingToken = utils.getMatchingOpeningToken(tokens, ii); utils.addAttrs(attrs2, openingToken); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "softbreak then curly in start" }; headerToken.content = token2.content; tokens[i].children.splice(j, 1, headerToken); } }, { /** * horizontal rule --- {#id} */ name: "horizontal rule", tests: [ { shift: 0, type: "paragraph_open" }, { shift: 1, type: "inline", children: (arr) => arr.length === 1, content: (str) => str.match(__hr) !== null }, { shift: 2, type: "paragraph_close" } ], transform: (tokens, i) => { const token2 = tokens[i]; token2.type = "hr"; token2.tag = "hr"; token2.nesting = 0; const content = tokens[i + 1].content; const start = content.lastIndexOf(options.leftDelimiter); const attrs2 = utils.getAttrs(content, start, options); utils.addAttrs(attrs2, token2); token2.markup = content; const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "horizontal rule" }; headerToken.content = content; tokens.splice(i + 1, 1, headerToken); } }, { /** * end of {.block} */ name: "end of block", tests: [ { shift: 0, type: "inline", children: [ { position: -1, content: utils.hasDelimiters("end", options), type: (t) => t !== "code_inline" && t !== "math_inline" && t !== "attr_anchor" } ] } ], transform: (tokens, i, j) => { const token2 = tokens[i].children[j]; const content = token2.content; const attrs2 = utils.getAttrs( content, content.lastIndexOf(options.leftDelimiter), options ); let ii = i + 1; while (tokens[ii + 1] && tokens[ii + 1].nesting === -1) { ii++; } const openingToken = utils.getMatchingOpeningToken(tokens, ii); utils.addAttrs(attrs2, openingToken); const startPos = content.lastIndexOf(options.leftDelimiter); token2.content = content.slice(0, startPos); const headerToken = new Token13("attr_anchor", "", 0); headerToken.meta = { rule: "end of block" }; headerToken.content = content.slice(startPos); tokens[i].children.splice(j + 1, 0, headerToken); } } ]; }; } }); // src/experiment/plugins/attrs/markdown-it-attrs/index.js var require_markdown_it_attrs = __commonJS({ "src/experiment/plugins/attrs/markdown-it-attrs/index.js"(exports2, module2) { "use strict"; var patternsConfig = require_patterns(); var defaultOptions = { leftDelimiter: "{", rightDelimiter: "}", allowedAttributes: [] }; module2.exports = function attributes2(md3, options_) { let options = Object.assign({}, defaultOptions); options = Object.assign(options, options_); const patterns = patternsConfig(options); function curlyAttrs(state2) { const tokens = state2.tokens; for (let i = 0; i < tokens.length; i++) { for (let p = 0; p < patterns.length; p++) { const pattern = patterns[p]; let j = null; const match = pattern.tests.every((t) => { const res = test(tokens, i, t); if (res.j !== null) { j = res.j; } return res.match; }); if (match) { pattern.transform(tokens, i, j); if (pattern.name === "inline attributes" || pattern.name === "inline nesting 0") { p--; } } } } } md3.core.ruler.before("linkify", "curly_attributes", curlyAttrs); }; function test(tokens, i, t) { const res = { match: false, j: null // position of child }; const ii = t.shift !== void 0 ? i + t.shift : t.position; if (t.shift !== void 0 && ii < 0) { return res; } const token2 = get3(tokens, ii); if (token2 === void 0) { return res; } for (const key of Object.keys(t)) { if (key === "shift" || key === "position") { continue; } if (token2[key] === void 0) { return res; } if (key === "children" && isArrayOfObjects(t.children)) { if (token2.children.length === 0) { return res; } let match; const childTests = t.children; const children = token2.children; if (childTests.every((tt) => tt.position !== void 0)) { match = childTests.every((tt) => test(children, tt.position, tt).match); if (match) { const j = last2(childTests).position; res.j = j >= 0 ? j : children.length + j; } } else { for (let j = 0; j < children.length; j++) { match = childTests.every((tt) => test(children, j, tt).match); if (match) { res.j = j; break; } } } if (match === false) { return res; } continue; } switch (typeof t[key]) { case "boolean": case "number": case "string": if (token2[key] !== t[key]) { return res; } break; case "function": if (!t[key](token2[key])) { return res; } break; case "object": if (isArrayOfFunctions(t[key])) { const r = t[key].every((tt) => tt(token2[key])); if (r === false) { return res; } break; } // fall through for objects !== arrays of functions default: throw new Error( `Unknown type of pattern test (key: ${key}). Test should be of type boolean, number, string, function or array of functions.` ); } } res.match = true; return res; } function isArrayOfObjects(arr) { return Array.isArray(arr) && arr.length && arr.every((i) => typeof i === "object"); } function isArrayOfFunctions(arr) { return Array.isArray(arr) && arr.length && arr.every((i) => typeof i === "function"); } function get3(arr, n) { return n >= 0 ? arr[n] : arr[arr.length + n]; } function last2(arr) { return arr.slice(-1)[0] || {}; } } }); // src/index.ts var src_exports = {}; __export(src_exports, { CriticalProcessingError: () => CriticalProcessingError, compose: () => compose5, extract: () => extract5, linkRefs: () => linkRefs, unlinkRefs: () => unlinkRefs }); module.exports = __toCommonJS(src_exports); // src/xliff/md-xliff/index.ts var import_markdown_it4 = __toESM(require("markdown-it")); // src/renderer/index.ts var import_renderer = __toESM(require("markdown-it/lib/renderer")); var CustomRendererLifeCycle = /* @__PURE__ */ ((CustomRendererLifeCycle2) => { CustomRendererLifeCycle2[CustomRendererLifeCycle2["BeforeRender"] = 0] = "BeforeRender"; CustomRendererLifeCycle2[CustomRendererLifeCycle2["AfterRender"] = 1] = "AfterRender"; CustomRendererLifeCycle2[CustomRendererLifeCycle2["BeforeInlineRender"] = 2] = "BeforeInlineRender"; CustomRendererLifeCycle2[CustomRendererLifeCycle2["AfterInlineRender"] = 3] = "AfterInlineRender"; return CustomRendererLifeCycle2; })(CustomRendererLifeCycle || {}); function isCustomRendererLifeCycle(cycle) { return Object.keys(CustomRendererLifeCycle).includes( cycle ); } function getMap(tokens, i) { let depth = 0; while (tokens[i]) { const token2 = tokens[i--]; depth += token2.nesting; if (token2.map && depth >= 0) { return token2.map; } } return null; } var CustomRenderer = class extends import_renderer.default { constructor({ hooks: hooks3 = {}, rules: rules4 = {}, state: state2 = {} }, parser) { super(); this.setRules(rules4); this.md = parser; this.state = state2; this.hooks = /* @__PURE__ */ new Map(); this.setHooks({ ...hooks3 }); } setRules(rules4) { for (const [name, rule] of Object.entries(rules4)) { if (!rule || !(name == null ? void 0 : name.length)) { continue; } this.rules[name] = rule.bind(this); } } setHooks(hooks3) { for (const [name, hook] of Object.entries(hooks3)) { if (isCustomRendererLifeCycle(name)) { this.hook(parseInt(name, 10), hook); } } } hook(cycle, hook) { const hooks3 = this.hooks.get(cycle) ?? []; const normalized = (Array.isArray(hook) ? hook : [hook]).map((h) => h.bind(this)); this.hooks.set(cycle, [...hooks3, ...normalized]); } render(tokens, options, env) { let rendered = ""; let children; let type2; let map; let len; let i; const parameters = { tokens, options, env }; rendered += this.runHooks(0 /* BeforeRender */, parameters); for (i = 0, len = tokens.length; i < len; i++) { type2 = tokens[i].type; children = tokens[i].children; map = getMap(tokens, i - 1); if (type2 === "inline" && Array.isArray(children)) { rendered += this.renderInline(children, options, env, map, tokens[i]); continue; } rendered += this.processToken(tokens, i, options, env); } rendered += this.runHooks(1 /* AfterRender */, parameters); return rendered; } // @ts-ignore renderInline(tokens, options, env, map, inline2) { const rendered = []; const parameters = { tokens, options, env, rendered, map, inline: inline2 }; rendered.push(this.runHooks(2 /* BeforeInlineRender */, parameters)); for (let i = 0; i < tokens.length; i++) { rendered.push(this.processToken(tokens, i, options, env)); } rendered.push(this.runHooks(3 /* AfterInlineRender */, parameters)); return rendered.join(""); } // renderInline provides rendered array // we accumulate render results into it // allowing us to access current render artifacts // at the time each before/after inline render hook runs runHooks(cycle, parameters) { const hooks3 = this.hooks.get(cycle) ?? []; let rendered = ""; let result = ""; for (const hook of hooks3) { result = hook(parameters); if (Array.isArray(parameters.rendered)) { parameters.rendered.push(result); } else { rendered += result; } } return Array.isArray(parameters.rendered) ? "" : rendered; } processToken(tokens, i, options, env) { let rendered = ""; const type2 = tokens[i].type; const rule = this.rules[type2]; if (rule) { rendered += rule(tokens, i, options, env, this); } else { rendered += this.renderToken(tokens, i, options); } return rendered; } }; function customRenderer(parser, parameters = {}) { parser.renderer = new CustomRenderer(parameters, parser); } // src/utils/index.ts var import_markdown_it = __toESM(require("markdown-it")); var md = new import_markdown_it.default(); var state = new md.core.State("", md, {}); function token(type2, props = {}) { return Object.assign(new state.Token(type2, "", 0), props); } function find(type2, tokens, idx) { while (tokens.length > idx) { if (tokens[idx].type === type2) { return tokens[idx]; } idx++; } return null; } function replace(source, units) { let matched = false; const result = source.replace(/%%%(\d+)%%%/g, (_2, id3) => { matched = true; id3 = Number(id3); if (!units[id3]) { throw new Error(`Translation token not found. Token id: ${id3}`); } let [value, submatch] = replace(units[id3], units); while (submatch) { [value, submatch] = replace(value, units); } return value; }); return [result, matched]; } // src/xliff/generator/template.ts var import_i18n_iso_languages = __toESM(require("@cospired/i18n-iso-languages")); var languagesList = import_i18n_iso_languages.default.langs(); function unit(source, index) { return ` <trans-unit id="${index}"> ${source} </trans-unit> `.trim(); } function template(units, { source, target }) { return ` <?xml version="1.0" encoding="UTF-8"?> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2"> <file original="file.ext" source-language="${source.language}-${source.locale}" target-language="${target.language}-${target.locale}" datatype="markdown"> <header> <skeleton> <external-file href="file.skl"></external-file> </skeleton> </header> <body> ${units.map(unit).join("\n ")} </body> </file> </xliff> `.trim(); } // src/xliff/generator/transunit.ts function transunit(parameters) { const { source, sourceLangLocale, target, targetLangLocale, compact } = parameters; let rendered = ``; if (target == null ? void 0 : target.length) { rendered += "\n"; rendered += `<target`; if (!compact) { rendered += ` xml:space="preserve"`; if (targetLangLocale == null ? void 0 : targetLangLocale.length) { rendered += ` xml:lang="${targetLangLocale}"`; } } rendered += ">"; rendered += `${target}</target>`; } if (source) { rendered += "\n"; rendered += `<source`; if (!compact) { rendered += ` xml:space="preserve"`; if (sourceLangLocale == null ? void 0 : sourceLangLocale.length) { rendered += ` xml:lang="${sourceLangLocale}"`; } } rendered += ">"; rendered += `${source}</source>`; } return rendered.trim(); } // src/symbols.ts var import_node_crypto = __toESM(require("crypto")); var gt = import_node_crypto.default.randomUUID(); var lt = import_node_crypto.default.randomUUID(); var sl = import_node_crypto.default.randomUUID(); var qt = import_node_crypto.default.randomUUID(); var mt = "E" + import_node_crypto.default.randomUUID() + "e"; var vr = "V" + import_node_crypto.default.randomUUID(); var gtre = new RegExp(`${gt}`, "gmu"); var ltre = new RegExp(`${lt}`, "gmu"); var qtre = new RegExp(`${qt}`, "gmu"); var slre = new RegExp(`${sl}`, "gmu"); var mtre = new RegExp(`${mt}`, "gmu"); var vrre = new RegExp(`${vr}-\\d+-v`, "gmu"); function unescapeSymbols(str) { return str.replace(gtre, ">").replace(ltre, "<").replace(qtre, '"').replace(slre, "/").replace(mtre, ""); } // src/xliff/generator/utils.ts function snakeCase(key) { return key.replace(/[A-Z]/g, (s) => "-" + s.toLowerCase()); } // src/xliff/generator/g.ts function generateOpenG(parameters) { parameters = { ...parameters, ...id() }; const props = Object.keys(parameters).sort().map((key) => `${snakeCase(key)}=${qt}${parameters[key]}${qt}`).join(" "); return `${lt}g ${props}${gt}`; } function generateCloseG() { return `${lt}${sl}g${gt}`; } var ID = 1; function id() { if (process.env.JEST_WORKER_ID) { return { id: "g-test" }; } return { id: "g-" + ID++ }; } // src/xliff/generator/x.ts function generateX(parameters) { parameters = { ...parameters, ...id2() }; const props = Object.keys(parameters).sort().map((key) => `${snakeCase(key)}=${qt}${parameters[key]}${qt}`).join(" "); return `${lt}x ${props}${sl + gt}`; } var ID2 = 1; function id2() { if (process.env.JEST_WORKER_ID) { return { id: "g-test" }; } return { id: "x-" + ID2++ }; } // src/xliff/md-xliff/hooks/after-inline.ts var import_markdown_it2 = __toESM(require("markdown-it")); var escapeHTML = new import_markdown_it2.default().utils.escapeHtml; function afterInline(parameters) { if (!parameters.rendered) { return ""; } let rendered = parameters.rendered.join(""); if (!rendered.length) { return ""; } rendered = escapeHTML(rendered); rendered = unescapeSymbols(rendered); parameters.rendered.splice(0, parameters.rendered.length, rendered); return ""; } // src/xliff/md-xliff/hooks/index.ts var hooks = { [3 /* AfterInlineRender */]: [afterInline] }; // src/xliff/md-xliff/rules/diplodoc/index.ts var always = (a) => () => a; var alwaysEmptyString = always(""); var rules = { // notes yfm_note_open: alwaysEmptyString, yfm_note_close: alwaysEmptyString, yfm_note_title_open: alwaysEmptyString, yfm_note_title_close: alwaysEmptyString, yfm_note_content_open: alwaysEmptyString, yfm_note_content_close: alwaysEmptyString, // cuts yfm_cut_open: alwaysEmptyString, yfm_cut_title_open: alwaysEmptyString, yfm_cut_title_close: alwaysEmptyString, yfm_cut_content_open: alwaysEmptyString, yfm_cut_content_close: alwaysEmptyString, yfm_cut_close: alwaysEmptyString, // gfm tables table_open: alwaysEmptyString, thead_open: alwaysEmptyString, tr_open: alwaysEmptyString, tr_close: alwaysEmptyString, th_open: alwaysEmptyString, th_close: alwaysEmptyString, thead_close: alwaysEmptyString, tbody_open: alwaysEmptyString, tbody_close: alwaysEmptyString, td_open: alwaysEmptyString, td_close: alwaysEmptyString, table_close: alwaysEmptyString, // checkbox checkbox_open: alwaysEmptyString, checkbox_input: alwaysEmptyString, checkbox_label_open: alwaysEmptyString, checkbox_label_close: alwaysEmptyString, checkbox_close: alwaysEmptyString, // monospace monospace_open: alwaysEmptyString, monospace_close: alwaysEmptyString, // include include: alwaysEmptyString, // tabs tabs_open: alwaysEmptyString, tabs_close: alwaysEmptyString, "tab-list_open": alwaysEmptyString, "tab-list_close": alwaysEmptyString, tab_open: alwaysEmptyString, tab_close: alwaysEmptyString, "tab-panel_open": alwaysEmptyString, "tab-panel_close": alwaysEmptyString, // anchors span_open: alwaysEmptyString, span_close: alwaysEmptyString, // table yfm_tbody_open: alwaysEmptyString, yfm_tbody_close: alwaysEmptyString, yfm_table_open: alwaysEmptyString, yfm_table_close: alwaysEmptyString, yfm_tr_open: alwaysEmptyString, yfm_tr_close: alwaysEmptyString, yfm_td_open: alwaysEmptyString, yfm_td_close: alwaysEmptyString }; // src/xliff/md-xliff/rules/link.ts var link = { link_auto: linkAuto, link_open: linkOpen, link_close: linkClose }; function linkAuto(tokens, i) { const href = tokens[i].content; return generateX({ ctype: "link_autolink", equivText: `${href}` }); } function linkOpen(tokens, i) { const open3 = tokens[i]; if (open3.g) { const title = open3.attrGet("title"); const href = open3.attrGet("href"); const begin = "[" + (open3.reflink ? "{#T}" : ""); const end = "](" + [href, title && '"' + title + '"'].filter(Boolean).join(" ") + ")"; return generateOpenG({ ctype: "link", equivText: `${begin}{{text}}${end}`, xBegin: begin, xEnd: end }); } else { if (open3.reflink) { return ""; } return generateX({ ctype: "link_text_part_open", equivText: "[" }); } } function linkClose(tokens, i) { const close3 = tokens[i]; if (close3.g) { return generateCloseG(); } const open3 = close3.open; const title = open3.attrGet("title"); const href = open3.attrGet("href"); let rendered = ""; if (open3.reflink) { rendered += generateX({ ctype: "link_reflink", equivText: "[{#T}]" }); } else { rendered += generateX({ ctype: "link_text_part_close", equivText: "]" }); } rendered += generateX({ ctype: "link_attributes_part_open", equivText: "(" }); if (href == null ? void 0 : href.length) { rendered += generateX({ ctype: "link_attributes_href", equivText: href }); } if (title == null ? void 0 : title.length) { rendered += generateX({ ctype: "link_attributes_title", equivText: title }); } rendered += generateX({ ctype: "link_attributes_part_close", equivText: ")" }); return rendered; } // src/xliff/md-xliff/rules/breaks.ts function generateBreak(tokens, i) { const _break = tokens[i]; return generateX({ ctype: `lb`, equivText: _break.content || "\n" }); } var breaks = { hardbreak: generateBreak, softbreak: generateBreak }; // src/xliff/md-xliff/rules/pair.ts var open = (ctype) => (tokens, i) => { const token2 = tokens[i]; const markup = token2.markup; if (token2.g) { return generateOpenG({ ctype, equivText: `${markup}{{text}}${markup}`, xBegin: markup, xEnd: markup }); } return generateX({ ctype: ctype + "_open", equivText: markup }); }; var close = (ctype) => (tokens, i) => { const token2 = tokens[i]; const markup = token2.markup; if (token2.g) { return generateCloseG(); } return generateX({ ctype: ctype + "_close", equivText: markup }); }; var pair = { strong_open: open("bold"), strong_close: close("bold"), em_open: open("italic"), em_close: close("italic"), s_open: open("strikethrough"), s_close: close("strikethrough"), sup_open: open("sup"), sup_close: close("sup"), monospace_open: open("monospace"), monospace_close: close("monospace") }; // src/xliff/md-xliff/rules/code-inline.ts var codeInline = { code_inline_open: codeInlineRule("open"), code_inline_close: codeInlineRule("close") }; function codeInlineRule(dir) { return function(tokens, i) { const { markup } = tokens[i]; return generateX({ ctype: `code_${dir}`, equivText: markup }); }; } // src/xliff/md-xliff/rules/text.ts var text = { text: function(tokens, i) { var _a; const text3 = tokens[i]; if (!((_a = text3.content) == null ? void 0 : _a.length) || text3.reflink) { return ""; } return text3.content; } }; // src/xliff/md-xliff/rules/liquid.ts var liquid = { liquid: function(tokens, i) { const { subtype, content, markup } = tokens[i]; return generateX({ ctype: `liquid_${subtype}`, equivText: markup || content }); } }; // src/xliff/md-xliff/rules/image.ts var import_markdown_it3 = __toESM(require("markdown-it")); var decodeURL = new import_markdown_it3.default().utils.lib.mdurl.decode; var image = { image_open: imageOpen, image_close: imageClose }; function imageOpen(tokens, idx) { const open3 = tokens[idx]; if (open3.g) { const close3 = open3.g; const src = close3.attrGet("src"); const title = close3.attrGet("title"); const height = close3.attrGet("height"); const width = close3.attrGet("width"); const begin = "!["; const end = "](" + [src && decodeURL(src), title && '"' + title + '"', size(width, height)].filter(Boolean).join(" ") + ")"; return generateOpenG({ ctype: "image", equivText: `${begin}{{text}}${end}`, xBegin: begin, xEnd: end }); } else { return generateX({ ctype: "image_text_part_open", equivText: "![" }); } } function imageClose(tokens, idx) { const close3 = tokens[idx]; if (close3.g) { return generateCloseG(); } let rendered = ""; rendered += generateX({ ctype: "image_text_part_close", equivText: "]" }); rendered += generateX({ ctype: "image_attributes_part_open", equivText: "(" }); let src = close3.attrGet("src"); if (src == null ? void 0 : src.length) { src = decodeURL(src); rendered += generateX({ ctype: "image_attributes_src", equivText: src }); } const title = close3.attrGet("title"); if (title == null ? void 0 : title.length) { rendered += generateX({ ctype: "image_attributes_title", equivText: title }); } const height = close3.attrGet("height"); const width = close3.attrGet("width"); if ((width == null ? void 0 : width.length) || (height == null ? void 0 : height.length)) { rendered += generateX({ ctype: "image_attributes_size", equivText: size(width, height) }); } rendered += generateX({ ctype: "image_attributes_part_close", equivText: ")" }); return rendered; } function size(width, height) { if (!(width == null ? void 0 : width.length) && !(height == null ? void 0 : height.length)) { return ""; } let equivText = "="; if (width == null ? void 0 : width.length) { equivText += width; } equivText += "x"; if (height == null ? void 0 : height.length) { equivText += height; } return equivText; } // src/xliff/md-xliff/rules/video.ts var video = { video: videoRule }; function videoRule(tokens, i) { const { service, videoID } = tokens[i]; return generateX({ ctype: "video", equivText: `@[${service}](${videoID})` }); } // src/xliff/md-xliff/rules/file.ts var file = { yfm_file: fileRule }; var attributes = /* @__PURE__ */ new Map([ ["href", "src"], ["download", "name"], ["hreflang", "lang"], ["type", "type"], ["target", "target"], ["rel", "rel"], ["referrerpolicy", "referrerpolicy"] ]); var translatable = /* @__PURE__ */ new Set(["download"]); function fileRule(tokens, i) { const { attrs: attrs2 } = tokens[i]; if (!(attrs2 == null ? void 0 : attrs2.length)) { throw new Error(`failed to render token: ${tokens[i]}`); } let rendered = generateX({ ctype: "file_open", equivText: "{%" }); for (const [key, val] of attrs2) { const attribute = attributes.get(key); if (!(attribute == null ? void 0 : attribute.length)) { continue; } const ctype = `file_${attribute}`; const equivText = `${attribute}="${val}"`; if (translatable.has(key)) { rendered += generateX({ ctype: `${ctype}_open`, equivText: `${attribute}="` }); rendered += val; rendered += generateX({ ctype: `${ctype}_close`, equivText: '"' }); } else { rendered += generateX({ ctype, equivText }); } } rendered += generateX({ ctype: "file_close", equivText: "%}" }); return rendered; } // src/xliff/md-xliff/rules/html-inline.ts var htmlInline = { html_inline: function(tokens, i) { const { skip: skip2, type: type2 } = tokens[i]; return generateX({ ctype: type2, equivText: (skip2 || "").toString() }); } }; // src/xliff/md-xliff/rules/index.ts var rules2 = { code_block: () => "", fence: () => "", html_block: () => "", heading_open: () => "", heading_close: () => "", paragraph_open: () => "", paragraph_close: () => "", bullet_list_open: () => "", bullet_list_close: () => "", ordered_list_open: () => "", ordered_list_close: () => "", blockquote_open: () => "", blockquote_close: () => "", list_item_open: () => "", list_item_close: () => "", ...rules, ...breaks, ...pair, ...codeInline, ...link, ...text, ...liquid, ...image, ...video, ...file, ...htmlInline }; // src/xliff/md-xliff/index.ts function render(tokens, unitId, compact = false) { const xliffRenderer = new import_markdown_it4.default({ html: true }); xliffRenderer.use(customRenderer, { rules: rules2, hooks, compact }); const source = xliffRenderer.renderer.render( [ token("inline", { children: groupUselessTokens(tokens) }) ], xliffRenderer.options, {} ); return transunit({ source, compact, id: unitId }); } function groupUselessTokens(tokens) { const map = {}; const result = []; for (const part of tokens) { if (!part.content) { const [name, type2] = part.type.split("_"); if (type2 === "open") { map[part.type] = map[part.type] || []; map[part.type].push(part); } else if (type2 === "close") { map[name + "_open"] = map[name + "_open"] || []; const opener = map[name + "_open"].pop(); if (opener) { opener.g = part; part.g = opener; } } } result.push(part); } return result; } // src/xliff/xliff-md/index.ts var import_assert = __toESM(require("assert")); // src/xliff/token.ts var xliffTagTokenNodeTypes = /* @__PURE__ */ new Set(["open", "close", "self-closing"]); function isXLFTextToken(token2) { return (token2 == null ? void 0 : token2.type) === "text"; } function isXLFTagToken(token2) { return (token2 == null ? void 0 : token2.type) === "tag" && xliffTagTokenNodeTypes.has(token2.nodeType); } // src/xliff/xliff-md/index.ts var literal = (token2) => { (0, import_assert.default)(isXLFTagToken(token2)); token2; const { equivText } = token2; (0, import_assert.default)( equivText == null ? void 0 : equivText.length, "literal tag should contain original markup inside equiv-text attritbute" ); return equivText; }; var openclose = (token2) => { (0, import_assert.default)(isXLFTagToken(token2)); token2; if (token2.nodeType === "open") { return token2.begin; } else { return token2.end; } }; var spaced = (actor) => (token2) => " " + actor(token2); var quoted = (actor) => (token2) => '"' + actor(token2) + '"'; var attr = spaced(quoted(literal)); var XLFMDRenderer = class { constructor() { this.rules = { text: this.text.bind(this), tag: this.tag.bind(this), x: this.x.bind(this), g: this.g.bind(this), // simple pair syntax // strong bold: openclose, bold_open: literal, bold_close: literal, // em italic: openclose, italic_open: literal, italic_close: literal, // s strikethrough: openclose, strikethrough_open: literal, strikethrough_close: literal, // sup sup: openclose, sup_open: literal, sup_close: literal, // sup monospace: openclose, monospace_open: literal, monospace_close: literal, // samp samp_open: literal, samp_close: literal, // code code_open: literal, code_close: literal, lb: literal, // link link: openclose, link_text_part_open: literal, link_text_part_close: literal, link_attributes_part_open: literal, link_attributes_part_close: literal, link_attributes_href: literal, link_attributes_title: attr, link_autolink: literal, link_reflink: literal, // image image: openclose, image_text_part_open: literal, image_text_part_close: literal, image_attributes_part_open: literal, image_attributes_part_close: literal, image_attributes_src: literal, image_attributes_title: attr, image_attributes_size: spaced(literal), // video video: literal, // anchor anchor: literal, // file file_open: literal, file_src: spaced(literal), file_name_open: spaced(literal), file_name_close: literal, file_referrerpolicy: spaced(literal), file_rel: spaced(literal), file_target: spaced(literal), file_type: spaced(literal),