mozilla / nunjucks

A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)
https://mozilla.github.io/nunjucks/
BSD 2-Clause "Simplified" License
8.54k stars 638 forks source link

nunjucks set json schema #1219

Closed illvart closed 5 years ago

illvart commented 5 years ago

How to use nunjucks set to my json schema?

{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "url": "{{ metadata.url }}",
  "potentialAction": {
    "@type": "SearchAction",
    "target": "{{ metadata.url }}/search?q={search_term_string}",
    "query-input": "required name=search_term_string"
  }
}

Use like this:

<script type="application/ld+json">
{{ search | jsonMinify | safe }}
</script>

Note: I want to use this to enable json minify with pretty-data.

fdintino commented 5 years ago

You have two options:

  1. Use set as a block tag:
{% set search %}
{
  "@context": "https://schema.org",
  ...
}
{% endset %}
<script type="application/ld+json">
{{ search | jsonMinify | safe }}
</script>
  1. create a custom tag using CallExtension. I haven't tested it, but the code would look something like:
function JsonMinifyExtension() {
  this.tags = ['jsonminify'];

  this.parse = function(parser, nodes, lexer) {
    var tok = parser.nextToken();
    parser.advanceAfterBlockEnd(tok.value);

    var body = parser.parseUntilBlocks('endjsonminify');
    parser.advanceAfterBlockEnd();

    return new nunjucks.nodes.CallExtension(this, 'run', null, [body]);
  };

  this.run = function(context, body) {
    var minified = pd.jsonmin(body());
    return new nunjucks.runtime.SafeString(minified);
  };
}

env.addExtension('JsonMinifyExtension', new JsonMinifyExtension());

and then in your template:


<script type="application/ld+json">
{% jsonminify %}
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "url": "{{ metadata.url }}",
  "potentialAction": {
    "@type": "SearchAction",
    "target": "{{ metadata.url }}/search?q={search_term_string}",
    "query-input": "required name=search_term_string"
  }
}
{% endjsonminify %}
</script>
illvart commented 5 years ago

Wow, thank you! @fdintino.

By the way I use nunjucks on Eleventy @zachleat.

At first time I used include and eleventyConfig.addFilter jsonMinify. This is works like this:

{% set search %}{% include "json/search.njk" %}{% endset %}
<script type="application/ld+json">
{{ search | jsonMinify | safe }}
</script>

And your @fdintino two options work well!

In your second option, I use eleventyConfig.addNunjucksTag and this works perfectly as below:

const prettyData = require("pretty-data").pd;
module.exports = function(eleventyConfig) {
  eleventyConfig.addNunjucksTag("jsonminify", function(nunjucksEngine) {
    return new (function() {
      this.tags = ["jsonminify"];

      this.parse = function(parser, nodes, lexer) {
        var tok = parser.nextToken();
        parser.advanceAfterBlockEnd(tok.value);
        var body = parser.parseUntilBlocks("endjsonminify");
        parser.advanceAfterBlockEnd();
        return new nodes.CallExtension(this, "run", null, [body]);
      };

      this.run = function(context, body) {
        var minified = prettyData.jsonmin(body());
        return new nunjucksEngine.runtime.SafeString(minified);
      };

    })();
  });
};

Now I use the second option because simple and fast!

Solved!