Attila Kling
Attila Kling

Reputation: 1787

Telling angular not to parse certain HTML block

For the context I'm building syntax highlighting for my angular (1.5.8) application. For syntax highlighting I use Prism.js which unfortunately can't highlight my code when I use ng-include in my HTML. Quite understandable since it introduces asynchronity. So to overcome the problem I'm creating an angular directive so that I can write something like this:

<prism lang="html">
  <md-toolbar layout layout-align="end center"></md-toolbar>
</prism>

Then in my directive I'm runnin the contents of the directive through Prism.highlight(transclusion, Prism.languages[this.lang]) so far so good. It works, but the only problem is, that angular parses my transclusion beforehand and modifies my input html that it adds additional classes because of my used layout and layout-align directives.

Here lies my question. Can I tell angular that "do not parse this chunk of code"?

Edit: I tried to wrap the input in <pre></pre> but that didn't help. Angular still parsed it and added classes.

Edit2: While I'm writing this I have an idea to put html elements outside of angular context giving them unique id. Then writing <prism code-id="some-unique-id"> then the directive could fetch the dom elem referenced by that uid and include it in the dom. Well, ugly af but could work am I right?

Edit3: I'm extending the post with more code so that you get the whole picture

1: In styleguide.html

<!-- MATERIAL DESIGN -->
<div id="material">
  <h1>Material design assets</h1>
  <div ng-include="'./material.html'"></div>
</div>

2: In material.html

<section>
  <h2>Dialog</h2>
  <md-button class="md-accent">Open sample dialog</md-button>

  <prism lang="html">
    <md-toolbar class="md-primary">
      <header class="md-toolbar-tools">
        <h3 class="md-headline">{{ 'Dialog title' | translate }}</h3>
        <!-- SPACER -->
        <span flex></span>
        <md-button class="md-icon-button" ng-click="ctrl.close()"><i class="material-icons">close</i></md-button>
      </header>
    </md-toolbar>
    <md-dialog-content>
      <div class="md-dialog-content">
        <!-- Content here -->
      </div>
    </md-dialog-content>
    <md-dialog-actions layout-padding layout layout-align="end center">
      <!-- stuff here -->
    </md-dialog-actions>
  </prism>
</section>

3: In the component

class PrismHighlighter {
    static get $descriptor() {
        return {
            controller: PrismHighlighter,
            template: `
                <pre>
                    <code class="language-{{$ctrl.lang}}">
                        <ng-transclude class="transclusion"></ng-transclude>
                    </code>
                </pre>
            `,
            transclude: true,
            bindings: {
                lang: '@'
            }
        }
    }

    static get $inject() {
        return ['$element'];
    }

    constructor($element) {
        this.element = $element;
    }

    $postLink() {
        const codeElem = this.element.find('code');
        const transclusion = $(this.element).find('ng-transclude').html();
        const hCode = Prism.highlight(transclusion, Prism.languages[this.lang]);
        codeElem.html(hCode);
    }
}
module.component('prism', PrismHighlighter.$descriptor);

4: And the output

enter image description here

Now you can clearly see that there are a lot of angular added things there what I don't want :/

Upvotes: 2

Views: 505

Answers (1)

Shaunak
Shaunak

Reputation: 18018

Use ng-non-bindable directive around it.

For Angular 1.x you can just use:

<div ng-non-bindable>
</div>

For angular 2.x this check this post that shows how to do the same.

Reference:

https://docs.angularjs.org/api/ng/directive/ngNonBindable

Upvotes: 1

Related Questions