vue-2-breadcrumbs icon indicating copy to clipboard operation
vue-2-breadcrumbs copied to clipboard

Custom template and Content Security Policy

Open Nincha opened this issue 3 years ago • 4 comments

Hi,

Thanks for the amazing work!

I'm using custom template like this, which is working fine on development environment:

Vue.use(VueBreadcrumbs, {
  template:  
  '  <nav v-if="$breadcrumbs.length" aria-label="breadcrumb" class="ncBreadcrumbs">\n' +  
  '    <localized-link class="icon-home-outline" tag="a" to="/""></localized-link>\n' +  
  '    <span v-for="(crumb, index, key) in $breadcrumbs" v-if="crumb.meta.breadcrumb" :key="key" class="breadcrumbItem" :class="[(index == $breadcrumbs.length - 1 ? \'breadcrumbCurrent\' : \'\')]" aria-current="page">\n' +  
  '      <span class="icon-right-open-outline"></span>' +  
  '      <localized-link v-if="index !== $breadcrumbs.length - 1" tag="a" to="{ path: getPath(crumb) }" class="breadcrumbText">{{ getBreadcrumb(crumb.meta.breadcrumbshort) }}</localized-link>' +  
  '      <span v-if="index == $breadcrumbs.length - 1" class="breadcrumbText" v-html="$t( getBreadcrumb(crumb.meta.breadcrumb) )"></span>' +  
  '    </span>\n' +  
  '  </nav>'  
});

It appears that the use of the custom template seems to require eval() or a similar method, and fails to load breadcrumbs into the page if 'unsafe-eval' isn't defined under script-src in the server's Content Security Policy headers.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src

Could you consider implementing custom template injection from a file template instead? Or maybe create a second implementation method, to allow old code compatibility ; that would allow the plugin to be compatible with secured server policies. :)

For the time being, I will keep it simple and inject a hard coded breadcrumb html on every page (as it's a small project, it's ok for that one but I will implement breadcrumbs in larger vue projects later in 2020, so that won't be possible on them 😅).

Cheers, Charlie

Nincha avatar Sep 10 '20 06:09 Nincha

@Nincha Hi, sorry for the long answer.

  1. Please note that I use a declarative approach to define the template.
  2. You can try using string template to define a template
  3. maybe it is worth giving up Runtime-only to the side Runtime + Compiler

Scrum avatar Sep 23 '20 09:09 Scrum

Could this be solved with slots? Perhaps a default slot for the root element and then a repeated slot for the items within, providing the scoped data one would need to use an alternative set of components to render their breadcrumbs.

scottadamsmith avatar Sep 16 '21 16:09 scottadamsmith

Sorry I didn't see your answer @Scrum, the last message notified me just now. Thanks for the feedback, I'll try to give a try to your suggestions in a near future. :)

Nincha avatar Sep 16 '21 16:09 Nincha

Alternatively, I was able to use the custom templates with components by writing a render function instead of using the template string. Not ideal, but was able to get past it without a change in the library. I think slots would still be a nice touch for those that would still prefer to compose their template in a traditional single file component.

Here is what I wrote to use the this library with the breadcrumb components from boostrap-vue:

import Vue from "vue";
import VueBreadcrumbs from "vue-2-breadcrumbs";

Vue.use(VueBreadcrumbs, {
  render: function(c) {
    if (this.$breadcrumbs.length) {
      return c( "b-breadcrumb", this.$breadcrumbs.map((crumb, index) => {
          return crumb.meta.breadcrumb
            ? c(
                "b-breadcrumb-item",
                {
                  key: `breadcrumb-item-${index}`,
                  props: {
                    to: { path: this.getPath(crumb) }
                  }
                },
                this.getBreadcrumb(crumb.meta.breadcrumb)
              )
            : null;
        })
      );
    }
  }
});

scottadamsmith avatar Sep 16 '21 16:09 scottadamsmith