@awesome-fe/translate
Version:
Translation utils
156 lines • 7.08 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.restructureTable = exports.markAndSwap = exports.HtmlMarker = void 0;
var dom_models_1 = require("../dom/parse5/dom-models");
var common_1 = require("../dom/common");
var slugs = require("github-slugger");
var util_1 = require("util");
var marker_1 = require("./marker");
var HtmlMarker = /** @class */ (function (_super) {
__extends(HtmlMarker, _super);
function HtmlMarker(selectors) {
if (selectors === void 0) { selectors = dom_models_1.defaultSelectors; }
var _this = _super.call(this) || this;
_this.selectors = selectors;
return _this;
}
HtmlMarker.prototype.markContent = function (content, mono) {
var doc = parseDoc(content);
this.addIdForHeaders(doc);
this.markAndSwapAll(doc);
if (mono) {
this.monochromatic(doc);
}
return doc.toHtml();
};
HtmlMarker.prototype.addIdForHeaders = function (body) {
var headers = body.querySelectorAll(function (it) { return ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(it.nodeName); });
var slugger = slugs();
headers.forEach(function (header) {
if (!header.hasAttribute('id')) {
header.setAttribute('id', toId(slugger, header.textContent));
}
});
};
HtmlMarker.prototype.markAndSwapAll = function (body) {
restructureTable(body);
this.selectors.forEach(function (selector) { return markAndSwap(body, selector); });
};
HtmlMarker.prototype.monochromatic = function (parent) {
parent.querySelectorAll(function (it) { return it.hasAttribute('translation-origin'); }).forEach(function (it) { return it.remove(); });
parent.querySelectorAll(function (it) { return it.hasAttribute('translation-result'); }).forEach(function (it) { return it.removeAttribute('translation-result'); });
};
return HtmlMarker;
}(marker_1.Marker));
exports.HtmlMarker = HtmlMarker;
function parseDoc(content) {
if (content.includes('<html')) {
return dom_models_1.DomDocument.parse(content);
}
else {
return dom_models_1.DomDocumentFragment.parse(content);
}
}
function toId(slugger, text) {
return slugger.slug(text);
}
function isPaired(prev, element) {
return prev && prev.nextElementSibling === element &&
prev.isTagOf(element.tagName) && prev.className === element.className;
}
function markAndSwap(element, selector) {
var elements = element.querySelectorAll(selector);
elements.forEach(function (element) {
if ((0, common_1.containsChinese)(element.innerHTML) && !element.hasAttribute('no-translate') && element.getAttribute('translate') !== 'no') {
var prev = element.previousElementSibling;
if (isPaired(prev, element) && !(0, common_1.containsChinese)(prev.innerHTML)) {
element.setAttribute('translation-result', 'on');
prev.setAttribute('translation-origin', 'off');
element.parentNode.insertBefore(element, prev);
// 交换 id,中文内容应该占用原文的 id
var id = prev.getAttribute('id');
if (id) {
prev.removeAttribute('id');
element.setAttribute('id', id);
}
var href = prev.getAttribute('href');
if (href) {
element.setAttribute('href', href);
}
if (element.isTagOf('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li')) {
var prevAnchor = prev.querySelector(function (it) { return it.isTagOf('a') && it.hasAttribute('href'); });
var thisAnchor = element.querySelector(function (it) { return it.isTagOf('a') && it.hasAttribute('href'); });
if (prevAnchor && thisAnchor && (0, common_1.containsChinese)(decodeURIComponent(thisAnchor.getAttribute('href')))) {
thisAnchor.setAttribute('href', prevAnchor.getAttribute('href'));
}
}
}
}
});
}
exports.markAndSwap = markAndSwap;
function shouldMergeTable(element) {
return element.getAttribute('translation-merge-rows') === 'no';
}
function shouldMergeRow(element) {
if (element.getAttribute('translation-merge-rows') === 'no') {
return false;
}
// 如果内部有 p 元素,则禁止自动合并
for (var i = 0; i < element.cells.length; ++i) {
if (element.cells[i].querySelector(function (it) { return it.isTagOf('p'); })) {
return false;
}
}
return true;
}
// 重塑表格结构
function restructureTable(element) {
var items = element.querySelectorAll(function (it) { return it.isTagOf('table'); });
items.forEach(function (table) {
if (shouldMergeTable(table)) {
return;
}
// 对出现在 thead 的行和出现在 tbody 的行进行统一处理
var rows = table.querySelectorAll(function (it) { return it.isTagOf('tr'); });
var translationRows = [];
for (var i = 0; i < rows.length - 1; ++i) {
var thisRow = rows[i];
var nextRow = rows[i + 1];
if (shouldMergeRow(nextRow) && (0, common_1.containsChinese)(nextRow.innerHTML) && !(0, common_1.containsChinese)(thisRow.innerHTML)) {
translationRows.push(nextRow);
mergeRows(thisRow, nextRow);
}
}
translationRows.forEach(function (row) { return row.remove(); });
});
}
exports.restructureTable = restructureTable;
function mergeRows(originRow, translationRow) {
if (originRow.cells.length !== translationRow.cells.length) {
return;
}
for (var i = 0; i < originRow.cells.length; ++i) {
var originCell = originRow.cells[i];
var translationCell = translationRow.cells[i];
if ((0, util_1.isDeepStrictEqual)(originCell.attrs, translationCell.attrs) && originCell.innerHTML !== translationCell.innerHTML) {
originCell.innerHTML = "<nt-wrapper>".concat(originCell.innerHTML, "</nt-wrapper><nt-wrapper>").concat(translationCell.innerHTML, "</nt-wrapper>");
}
}
}
//# sourceMappingURL=html-marker.js.map