@taiga-ui/cdk
Version:
Base library for creating Angular components and applications using Taiga UI principles regarding of actual visual appearance
211 lines • 8.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrateDocDocumentation = migrateDocDocumentation;
const insert_todo_1 = require("../../../../utils/insert-todo");
const elements_1 = require("../../../../utils/templates/elements");
const template_resource_1 = require("../../../../utils/templates/template-resource");
const DOC_PROPERTY_ATTRS = [
'documentationPropertyMode',
'documentationPropertyName',
'documentationPropertyType',
'[documentationPropertyValue]',
'[(documentationPropertyValue)]',
'(documentationPropertyValueChange)',
'[documentationPropertyValues]',
].map((x) => x.toLowerCase());
function migrateDocDocumentation({ resource, recorder, fileSystem, }) {
const template = (0, template_resource_1.getTemplateFromTemplateResource)(resource, fileSystem);
const templateOffset = (0, template_resource_1.getTemplateOffset)(resource);
const elements = (0, elements_1.findElementsByTagName)(template, 'tui-doc-documentation');
const replacements = [];
elements.forEach((element) => {
replacements.push(...buildOuterReplacement(template, element));
collectInnerTemplates(element).forEach((inner) => {
replacements.push(...buildInnerReplacement(template, inner));
});
});
replacements
.sort((a, b) => b.startOffset - a.startOffset)
.forEach(({ startOffset, endOffset, replacement }) => {
recorder.remove(templateOffset + startOffset, endOffset - startOffset);
recorder.insertRight(templateOffset + startOffset, replacement);
});
}
function collectInnerTemplates(element) {
const found = [];
const visit = (nodes) => {
nodes === null || nodes === void 0 ? void 0 : nodes.forEach((node) => {
const el = node;
if (el.tagName === 'ng-template' && hasDocPropertyAttr(el)) {
found.push(el);
}
visit(el.childNodes);
});
};
visit(element.childNodes);
return found;
}
function hasDocPropertyAttr(element) {
var _a;
return ((_a = element.attrs) !== null && _a !== void 0 ? _a : []).some((attr) => DOC_PROPERTY_ATTRS.includes(attr.name.toLowerCase()));
}
function buildOuterReplacement(template, element) {
const loc = element.sourceCodeLocation;
const startTag = loc === null || loc === void 0 ? void 0 : loc.startTag;
if (!startTag) {
return [];
}
const replacements = [];
const startTagStr = template.slice(startTag.startOffset, startTag.endOffset);
const isSelfClosing = startTagStr.trimEnd().endsWith('/>');
const headingAttr = element.attrs.find((attr) => attr.name === 'heading');
const otherAttrs = element.attrs.filter((attr) => attr.name !== 'heading');
const attrsStr = ['tuiDocAPI', ...otherAttrs.map(formatAttr)].join(' ');
const close = isSelfClosing ? ' />' : '>';
let newStartTag = `<table ${attrsStr}${close}`;
if (headingAttr === null || headingAttr === void 0 ? void 0 : headingAttr.value) {
const indent = getLineIndent(template, startTag.startOffset);
newStartTag = `<h3>${headingAttr.value}</h3>\n${indent}${newStartTag}`;
}
replacements.push({
startOffset: startTag.startOffset,
endOffset: startTag.endOffset,
replacement: newStartTag,
});
if (loc.endTag) {
replacements.push({
startOffset: loc.endTag.startOffset,
endOffset: loc.endTag.endOffset,
replacement: '</table>',
});
}
return replacements;
}
function buildInnerReplacement(template, element) {
var _a, _b;
const loc = element.sourceCodeLocation;
const startTag = loc === null || loc === void 0 ? void 0 : loc.startTag;
if (!startTag) {
return [];
}
const replacements = [];
const startTagStr = template.slice(startTag.startOffset, startTag.endOffset);
const isSelfClosing = startTagStr.trimEnd().endsWith('/>');
const mode = getAttrValue(element, 'documentationPropertyMode');
const name = (_a = getAttrValue(element, 'documentationPropertyName')) !== null && _a !== void 0 ? _a : '';
const type = getAttrValue(element, 'documentationPropertyType');
const items = getAttrValue(element, '[documentationPropertyValues]');
const twoWayValue = getAttrValue(element, '[(documentationPropertyValue)]');
const oneWayValue = getAttrValue(element, '[documentationPropertyValue]');
const valueChange = getAttrValue(element, '(documentationPropertyValueChange)');
const refAttr = element.attrs.find((attr) => attr.name.startsWith('#') && attr.value === 'documentationProperty');
const wrappedName = wrapName(name, mode);
const orderedAttrs = [];
if (refAttr) {
orderedAttrs.push(getOriginalAttrName(template, element, refAttr.name));
}
if (wrappedName) {
orderedAttrs.push(`name="${wrappedName}"`);
}
orderedAttrs.push('tuiDocAPIItem');
if (type !== undefined) {
orderedAttrs.push(`type="${type}"`);
}
if (items !== undefined) {
orderedAttrs.push(`[items]="${items}"`);
}
if (twoWayValue !== undefined) {
orderedAttrs.push(`[(value)]="${twoWayValue}"`);
}
else if (oneWayValue !== undefined) {
orderedAttrs.push(`[value]="${oneWayValue}"`);
}
const valueChangeTodo = valueChange === undefined
? ''
: `<!-- ${insert_todo_1.TODO_MARK} $any($event) used because model<T>() emits T | undefined; consider using [(value)] two-way binding or replace $any($event) with $event ?? <default> -->\n`;
if (valueChange !== undefined) {
orderedAttrs.push(`(valueChange)="${valueChange.replaceAll('$event', '$any($event)')}"`);
}
const isMultiline = startTagStr.includes('\n');
let newStartTag;
if (isMultiline) {
const elementIndent = getLineIndent(template, startTag.startOffset);
const attrIndent = (_b = getAttrIndent(template, element)) !== null && _b !== void 0 ? _b : `${elementIndent} `;
const lines = ['<tr'];
orderedAttrs.forEach((attr) => lines.push(`${attrIndent}${attr}`));
lines.push(isSelfClosing ? `${elementIndent}/>` : `${elementIndent}>`);
newStartTag = `${valueChangeTodo}${lines.join('\n')}`;
}
else {
const close = isSelfClosing ? ' />' : '>';
newStartTag = `${valueChangeTodo}<tr ${orderedAttrs.join(' ')}${close}`;
}
replacements.push({
startOffset: startTag.startOffset,
endOffset: startTag.endOffset,
replacement: newStartTag,
});
if (loc.endTag) {
replacements.push({
startOffset: loc.endTag.startOffset,
endOffset: loc.endTag.endOffset,
replacement: '</tr>',
});
}
return replacements;
}
function getAttrValue(element, name) {
var _a;
return (_a = element.attrs.find((attr) => attr.name === name.toLowerCase())) === null || _a === void 0 ? void 0 : _a.value;
}
function getOriginalAttrName(template, element, name) {
var _a, _b;
const loc = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[name];
if (!loc) {
return name;
}
const slice = template.slice(loc.startOffset, loc.endOffset);
const eqIdx = slice.indexOf('=');
return eqIdx === -1 ? slice : slice.slice(0, eqIdx);
}
function getAttrIndent(template, element) {
var _a, _b;
const firstAttr = element.attrs[0];
if (!firstAttr) {
return null;
}
const loc = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[firstAttr.name];
if (!loc) {
return null;
}
const prevNl = template.lastIndexOf('\n', loc.startOffset - 1);
if (prevNl === -1) {
return null;
}
const candidate = template.slice(prevNl + 1, loc.startOffset);
return /^\s*$/.test(candidate) ? candidate : null;
}
function formatAttr(attr) {
return attr.value ? `${attr.name}="${attr.value}"` : attr.name;
}
function wrapName(name, mode) {
switch (mode) {
case 'input':
return `[${name}]`;
case 'input-output':
return `[(${name})]`;
case 'output':
return `(${name})`;
default:
return name;
}
}
function getLineIndent(template, offset) {
const lastLineBreak = template.lastIndexOf('\n', offset - 1);
if (lastLineBreak === -1) {
return '';
}
const candidate = template.slice(lastLineBreak + 1, offset);
return /^\s*$/.test(candidate) ? candidate : '';
}
//# sourceMappingURL=migrate-doc-documentation.js.map