UNPKG

@awesome-fe/translate

Version:
206 lines 7.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.tinyHtmlToAdoc = exports.tinyHtmlDomToAdoc = void 0; const dom_models_1 = require("../../parse5/dom-models"); const create_asciidoctor_1 = require("../utils/create-asciidoctor"); const adoc_1 = require("../utils/adoc"); const quotes_1 = require("./quotes"); const add_quotes_1 = require("../adoc-builder/renderers/utils/add-quotes"); function extractValue(value, type) { if (type === 'object') { return JSON.parse(value); } else if (type === 'boolean') { return value === 'true'; } else if (type === 'number') { return +value; } else { return value; } } function loadAttributes(domNode, adocNode) { const attributes = domNode.getAttributes(); attributes.filter(it => it.name.startsWith('data-') && it.value !== undefined && it.value !== null) .forEach((attr) => { const type = domNode.getAttribute(`type-${attr.name}`); const name = attr.name.replace(/^data-/g, ''); const value = extractValue(attr.value, type); // setAttribute 无法正确处理 number 类型的参数,因此要绕过它 if (typeof value === 'number') { adocNode.attributes.$$smap[name] = value; } else { adocNode.setAttribute(name, value); } }); } function isUnconstrained(domNode) { return /\w$/.test(domNode.previousSibling()?.textContent ?? '') || /^\w/.test(domNode.nextSibling()?.textContent ?? ''); } function buildInlineQuoted(domNode, content) { if (domNode.getAttribute('prop-type') === 'asciimath') { return `stem:[${content}]`; } const times = isUnconstrained(domNode) ? 2 : 1; switch (domNode.getAttribute('prop-type')) { case 'double': return `"\`${content}\`"`; case 'single': return `'\`${content}\`'`; case 'unquoted': return `[.${domNode.getAttribute('data-role')}]#${content}#`; default: const quote = (0, quotes_1.quoteTypeToChar)(domNode)?.repeat(times) ?? ''; return [quote, content, quote].join(''); } } function buildInlineAnchor(domNode, content) { const role = domNode.getAttribute('data-role'); const window = domNode.getAttribute('data-window'); const target = domNode.getAttribute('prop-target').replace(/\.html\b/, '.adoc'); if (role === undefined) { if (target.startsWith('mailto:')) { return content; } else { if (target === '#' + content) { return `<<${content}>>`; } else { return `<<${target.replace(/^#/, '')},${content}>>`; } } } else if (role === 'bare') { return target; } else if (role && target) { return `${target}[${content}${window === '_blank' ? '^' : ''}, role=${role}]`; } else { return ''; } } function buildInlineImage(domNode) { const alt = domNode.getAttribute('prop-alt'); const defaultAlt = domNode.getAttribute('data-default-alt'); const nonDefaultAlt = alt === defaultAlt ? '' : alt; const target = domNode.getAttribute('prop-target'); const type = domNode.getAttribute('prop-type'); switch (type) { case 'icon': const link = domNode.getAttribute('data-link'); const window = domNode.getAttribute('data-window'); return `icon:${target}[link=${link},window=${window}]`; default: return `image:${target}[${nonDefaultAlt}]`; } } function buildInlineKbd(domNode) { const keys = domNode.querySelectorAll(it => it.isTagOf('kbd')).map(it => it.textContent); return `kbd:[${keys.join('+')}]`; } function buildInlineButton(domNode) { return `btn:[${domNode.textContent}]`; } function buildInlineMenu(domNode) { const items = domNode.querySelectorAll(it => it.isTagOf('span')).map(it => it.textContent); const menu = items.slice(0, 1); const submenus = items.slice(1, items.length - 1); const menuItem = items.slice(items.length - 1, items.length); return `menu:${menu}[${[...submenus, menuItem].filter(it => !!it).join(' > ')}]`; } function buildInlineIndexTerm(domNode) { const terms = domNode.querySelectorAll(it => it.hasClass('term')).map(it => (0, add_quotes_1.addQuotes)(it.textContent)); const isInline = domNode.getAttribute('prop-type') === 'visible'; if (isInline) { return `((${terms.join(', ')}))`; } else { if (domNode.nextSibling()?.textContent.startsWith('\n')) { return `(((${terms.join(', ')})))`; } else { return `(((${terms.join(', ')})))\n`; } } } function buildInlineFootNote(domNode) { const type = domNode.getAttribute('prop-type'); if (!type) { return `footnote:[${domNode.textContent}]`; } else if (type === 'ref') { const id = domNode.getAttribute('attr-id') ?? ''; return `footnote:${id}[${domNode.textContent}]`; } else if (type === 'xref') { const target = domNode.getAttribute('prop-target') ?? ''; return `footnote:${target}[]`; } } function toAdocLines(domNode) { if (domNode instanceof dom_models_1.DomElement) { const content = domNode.childNodes.map(it => toAdocLines(it)).join(''); const adocName = domNode.getAttribute('adoc-name'); switch (adocName) { case 'inline_quoted': return buildInlineQuoted(domNode, content); case 'inline_anchor': return buildInlineAnchor(domNode, content); case 'inline_image': return buildInlineImage(domNode); case 'inline_kbd': return buildInlineKbd(domNode); case 'inline_button': return buildInlineButton(domNode); case 'inline_menu': return buildInlineMenu(domNode); case 'inline_indexterm': return buildInlineIndexTerm(domNode); case 'inline_footnote': return buildInlineFootNote(domNode); default: return content; } } else if (domNode instanceof dom_models_1.DomText) { // 如果网址没有包含在链接中,说明它是被专门转义过的 if (!domNode.queryAncestor(it => it.isTagOf('a'))) { return domNode.textContent .replace(/\b(https?:)/, '\\$1') .replace(/\b([\w.-]+@[\w.-]+)/, '\\$1'); } return domNode.textContent; } } function decompile(adocNode, domNode) { if (!adocNode || !domNode) { return; } const name = domNode.getAttribute('adoc-name'); const node = adoc_1.adoc.createNode(adocNode, name); loadAttributes(domNode, node); domNode.children.forEach(it => { decompile(node, it); }); if (adoc_1.adoc.hasLines(node)) { node.lines = toAdocLines(domNode).split('\n'); } } function tinyHtmlDomToAdoc(tinyHtmlDoc) { const doc = (0, create_asciidoctor_1.createAsciidoctor)(); const root = doc.load('', { backend: 'adoc' }); decompile(root, tinyHtmlDoc.querySelector(it => it.isTagOf('article'))); return root; } exports.tinyHtmlDomToAdoc = tinyHtmlDomToAdoc; function tinyHtmlToAdoc(tinyHtml) { const doc = tinyHtmlDomToAdoc(dom_models_1.DomDocument.parse(tinyHtml)); return doc.convert({ backend: 'adoc' }).trim(); } exports.tinyHtmlToAdoc = tinyHtmlToAdoc; //# sourceMappingURL=tiny-html-to-adoc.js.map