@taiga-ui/cdk
Version:
Base library for creating Angular components and applications using Taiga UI principles regarding of actual visual appearance
189 lines • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrateSelect = migrateSelect;
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 control_state_attrs_1 = require("../../../utils/templates/control-state-attrs");
const replace_tag_1 = require("../../../utils/templates/replace-tag");
const SELECT_MIGRATION_TODO = `<!-- ${insert_todo_1.TODO_MARK} tui-select was partially migrated. Complete migration manually. See examples: https://taiga-ui.dev/components/select -->\n`;
const VALUE_CONTENT_ATTR = 'valueContent';
const CONTENT_ATTR = 'content';
const TEXTFIELD_LABEL_OUTSIDE_ATTR = 'tuiTextfieldLabelOutside';
const CONTROL_ATTR_NAMES = [
'formControlName',
'[formControl]',
'formControl',
'[(ngModel)]',
'[ngModel]',
'ngModel',
];
const CONTROL_ATTRS = new Set(CONTROL_ATTR_NAMES.map((name) => name.toLowerCase()));
function migrateSelect({ 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-select');
elements.forEach((element) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const startOffset = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset;
const controlAttrs = element.attrs.filter((attr) => CONTROL_ATTRS.has(attr.name.toLowerCase()));
const controlStateAttrs = (0, control_state_attrs_1.getControlStateAttrs)(element);
if (typeof startOffset === 'number') {
recorder.insertLeft(templateOffset + startOffset, SELECT_MIGRATION_TODO);
}
renameAttr(recorder, templateOffset, element, `[${VALUE_CONTENT_ATTR}]`, `[${CONTENT_ATTR}]`);
renameAttr(recorder, templateOffset, element, VALUE_CONTENT_ATTR, CONTENT_ATTR);
const labelOutsideAttr = element.attrs.find((attr) => attr.name.toLowerCase() ===
`[${TEXTFIELD_LABEL_OUTSIDE_ATTR}]`.toLowerCase() ||
attr.name.toLowerCase() === TEXTFIELD_LABEL_OUTSIDE_ATTR.toLowerCase());
const isBinding = (_b = labelOutsideAttr === null || labelOutsideAttr === void 0 ? void 0 : labelOutsideAttr.name.startsWith('[')) !== null && _b !== void 0 ? _b : false;
const isLabelOutsideTrue = (labelOutsideAttr === null || labelOutsideAttr === void 0 ? void 0 : labelOutsideAttr.value) === 'true' ||
(!!labelOutsideAttr && !isBinding && labelOutsideAttr.value === '');
const isLabelOutsideDynamic = !!labelOutsideAttr &&
!isLabelOutsideTrue &&
labelOutsideAttr.value !== 'false';
removeAttr(recorder, templateOffset, element, `[${TEXTFIELD_LABEL_OUTSIDE_ATTR}]`, template);
removeAttr(recorder, templateOffset, element, TEXTFIELD_LABEL_OUTSIDE_ATTR, template);
controlAttrs.forEach((attr) => {
removeAttr(recorder, templateOffset, element, attr.name, template);
});
(0, control_state_attrs_1.removeControlStateAttrs)(recorder, templateOffset, element, template, controlStateAttrs);
const hasChevron = element.attrs.some((attr) => attr.name.toLowerCase() === 'tuiChevron'.toLowerCase());
(0, replace_tag_1.replaceTag)(recorder, element.sourceCodeLocation, 'tui-select', 'tui-textfield', template, templateOffset, hasChevron ? [] : ['tuiChevron']);
const placeholder = getPlaceholderText(element);
const inputs = element.childNodes.filter((node) => node.nodeName === 'input');
if (inputs.length) {
if (isLabelOutsideTrue && placeholder) {
removeTextContent(recorder, templateOffset, element);
}
else if (!isLabelOutsideDynamic && !isLabelOutsideTrue) {
wrapTextInLabel(recorder, templateOffset, element);
}
inputs.forEach((input) => {
var _a, _b, _c;
input.attrs.forEach((attr) => {
var _a, _b, _c;
if (!/^tuitextfieldlegacy$|^tuitextfield$/i.test(attr.name)) {
return;
}
const { startOffset = 0, endOffset = 0 } = (_c = (_b = (_a = input.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[attr.name]) !== null && _c !== void 0 ? _c : {};
recorder.remove(templateOffset + startOffset, endOffset - startOffset);
recorder.insertRight(templateOffset + startOffset, 'tuiSelect');
});
const formAttrs = formatControlAttrs(controlAttrs);
const controlStateStr = (0, control_state_attrs_1.stringifyControlStateAttrs)(controlStateAttrs);
const placeholderAttr = isLabelOutsideTrue && placeholder
? ` placeholder="${placeholder}"`
: '';
const insertOffset = ((_c = (_b = (_a = input.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startTag) === null || _b === void 0 ? void 0 : _b.startOffset) !== null && _c !== void 0 ? _c : 0) +
'<input'.length;
if (formAttrs || placeholderAttr || controlStateStr) {
recorder.insertRight(templateOffset + insertOffset, `${placeholderAttr}${formAttrs ? ` ${formAttrs}` : ''}${controlStateStr}`);
}
});
}
else {
const formAttrs = formatControlAttrs(controlAttrs);
const controlStateStr = (0, control_state_attrs_1.stringifyControlStateAttrs)(controlStateAttrs);
const firstElementChildOffset = (_d = (_c = element.childNodes.find((node) => node.nodeName !== '#text')) === null || _c === void 0 ? void 0 : _c.sourceCodeLocation) === null || _d === void 0 ? void 0 : _d.startOffset;
const insertOffset = (_g = firstElementChildOffset !== null && firstElementChildOffset !== void 0 ? firstElementChildOffset : (_f = (_e = element.sourceCodeLocation) === null || _e === void 0 ? void 0 : _e.endTag) === null || _f === void 0 ? void 0 : _f.startOffset) !== null && _g !== void 0 ? _g : 0;
const placeholderAttr = isLabelOutsideTrue && placeholder ? ` placeholder="${placeholder}"` : '';
const inputTemplate = `\n<input${placeholderAttr} tuiSelect${formAttrs ? ` ${formAttrs}` : ''}${controlStateStr} />\n`;
if (isLabelOutsideTrue) {
removeTextContent(recorder, templateOffset, element);
}
else if (!isLabelOutsideDynamic) {
wrapTextInLabel(recorder, templateOffset, element);
}
recorder.insertRight(templateOffset + insertOffset, inputTemplate);
}
if (isLabelOutsideDynamic && typeof startOffset === 'number') {
const lineStart = template.lastIndexOf('\n', startOffset - 1) + 1;
const indent = (_j = (_h = /^[ \t]*/.exec(template.slice(lineStart, startOffset))) === null || _h === void 0 ? void 0 : _h[0]) !== null && _j !== void 0 ? _j : '';
recorder.insertRight(templateOffset + startOffset, `<!-- ${insert_todo_1.TODO_MARK} [tuiTextfieldLabelOutside] is dynamic and cannot be migrated automatically. Use <label tuiLabel> inside <tui-textfield> for floating label or input[placeholder] for outside label -->\n${indent}`);
}
});
}
function renameAttr(recorder, templateOffset, element, from, to) {
var _a, _b;
const attrLocation = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[from.toLowerCase()];
if (!attrLocation) {
return;
}
recorder.remove(templateOffset + attrLocation.startOffset, from.length);
recorder.insertRight(templateOffset + attrLocation.startOffset, to);
}
function removeAttr(recorder, templateOffset, element, name, template) {
var _a, _b;
const attrLocation = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[name.toLowerCase()];
if (!attrLocation) {
return;
}
const lineStart = template.lastIndexOf('\n', attrLocation.startOffset) + 1;
const lineEnd = template.indexOf('\n', attrLocation.endOffset);
const attrText = template.slice(attrLocation.startOffset, attrLocation.endOffset);
const lineText = lineEnd === -1 ? '' : template.slice(lineStart, lineEnd);
if (lineText.trim() === attrText.trim() && lineEnd !== -1) {
recorder.remove(templateOffset + lineStart, lineEnd - lineStart + 1);
return;
}
recorder.remove(templateOffset + attrLocation.startOffset - 1, attrLocation.endOffset - attrLocation.startOffset + 1);
}
function getPlaceholderText(element) {
var _a;
const textNode = element.childNodes.find((node) => isTextNode(node) ? !!node.value.trim() : false);
return (_a = textNode === null || textNode === void 0 ? void 0 : textNode.value.trim()) !== null && _a !== void 0 ? _a : '';
}
function removeTextContent(recorder, templateOffset, element) {
element.childNodes.forEach((node) => {
var _a, _b, _c, _d;
if (node.nodeName !== '#text') {
return;
}
const textNode = node;
const start = (_b = (_a = textNode.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset) !== null && _b !== void 0 ? _b : 0;
const end = (_d = (_c = textNode.sourceCodeLocation) === null || _c === void 0 ? void 0 : _c.endOffset) !== null && _d !== void 0 ? _d : start;
if (!textNode.value.trim()) {
return;
}
recorder.remove(templateOffset + start, end - start);
});
}
function formatControlAttrs(attrs) {
return attrs
.map(({ name, value }) => `${normalizeAttrName(name)}="${value}"`)
.join(' ');
}
function normalizeAttrName(name) {
switch (name.toLowerCase()) {
case '[(ngModel)]'.toLowerCase():
return '[(ngModel)]';
case '[formControl]'.toLowerCase():
return '[formControl]';
case '[ngModel]'.toLowerCase():
return '[ngModel]';
case 'formControl'.toLowerCase():
return 'formControl';
case 'formControlName'.toLowerCase():
return 'formControlName';
case 'ngModel'.toLowerCase():
return 'ngModel';
default:
return name;
}
}
function wrapTextInLabel(recorder, templateOffset, element) {
var _a, _b, _c, _d;
const textNode = element.childNodes.find((node) => isTextNode(node) && !!node.value.trim());
if (!textNode) {
return;
}
const start = ((_b = (_a = textNode.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.startOffset) !== null && _b !== void 0 ? _b : 0) + templateOffset;
const end = ((_d = (_c = textNode.sourceCodeLocation) === null || _c === void 0 ? void 0 : _c.endOffset) !== null && _d !== void 0 ? _d : 0) + templateOffset;
recorder.insertRight(start, '\n<label tuiLabel>');
recorder.insertRight(end, '</label>\n');
}
function isTextNode(node) {
return node.nodeName === '#text';
}
//# sourceMappingURL=migrate-select.js.map