Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A [feature-rich](https://livecodes.io/docs/features/), open-source, **client-sid
[![LiveCodes: npm version](https://img.shields.io/npm/v/livecodes)](https://www.npmjs.com/package/livecodes)
[![LiveCodes: npm downloads](https://img.shields.io/npm/dm/livecodes)](https://www.npmjs.com/package/livecodes)
[![LiveCodes: jsdelivr downloads](https://data.jsdelivr.com/v1/package/npm/livecodes/badge?style=rounded)](https://www.jsdelivr.com/package/npm/livecodes)
[![LiveCodes: languages](https://img.shields.io/badge/languages-95-blue)](https://livecodes.io/docs/languages/)
[![LiveCodes: languages](https://img.shields.io/badge/languages-96-blue)](https://livecodes.io/docs/languages/)
[![LiveCodes: docs](https://img.shields.io/badge/Documentation-575757?logo=gitbook&logoColor=white)](https://livecodes.io/docs/)
[![LiveCodes: llms.txt](https://img.shields.io/badge/llms.txt-575757?logo=googledocs&logoColor=white)](https://livecodes.io/docs/llms.txt)
[![LiveCodes: llms-full.txt](https://img.shields.io/badge/llms--full.txt-575757?logo=googledocs&logoColor=white)](https://livecodes.io/docs/llms-full.txt)
Expand Down
151 changes: 151 additions & 0 deletions docs/docs/languages/jinja.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Jinja

[Jinja](https://jinja.palletsprojects.com/) is a fast, expressive, extensible templating engine. Special placeholders in the template allow writing code similar to Python syntax. Then the template is passed data to render the final document.

LiveCodes uses a [minimalistic JavaScript implementation](https://github.com/huggingface/huggingface.js/tree/main/packages/jinja).

## Usage

There are 2 modes for rendering:

### Pre-rendered (Default)

The values of the expressions are evaluated and added to the template during compilation of the [result page](../features/result.mdx).

The values of all expressions should be supplied in advance using [custom settings](../advanced/custom-settings.mdx) to the property `template.data` which accepts an object of key-value pairs.

Example: This provides the value of the expression `name`

```json title="Custom Settings"
{
"template": {
"data": {
"name": "LiveCodes"
}
}
}
```

[Full example below](#pre-rendered)

### Dynamic

To use this mode, the property `template.prerender` in [custom settings](../advanced/custom-settings.mdx) should be set to `false`.

Example:

```json title="Custom Settings"
{
"template": {
"prerender": false
}
}
```

In this mode, in addition to values supplied in custom settings (see above), expressions can have values that are evaluated during the [result page](../features/result.mdx) runtime.

This can be achieved in JavaScript (or any [language](../languages/index.mdx) that compiles to it) by assigning `window.livecodes.templateData` to an object with the data.

Please note that template rendering occurs on [page load](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event), so the assignment must occur before that.

Example:

```js title="Script Editor (JS)"
window.livecodes.templateData = { name: 'LiveCodes' };
```

[Full example below](#dynamic-1)

## Language Info

### Name

`jinja`

### Extension

`.jinja`

### Editor

`markup`

## Compiler

[@huggingface/jinja](https://www.npmjs.com/package/@huggingface/jinja).

### Version

`@huggingface/jinja`: v0.5.0

## Code Formatting

Using `@huggingface/jinja` integrated formatted.

## Example Usage

import LiveCodes from '../../src/components/LiveCodes';

### Pre-rendered

export const config = {
markup: { language: 'jinja', content: `<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>

<h1>My Webpage</h1>
{{ a_variable }}

` },
customSettings: { template: { data: {
navigation: [
{ href: "/", caption: "Home" },
{ href: "/about", caption: "About" },
{ href: "/contact", caption: "Contact" },
],
a_variable: "Hello World!",
} } },
};

export const params = { compiled: 'open' };

<LiveCodes config={config} params={params}></LiveCodes>

### Dynamic

export const config2 = {
markup: { language: 'jinja', content: `<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>

<h1>My Webpage</h1>
{{ a_variable }}

` },
script: {
language: 'javascript',
content: `window.livecodes.templateData = {
navigation: [
{ href: "/", caption: "Home" },
{ href: "/about", caption: "About" },
{ href: "/contact", caption: "Contact" },
],
a_variable: "Hello World!",
};`,
},
customSettings: { template: { prerender: false } },
activeEditor: 'script',
};

<LiveCodes config={config2}></LiveCodes>

## Links

- [Jinja](https://jinja.palletsprojects.com/)
- [Template Documentation](https://jinja.palletsprojects.com/en/stable/templates/)
- [`@huggingface/jinja`](https://www.npmjs.com/package/@huggingface/jinja)

1 change: 1 addition & 0 deletions docs/src/components/LanguageSliders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default function Sliders() {
{ name: 'twig', title: 'Twig' },
{ name: 'vento', title: 'Vento' },
{ name: 'art-template', title: 'art-template' },
{ name: 'jinja', title: 'Jinja' },
{ name: 'bbcode', title: 'BBCode' },
{ name: 'mjml', title: 'MJML' },
{ name: 'diagrams', title: 'Diagrams' },
Expand Down
54 changes: 54 additions & 0 deletions e2e/specs/compilers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,60 @@ const title = "World";
expect(resultText).toContain('Welcome to art-template');
});

test('jinja', async ({ page, getTestUrl }) => {
await page.goto(getTestUrl());

const { app, getResult, waitForResultUpdate } = await getLoadedApp(page);

await app.click('[aria-label="Project"]');
await app.click('text=Custom Settings');
await waitForEditorFocus(app, '#custom-settings-editor');
await page.keyboard.press('Control+A');
await page.keyboard.press('Delete');
await page.keyboard.type(`{"template":{"data":{"name": "jinja"}}}`);
await app.click('button:has-text("Load"):visible');

await app.click(':nth-match([title="Change Language"], 1)');
await app.click('text="Jinja"');
await waitForEditorFocus(app);
await page.keyboard.type(`<h1>Welcome to {{ name }}</h1>`);

await waitForResultUpdate();
const resultText = await getResult().innerHTML('h1');

expect(resultText).toContain('Welcome to jinja');
});

test('jinja dynamic', async ({ page, getTestUrl }) => {
await page.goto(getTestUrl());

const { app, getResult, waitForResultUpdate } = await getLoadedApp(page);

await app.click('[aria-label="Project"]');
await app.click('text=Custom Settings');
await waitForEditorFocus(app, '#custom-settings-editor');
await page.keyboard.press('Control+A');
await page.keyboard.press('Delete');
await page.keyboard.type(`{"template":{"prerender": false}}`);
await app.click('button:has-text("Load"):visible');

await app.click(':nth-match([title="Change Language"], 3)');
await app.click('text=JavaScript');
await waitForEditorFocus(app);
await page.keyboard.type(`window.livecodes.templateData = { name: 'jinja' };`);

await app.click(':nth-match([title="Change Language"], 1)');
await app.click('text="Jinja"');
await waitForEditorFocus(app);
await page.keyboard.type(`<h1>Welcome to {{ name }}</h1>`);

await waitForResultUpdate();
await app.waitForTimeout(3000);
const resultText = await getResult().innerHTML('h1');

expect(resultText).toContain('Welcome to jinja');
});

test('BBCode', async ({ page, getTestUrl }) => {
await page.goto(getTestUrl());

Expand Down
1 change: 1 addition & 0 deletions scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ const iifeBuild = () =>
'languages/haml/lang-haml-compiler.ts',
'languages/handlebars/lang-handlebars-compiler.ts',
'languages/imba/lang-imba-compiler.ts',
'languages/jinja/lang-jinja-compiler.ts',
'languages/julia/lang-julia-script.ts',
'languages/liquid/lang-liquid-compiler.ts',
'languages/lua-wasm/lang-lua-wasm-script.ts',
Expand Down
34 changes: 34 additions & 0 deletions src/livecodes/html/language-info.html
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,40 @@ <h3 data-i18n="language-info:java.name">Java</h3>
</li>
</ul>
</section>
<section data-lang="jinja">
<h3 data-i18n="language-info:jinja.name">Jinja</h3>
<div data-i18n="language-info:jinja.desc">
Jinja is a fast, expressive, extensible templating engine.
</div>
<ul data-i18n="language-info:jinja.link" data-i18n-prop="innerHTML">
<li>
<a href="https://jinja.palletsprojects.com/" target="_blank" rel="noopener"
>Official website</a
>
</li>
<li>
<a
href="https://jinja.palletsprojects.com/en/stable/templates/"
target="_blank"
rel="noopener"
>Template documentation</a
>
</li>
<li>
<a
href="https://github.com/huggingface/huggingface.js/tree/main/packages/jinja"
target="_blank"
rel="noopener"
>JavaScript implementation</a
>
</li>
<li>
<a href="{{DOCS_BASE_URL}}languages/jinja" target="_blank" rel="noopener"
>LiveCodes Documentations</a
>
</li>
</ul>
</section>
<section data-lang="jsx">
<h3 data-i18n="language-info:jsx.name">JSX</h3>
<div data-i18n="language-info:jsx.desc">
Expand Down
12 changes: 12 additions & 0 deletions src/livecodes/i18n/locales/en/language-info.lokalise.json
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,18 @@
"notes": "",
"translation": "Java"
},
"jinja.desc": {
"notes": "",
"translation": "Jinja is a fast, expressive, extensible templating engine."
},
"jinja.link": {
"notes": "### <tag-1> ###\n<li />\n\n### <tag-2> ###\n<a href=\"https://jinja.palletsprojects.com/\" target=\"_blank\" rel=\"noopener\" />\n\n### <tag-3> ###\n<li />\n\n### <tag-4> ###\n<a href=\"https://jinja.palletsprojects.com/en/stable/templates/\" target=\"_blank\" rel=\"noopener\" />\n\n### <tag-5> ###\n<li />\n\n### <tag-6> ###\n<a href=\"https://github.com/huggingface/huggingface.js/tree/main/packages/jinja\" target=\"_blank\" rel=\"noopener\" />\n\n### <tag-7> ###\n<li />\n\n### <tag-8> ###\n<a href=\"{{DOCS_BASE_URL}}languages/jinja\" target=\"_blank\" rel=\"noopener\" />\n\n",
"translation": "<tag-1> <tag-2>Official website</tag-2> </tag-1> <tag-3> <tag-4>Template documentation</tag-4> </tag-3> <tag-5> <tag-6>JavaScript implementation</tag-6> </tag-5> <tag-7> <tag-8>LiveCodes Documentations</tag-8> </tag-7>"
},
"jinja.name": {
"notes": "",
"translation": "Jinja"
},
"jsx.desc": {
"notes": "",
"translation": "JSX is compiled to JavaScript in LiveCodes using the TypeScript Compiler. By default it uses React as the JSX runtime."
Expand Down
5 changes: 5 additions & 0 deletions src/livecodes/i18n/locales/en/language-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ const languageInfo = {
link: '<1> <2>Java official website</2> </1> <3> <4>DoppioJVM</4> </3> <5> <6>Learn X in Y minutes, where X=java</6> </5> <7> <8>LiveCodes Documentation</8> </7> <9> <10>Load starter template</10> </9>',
name: 'Java',
},
jinja: {
desc: 'Jinja is a fast, expressive, extensible templating engine.',
link: '<1> <2>Official website</2> </1> <3> <4>Template documentation</4> </3> <5> <6>JavaScript implementation</6> </5> <7> <8>LiveCodes Documentations</8> </7>',
name: 'Jinja',
},
jsx: {
desc: 'JSX is compiled to JavaScript in LiveCodes using the TypeScript Compiler. By default it uses React as the JSX runtime.',
link: '<1> <2>React official website</2> </1> <3> <4>JSX in React documentation</4> </3> <5> <6>LiveCodes Documentations</6> </5>',
Expand Down
1 change: 1 addition & 0 deletions src/livecodes/languages/jinja/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lang-jinja';
28 changes: 28 additions & 0 deletions src/livecodes/languages/jinja/lang-jinja-compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { CompilerFunction } from '../../models';
import { escapeCode } from '../../utils';
import { jinjaUrl } from './lang-jinja';

(self as any).createJinjaCompiler =
(): CompilerFunction =>
async (code, { config }) => {
const data = config.customSettings.template?.data || {};
if (config.customSettings.template?.prerender !== false) {
const template = new (self as any).Jinja.Template(code);
return template.render(data);
}
return `<!-- ... compiling ... -->

<script src="${jinjaUrl}"></script>
<script>
window.addEventListener("load", () => {
const template = new Jinja.Template(\`${escapeCode(code)}\`);
const content = template.render({
...${escapeCode(JSON.stringify(data || {}))},
...window.livecodes?.templateData,
});
document.body.innerHTML += content
parent.postMessage({type: 'compiled', payload: {language: 'jinja', content}}, '*');
});
</script>
`;
};
30 changes: 30 additions & 0 deletions src/livecodes/languages/jinja/lang-jinja.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { LanguageSpecs } from '../../models';
import { vendorsBaseUrl } from '../../vendors';

export const jinjaUrl = `${vendorsBaseUrl}jinja/jinja.js`;

export const jinja: LanguageSpecs = {
name: 'jinja',
title: 'Jinja',
formatter: {
factory: () => {
(self as any).importScripts(jinjaUrl);
return async (code, cursorOffset, formatterConfig) => {
const formatted = new (self as any).Jinja.Template(code).format({
indent: formatterConfig?.tabSize || 2,
});
return { formatted, cursorOffset };
};
},
},
compiler: {
url: jinjaUrl,
factory: (_config, baseUrl) => {
(self as any).importScripts(baseUrl + '{{hash:lang-jinja-compiler.js}}');
return (self as any).createJinjaCompiler();
},
},
extensions: ['jinja'],
editor: 'markup',
editorLanguage: 'html',
};
2 changes: 2 additions & 0 deletions src/livecodes/languages/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import { vento } from './vento';
import { react, reactTsx } from './react';
import { java } from './java';
import { csharpWasm } from './csharp-wasm';
import { jinja } from './jinja';
export const languages: LanguageSpecs[] = [
html,
markdown,
Expand All @@ -95,6 +96,7 @@ export const languages: LanguageSpecs[] = [
twig,
vento,
artTemplate,
jinja,
bbcode,
mjml,
diagrams,
Expand Down
2 changes: 1 addition & 1 deletion src/livecodes/vendors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { modulesService } from './services/modules';
const { getUrl, getModuleUrl } = modulesService;

export const vendorsBaseUrl = // 'http://127.0.0.1:8081/';
/* @__PURE__ */ getUrl('@live-codes/browser-compilers@0.22.2/dist/');
/* @__PURE__ */ getUrl('@live-codes/browser-compilers@0.22.3/dist/');

export const acornUrl = /* @__PURE__ */ getUrl('acorn@8.12.1/dist/acorn.js');

Expand Down
Loading