@awesome-fe/translate
Version:
Translation utils
206 lines • 7.63 kB
JavaScript
;
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