Angular 2中的语法高亮显示

Angular 2中的语法高亮显示,angular,syntax-highlighting,Angular,Syntax Highlighting,我正在使用angular 2创建简单的web应用程序。我有两个部分。第一个基本上是包含一些数据行的表。执行“单击行”时,与行相对应的数据将显示在第二个组件中。数据是XML,加载到代码元素。看起来像 @Component export class TableComponent { items: Data[]; selectedItemsXml: string; // ...other stuff //when row is clicked toggleSe

我正在使用angular 2创建简单的web应用程序。我有两个部分。第一个基本上是包含一些数据行的表。执行“单击行”时,与行相对应的数据将显示在第二个组件中。数据是XML,加载到代码元素。看起来像

@Component
export class TableComponent {
    items: Data[];
    selectedItemsXml: string;
    // ...other stuff

    //when row is clicked
    toggleSelectedRow(rowIndex: number) {
        // ...other stuff related to change row's background color
        this.selectedItemsXml = this.items[i].xml;
    }
    // ...other stuff again
}

//TableComponent's template
<div>
    <table>
        ...
        ...*ngFor="let item of items; let i = index;"...
        <tr (click)="toggleSelectedRow(i)">
            <td>{{item.id}}</td>
            <td>{{item.time}}</td>
        </tr>
        ...
    </table>
</div>
<xml-detail [xml]="selectedItemsXml"></xml-detail>

@Component
export class XmlDetailComponent {
    @Input() xml: string;
}

//XmlDetailComponent's template
<div>
    <pre><code>{{xml}}</code></pre>
</div>
在我想为xml添加语法高亮显示之前,一切都很顺利。首先,我想使用插件ng2 prism,但在使其正常工作时遇到了问题。在我看到它的git回购协议出现问题后,我把它扔掉了。我接下来尝试的是基于以下帖子使用highlight.js创建指令:。使用此方法突出显示Xml,但仅在第一次单击行时突出显示。单击另一行时,甚至不会显示新的xml。我也尝试过使用prism.js,但我得到了相同的行为。一旦某个xml字符串第一次绑定、显示在代码元素中并使用highlight.js或prism.js高亮显示,它将保持不变

我猜这与angular 2中DOM和数据绑定的工作方式有关,因为在不使用语法高亮显示的情况下,每次选择行时,我都会绑定字符串并将其传递给代码元素。使用高亮显示可以绑定字符串,将其传递给代码元素,然后对其进行预加密。这意味着代码元素中没有简单的字符串,而是有很多样式化的span元素,这会导致在选择新行时加载新xml字符串时出现问题。我还尝试使用Prism.highlight(text_to_pretified)绑定“pre-pre-pretified”字符串,但使用此方法会导致显示包含由Prism添加的所有span元素的xml


现在,我正在绞尽脑汁思考如何解决这个问题。请给我一些动力,我如何才能使它工作。

我将创建一个利用PRISMJ的组件

包括prismjs脚本,包括所需组件文件夹中的任何脚本

Index.html


安装Prism的最新类型定义文件(这将为您提供类型安全):

npm安装@ryancavanaugh/prismjs
注意:不要安装@types/prismjs-它可能已过期或编写不正确。
prismjs
的作者推荐@ryancvanaugh/prismjs作为类型定义

将文件夹添加到
tsconfig.json
中的
typeRoots
列表属性中,以便typescript编译器可以找到它:

tsconfig.json(在编译器选项下)

“类型根”:[
“节点\模块/@类型”,
“节点_模块/@ryancavanaugh”
]
创建调用
prism的自定义
prism
组件。突出显示

prism.component.ts

//
导入{
组成部分,
AfterViewInit,
输入,
ElementRef,
视图儿童
}从“@angular/core”开始;
@组成部分({
moduleId:module.id,
选择器:“棱镜”,
模板:`
像这样使用它:


var x=3;
T类
{{ '{' }}
{{ '}' }}

您可以尝试我为Angular 2/4编写的这个简单组件,因为它已不再维护,并且不适用于最新的Angular版本。

我使用PixelBits解决方案,只需进行少量更改,首先确保您不在App.component.ts文件中尝试prism组件,您将获得“检查后视图已更改”如果重新加载页面,将不会调用error和ngAfterViewInit()。因此,请创建一个基本路由,并创建一个页面,然后在该新页面中尝试使用prism组件。 接下来,如果您想使用行号插件,Prism.highlight将无法工作。您需要使用Prism.highlightElement。 同样,使用PixelBits解决方案,您可以在代码前后获得空白空间。 不要忘记更改引用路径url,使其与您的项目匹配

ts:

和html:


另外,我没有使用npm获取prism.js,但我是从prism官方网站获取的(行号插件集成在prism.js中)。

我不确定“选择新行时加载新xml字符串”是什么意思。你能澄清这个问题吗?您好,我添加了一个简短的代码示例。现在可能更清楚了。我能够将这个答案与@Vaibhav提供的回购协议结合起来使用。多亏了大家!我遇到了一个错误:
error ReferenceError:Prism在尝试调用
this.content=Prism.highli时未定义
ght(this.rawContent.nativeElement.innerHTML,Prism.languages[this.language]);
在我的Prism组件上:(angular prism对我来说工作得很好。我花了很长时间制作了自己的,这就更好了。谢谢你!使用你制作的东西和最初的prism源代码,我编写了一个版本,在typescript/angular 2/4中本机工作,而无需导入任何单独的、普通的javascript库。它只是一个服务、一个组件,以及用于语法主题,打包到NgModule中。我以前从未向Github贡献过任何东西,所以我对它的工作原理一无所知。我应该创建一个全新的回购并将其作为单独的东西上传吗?还是应该将其贡献给您的,看看您是否可以将其合并?@diopside您可以使用一个Yeoman生成器来创建gular library软件包。一旦成功,将代码推送到git repo,您还可以在npm上发布您的模块。您可以在internet上轻松找到所有这些步骤的指南
export class PrismComponent implements OnInit,AfterViewInit {
    @Input() language: string;
    @ViewChild("rawContent") rawContent: ElementRef;
    @ViewChild("codeRef") codeRef: ElementRef;
    content: string;
    myClass:string;

    constructor(
        private elementRef:ElementRef,
    ) {
    }

    ngOnInit(){
        this.myClass = "language-" + this.language;
    }

    ngAfterViewInit() {
        // trim because ng-content add space
        this.content = this.rawContent.nativeElement.innerHTML.trim();
        // make line number plugin work.
        Prism.highlightElement(this.codeRef.nativeElement,true);
    }
}
<pre class="line-numbers"><code #codeRef [innerHTML]="content" [class]="myClass"></code></pre>
<div style="display: none;" hidden="true" #rawContent>
  <ng-content></ng-content>
</div>