如何使用角度示意图修改文件

use*_*102 4 angular angular-schematics

假设我们有一个现有的角度组件,包括menu.component.html

<ul>
  <li><a href="/home">home</a></li>
  <li><a href="/about">about</a></li>
</ul>
Run Code Online (Sandbox Code Playgroud)

目标是在“大约”之后添加带有角度示意图的新链接。

 <li><a href="/contact">contact</a></li>
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

eko*_*eko 8

您可以执行以下操作:

export function myComponent(options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    const content: Buffer | null = tree.read("./menu.component.html");
    let strContent: string = '';
    if(content) strContent = content.toString();

    const appendIndex = strContent.indexOf('</ul>');
    const content2Append = '    <li><a href="/contact">contact</a></li> \n';
    const updatedContent = strContent.slice(0, appendIndex) + content2Append + strContent.slice(appendIndex);

    tree.overwrite("./menu.component.html", updatedContent);
    return tree;
  };
}
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个非常原始的解决方案。nodejs中有DOM解析器库,可以简化您的生活(jsdom)。您可以将content2Append变量作为输入,并为您的用例进行清理。


Mar*_*tin 6

Eko的回答是正确的。我想扩展这个答案并做两件事:

  1. 使用树记录器更新模板
  2. 使用jsdom在模板中查找位置进行更新

使用 jsdom 和类似的工具,序列化一个 Angular 模板要么不起作用——或者破坏任何驼峰、[boxed]、(括号)、#tagged——属性。所以我们只会使用 jsdom 来查找我们想要更新的位置。

function updateTemplate() {
  return (tree: Tree) => {
    const buffer = tree.read(TEMPLATE_PATH);
    const content = buffer?.toString();
    if (!content) {
      throw new SchematicsException(`Template ${TEMPLATE_PATH} not found`);
    }

    // the includeLocations flag is very important here
    const dom = new JSDOM(content, { includeNodeLocations: true });
    const element = dom.window.document.querySelector('ul');
    const locations = dom.nodeLocation(element);
    if (!locations) {
      throw new SchematicsException(`<ul> could not be found in ${TEMPLATE_PATH}`);
    }

    // now we update the template using the tree recorder
    // we don't use jsdom to directly update the template
    const recorder = tree.beginUpdate(TEMPLATE_PATH);
    const listItem = `  <li><a href="/contact">contact</a></li>\n`
    recorder.insertLeft(locations.endTag.startOffset, listItem);
    tree.commitUpdate(recorder);

    return tree;
  };
}
Run Code Online (Sandbox Code Playgroud)

同样,eko 的答案是正确的。这个答案说明了如何一起使用 jsdom 和树记录器来更新 Angular 模板——这对于将指令、事件、标签和方法插入元素、包装部分和更复杂的转换非常有用。