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

时间:2018-07-16 15:31:14

标签: angular angular-schematics

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

<ul>
  <li><a href="/home">home</a></li>
  <li><a href="/about">about</a></li>
</ul>

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

 <li><a href="/contact">contact</a></li>

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

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

  1. 使用树记录器更新模板
  2. 使用jsdom在模板中找到要更新的位置

使用jsdom和类似工具,序列化Angular模板将不起作用-或破坏任何camelCase,[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.nodeLocations(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;
  };
}

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

答案 1 :(得分:3)

您可以执行以下操作:

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;
  };
}

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

答案 2 :(得分:0)

更新:使用最新的1.0.0rc3 cheerio版本,xmlMode会自动关闭标签,这会杀死您的模板! 因此,改为使用 0.22.0 cheerio 版本并丢失xmlMode选项!


我正在测试Shematic,并且还需要更新角度分量模板。 这是一篇有用的文章:

https://medium.com/humanitec-developers/update-and-insert-auto-generated-code-to-existing-typescript-html-and-json-files-with-angular-9b37bdadf041

现在,要小心,对于最新版本的cheerio,您应该使用xmlMode选项加载组件模板,否则,您将拥有一个完整的HTML文档:

https://github.com/cheeriojs/cheerio/issues/1031#issuecomment-368307598

您最终将以这种方式向Angular模板中添加一些HTML:

function addComponent(): Rule {
  return (tree: Tree) => {
    const filePath = './src/app/app.component.html';
    const content: Buffer | null = tree.read(filePath);
    let strContent: string = '';
    if(content) strContent = content.toString('utf8');
    const $ = cheerio.load(strContent, {
      xmlMode: true
    });
    const contentToInsert = `<my-comp></my-comp>`;
    $.root().append(contentToInsert);
    tree.overwrite(filePath, $.html());
    return tree;
  };
}

我希望这会有所帮助:)