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

Posted

技术标签:

【中文标题】如何使用角度示意图修改 HTML 文件【英文标题】:How to modify a HTML file with angular schematics 【发布时间】:2018-12-24 05:05:02 【问题描述】:

假设我们有一个现有的角度组件,包括 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>

有什么想法吗?

【问题讨论】:

您对如何构建自己的原理图了解多少?有没有浏览过这样的文章:medium.com/@tomastrajan/… 我浏览了很多文章。我找到了修改特定元素的示例,例如模块中的构造函数或声明。这是一个例子link。 【参考方案1】:

你可以这样做:

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 变量作为输入并为您的用例清理它。

【讨论】:

不幸的是 jsdom 不支持角度模板语法,我一直在尝试寻找可以帮助我添加和操作模板的模板解析器,任何建议将不胜感激! @saKins 在如何使用 jsdom 和树记录器更新 Angular 模板方面看到我的答案。【参考方案2】:

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

    使用树记录器更新模板 使用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.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;
  ;

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

【讨论】:

仅供参考,简单的 htmlparser 库似乎能够在不破坏 Angular 特定属性的情况下读取 HTML。您可以相当轻松地修改 DOM。将其重写为字符串并不那么简单。【参考方案3】:

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


我正在测试图形学,我还需要更新角度组件模板。 这是一篇有用的文章:

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

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

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

我希望这可以帮助:)

【讨论】:

以上是关于如何使用角度示意图修改 HTML 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何修改默认意图相机[关闭]

接收到 websocket 消息后,如何从组件 **ts** 文件中重新呈现角度组件视图?

自定义角度示意图:管道“dasherize”未定义。在角度项目上运行时

如何使用角度访问 HTML 中的 JSON 数组对象?

如何用角度示意图覆盖文件?

如何使用角度修改 asp.net 核心 WebAPI 的 asp.net 身份 UI