Merge pull request #462 from Riverside-Healthcare/dev

This commit is contained in:
sur.la.route 2022-11-22 15:04:04 +01:00 committed by GitHub
commit 65fdfbd6f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 6928 additions and 5304 deletions

View file

@ -26,6 +26,27 @@ jobs:
- name: Setup Poetry
uses: snok/install-poetry@v1
- name: Update wheels in docs demo
run: |
# remove old wheels
rm -f docs/src/static/py/*
# build new wheels
poetry run pip wheel . -w docs/src/static/py
# rename wheels
cd docs/src/static/py
mv djlint* djlint-99-py3-none-any.whl
mv click* click-99-py3-none-any.whl
mv colorama* colorama-99-py3-none-any.whl
mv cssbeautifier* cssbeautifier-99-py3-none-any.whl
mv EditorConfig* EditorConfig-99-py3-none-any.whl
mv html_tag_names* html_tag_names-99-py3-none-any.whl
mv html_void_elements* html_void_elements-99-py3-none-any.whl
mv importlib_metadata* importlib_metadata-99-py3-none-any.whl
mv jsbeautifier* jsbeautifier-99-py3-none-any.whl
mv pathspec* pathspec-99-py3-none-any.whl
mv PyYAML* PyYAML-99-py3-none-any.whl
mv zipp* zipp-99-py3-none-any.whl
- name: Semantic Release
uses: cycjimmy/semantic-release-action@v3
@ -42,6 +63,6 @@ jobs:
- name: Build and publish package
if: steps.semantic.outputs.new_release_published == 'true'
uses: JRubics/poetry-publish@v1.13
uses: JRubics/poetry-publish@v1.15
with:
pypi_token: ${{ secrets.PYPI_API_TOKEN }}

View file

@ -9,7 +9,7 @@
"prepareCmd" : "poetry version ${nextRelease.version}"
}],
["@semantic-release/git", {
"assets": ["package.json", "pyproject.toml"]
"assets": ["package.json", "pyproject.toml", "docs"]
}],
"@semantic-release/github"
]

View file

@ -11,6 +11,8 @@ const outdent = require('outdent');
const schema = require('@quasibit/eleventy-plugin-schema');
const editOnGithub = require('eleventy-plugin-edit-on-github');
const i18n_func = require('eleventy-plugin-i18n/i18n.js');
const rollupper = require('./src/_utils/rollupper');
const { nodeResolve } = require('@rollup/plugin-node-resolve');
const slugifyCustom = (s) =>
slugify(s, { lower: true, remove: /[*+~.()'"!:@]/g });
@ -93,6 +95,15 @@ module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(metagen);
eleventyConfig.addPlugin(criticalCss);
eleventyConfig.addPlugin(schema);
eleventyConfig.addPlugin(rollupper, {
rollup: {
output: {
format: 'umd',
dir: '_site/static/js',
},
plugins: [nodeResolve()],
},
});
eleventyConfig.addPlugin(editOnGithub, {
// required
github_edit_repo: 'https://github.com/Riverside-Healthcare/djLint',
@ -190,6 +201,16 @@ module.exports = function (eleventyConfig) {
'src/static/img/favicon.ico': 'favicon.ico',
});
// copy wheels
eleventyConfig.addPassthroughCopy({
'src/static/py': 'static/py',
});
// copy python
eleventyConfig.addPassthroughCopy({
'src/static/js/worker.js': 'static/js/worker.js',
});
eleventyConfig.addFilter('jsonify', (text) => {
return JSON.stringify(text).replace(/(?:\\n\s*){2,}/g, '\\n');
});
@ -244,6 +265,7 @@ module.exports = function (eleventyConfig) {
'infinity',
'download',
'code-commit',
'spinner',
],
},
'_site/static/font/fontawesome/webfonts',

10385
docs/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "djlint_docs",
"version": "1.0.44",
"version": "1.0.46",
"description": "",
"main": "index.js",
"scripts": {
@ -13,23 +13,28 @@
"license": "AGPL-3.0-or-later",
"browserslist": "> 2%, not dead",
"dependencies": {
"@codemirror/lang-html": "^6.2.0",
"@codemirror/state": "^6.1.4",
"@creativebulma/bulma-divider": "^1.1.0",
"@fontsource/crimson-pro": "^4.5.8",
"@fontsource/rasa": "^4.5.8",
"@quasibit/eleventy-plugin-schema": "^1.9.1",
"@rollup/plugin-node-resolve": "^15.0.1",
"@sindresorhus/slugify": "^2.1.0",
"animate-sass": "^0.8.2",
"animate.css": "github:animate-css/animate.css",
"codemirror": "^6.0.1",
"eleventy-critical-css": "^1.1.0",
"eleventy-plugin-i18n": "^0.1.3",
"md5": "^2.3.0"
"md5": "^2.3.0",
"rollup": "^3.3.0"
},
"devDependencies": {
"@11ty/eleventy": "1.0.2",
"@11ty/eleventy-img": "2.0.1",
"@11ty/eleventy-plugin-syntaxhighlight": "4.2.0",
"@fontsource/inter": "4.5.14",
"@fortawesome/fontawesome-free": "6.2.0",
"@fortawesome/fontawesome-free": "6.2.1",
"@fullhuman/postcss-purgecss": "5.0.0",
"@toycode/markdown-it-class": "1.2.4",
"algoliasearch": "4.14.2",
@ -40,7 +45,7 @@
"cz-conventional-changelog": "3.3.0",
"eleventy-plugin-edit-on-github": "1.1.0",
"eleventy-plugin-metagen": "1.7.11",
"esbuild": "0.15.13",
"esbuild": "0.15.15",
"eslint": "8.27.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-plugin-import": "2.26.0",

View file

@ -135,4 +135,9 @@ module.exports = {
ru: 'Игнорирование Контент',
fr: 'Ignorer le Contenu',
},
try_online: {
'en-US': '🤩 Try Online',
ru: '🤩 Essayez',
fr: '🤩 Попробуйте онлайн',
},
};

View file

@ -34,6 +34,9 @@
<a class="navbar-item has-text-grey-dark umami--nav--bestpractices" href="{{ "lang_code_url" | i18n }}/docs/best-practices">
{{ "best_practices" | i18n }}
</a>
<a class="navbar-item has-text-grey-dark umami--nav--tryonline" href="{{ "lang_code_url" | i18n }}/demo">
{{ "try_online" | i18n }}
</a>
</div>
<div class="navbar-end mx-0">
<a class="navbar-item button is-white animated fadeIn umami--nav--github"

View file

@ -0,0 +1,91 @@
/*
rollup plugin from https://www.hoeser.dev/blog/2021-02-28-11ty-and-rollup/
*/
const rollup = require('rollup');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
module.exports = (eleventyConfig, options) => {
new Rollupper(eleventyConfig, options);
};
class Rollupper {
inputFiles = {};
rollupOptions = {};
constructor(eleventyConfig, { shortcode = 'rollup', rollup } = {}) {
this.rollupOptions = rollup;
eleventyConfig.on('beforeBuild', () => this.beforeBuild());
eleventyConfig.on('afterBuild', () => this.afterBuild());
// We want to use "this" in the callback function, so we save the class instance beforehand
const thisRollupper = this;
eleventyConfig.addAsyncShortcode(shortcode, function (...args) {
return thisRollupper.rollupperShortcode(this, ...args);
});
}
beforeBuild() {
this.inputFiles = {};
}
async rollupperShortcode(eleventyInstance, src, fileRelative = false) {
// Resolve to the correct relative location
if (fileRelative) {
src = path.join(path.dirname(eleventyInstance.page.inputPath), src);
}
// resolve to absolute, since rollup uses absolute paths
src = path.resolve(src);
// generate a unique name for the file.
// we take the first 6 chars of the sha256 of the absolute paths.
const fileHash = await new Promise(function (resolve, reject) {
const hash = crypto.createHash('sha256');
const input = fs.createReadStream(src);
input.on('error', reject);
input.on('data', function (chunk) {
hash.update(chunk);
});
input.on('close', function () {
resolve(hash.digest('hex'));
});
});
const scriptSrc = fileHash.substr(0, 6) + '.js';
// register for rollup bundling
this.inputFiles[src] = scriptSrc;
// calculate script src after bundling
const relativePath = path.relative(
eleventyInstance.page.outputPath,
path.join(this.rollupOptions.output.dir, scriptSrc),
);
return `<script src="${relativePath}" type="module"></script>`;
}
async afterBuild() {
// Return early if no JS was used, since rollup throws on empty inputs
if (!Object.keys(this.inputFiles).length) {
return;
}
const bundle = await rollup.rollup({
input: Object.keys(this.inputFiles),
...this.rollupOptions,
});
const inputFiles = this.inputFiles;
await bundle.write({
entryFileNames: (chunk) => {
return inputFiles[chunk.facadeModuleId];
},
...this.rollupOptions.output,
});
await bundle.close();
}
}

127
docs/src/demo.njk Normal file
View file

@ -0,0 +1,127 @@
---
layout: layout.njk
date: Last Modified
description: Online HTML Template formatter. Reformat your HTML templates online with djLint.
keywords: online template formatter, djLint, HTML, templates, formatter, linter, rules, online html template formatter
---
<div class="section">
<div class="container">
<h1 class="title is-3">Online HTML Template formatter using djLint!</h1>
<div class="block" id="djlint-status">
<span class="icon-text">
<span class="icon">
<i class="fas fa-spinner fa-spin"></i>
</span>
<span><strong>Loading djLint ..</strong></span>
</span>
</div>
<div class="columns is-hidden">
<div class="column is-narrow">
<form id="djlint-settings">
<div class="field">
<label class="label">Custom Blocks</label>
<div class="control">
<input id="settings-custom-blocks" class="input" type="text" placeholder="toc,example">
</div>
</div>
<div class="field">
<label class="label">Custom HTML</label>
<div class="control">
<input id="settings-custom-html" class="input" type="text" placeholder="mjml,simple-greeting,mj-\w+">
</div>
</div>
<div class="field">
<label class="label">Indent</label>
<div class="control">
<input id="settings-indent" class="input" type="text" placeholder="4">
</div>
</div>
<div class="field">
<label class="label">Blank Line after Tag</label>
<div class="control">
<input id="settings-blank-line-after-tag" class="input" type="text" placeholder="load,extends,include">
</div>
</div>
<div class="field">
<label class="label">Blank Line before Tag</label>
<div class="control">
<input id="settings-blank-line-before-tag" class="input" type="text" placeholder="load,extends,include">
</div>
</div>
<div class="field">
<label class="label">Profile</label>
<div class="control">
<div class="select">
<select id="settings-profile" >
<option value="html">html (default)</option>
<option value="django">django</option>
<option value="jinja">jinja</option>
<option value="nunjucks">nunjucks (nunjucks and twig)</option>
<option value="handlebars">handlebars (handlebars and mustache)</option>
<option value="golang">golang</option>
<option value="angular">angular</option>
</select>
</div>
</div>
</div>
<div class="field">
<label class="label">Max Line Length</label>
<div class="control">
<input id="settings-max-line-length" class="input" type="text" placeholder="80">
</div>
</div>
<div class="field">
<label class="label">Max Attribute Length</label>
<div class="control">
<input id="settings-max-attribute-length" class="input" type="text" placeholder="0">
</div>
</div>
<div class="field">
<label class="checkbox">
<input id="settings-format-attribute-template-tags" type="checkbox">
Format Attribute Template Tags
</label>
</div>
<div class="field">
<label class="checkbox">
<input id="settings-preserve-leading-space" type="checkbox">
Preserve Leading Space
</label>
</div>
<div class="field">
<label class="checkbox">
<input id="settings-preserve-blank-space" type="checkbox">
Preserve Blank Space
</label>
</div>
<div class="field">
<label class="checkbox">
<input id="settings-format-js" type="checkbox">
Format JS
</label>
</div>
<div class="field">
<label class="checkbox">
<input id="settings-format-css" type="checkbox">
Format CSS
</label>
</div>
</form>
</div>
<div class="column" id="djlint-input">
</div>
<div class="column" id="djlint-output">
</div>
</div>
</div>
</div>
{% rollup "src/static/js/editor.js" | url %}

View file

@ -380,7 +380,7 @@ pre .number {
background-color: unset;
}
pre {
pre:not(.CodeMirror-line) {
margin-bottom: 1.5rem !important;
}

View file

@ -5,6 +5,7 @@
@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/_mixins';
@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/_core';
@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/_sizing';
@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/_animated';
$fa-font-path: '/static/font/fontawesome/webfonts';
@font-face {
@ -66,6 +67,7 @@ $icons: (
circle-arrow-right: $fa-var-circle-arrow-right,
globe: $fa-var-globe,
code-commit: $fa-var-code-commit,
spinner: $fa-var-spinner,
);
@each $key, $value in $icons {

View file

@ -0,0 +1,167 @@
import { EditorView, basicSetup } from 'codemirror';
import { EditorState, Compartment } from '@codemirror/state';
import { html } from '@codemirror/lang-html';
let session_id = 0;
if (typeof Worker !== 'undefined') {
console.log('creating web worker ');
let w;
if (typeof w == 'undefined') {
w = new Worker('/static/js/worker.js');
}
function getConfig() {
let config = {};
const customBlocks = document.getElementById(
'settings-custom-blocks',
).value;
if (customBlocks) config['customBlocks'] = customBlocks;
const customHtml = document.getElementById('settings-custom-html').value;
if (customHtml) config['customHtml'] = customHtml;
const indent = document.getElementById('settings-indent').value;
if (indent) config['indent'] = indent;
const blankLineAfterTag = document.getElementById(
'settings-blank-line-after-tag',
).value;
if (blankLineAfterTag) config['blankLineAfterTag'] = blankLineAfterTag;
const blankLineBeforeTag = document.getElementById(
'settings-blank-line-before-tag',
).value;
if (blankLineBeforeTag) config['blankLineBeforeTag'] = blankLineBeforeTag;
const profile = document.getElementById('settings-profile').value;
if (profile) config['profile'] = profile;
const maxLineLength = document.getElementById(
'settings-max-line-length',
).value;
if (maxLineLength) config['maxLineLength'] = maxLineLength;
const maxAttributeLength = document.getElementById(
'settings-max-attribute-length',
).value;
if (maxAttributeLength) config['maxAttributeLength'] = maxAttributeLength;
const formatAttributeTemplateTags = document.getElementById(
'settings-format-attribute-template-tags',
).checked;
if (formatAttributeTemplateTags)
config['formatAttributeTemplateTags'] = formatAttributeTemplateTags;
const preserveLeadingSpace = document.getElementById(
'settings-preserve-leading-space',
).checked;
if (preserveLeadingSpace)
config['preserveLeadingSpace'] = preserveLeadingSpace;
const preserveBlankSpace = document.getElementById(
'settings-preserve-blank-space',
).checked;
if (preserveBlankSpace) config['preserveBlankSpace'] = preserveBlankSpace;
const formatJs = document.getElementById('settings-format-js').checked;
if (formatJs) config['formatJs'] = formatJs;
const formatCss = document.getElementById('settings-format-css').checked;
if (formatCss) config['formatCss'] = formatCss;
return config;
}
const runPython = (script) => {
session_id += 1;
w.postMessage({
config: getConfig(),
html: script,
id: session_id,
});
};
w.onmessage = (event) => {
const { id, type, message, ...data } = event.data;
if (type == 'status') {
const div = document.createElement('div');
div.innerText = message;
const status = document.getElementById('djlint-status');
status.insertBefore(div, status.lastElementChild);
if (message === 'ready') {
document.getElementById('djlint-status').classList.add('is-hidden');
document
.getElementById('djlint-settings')
.closest('.columns.is-hidden')
.classList.remove('is-hidden');
runPython(editor.state.doc.toString());
}
}
if ((type == 'error' || type == 'html') && id == session_id) {
setOutput(message);
} else {
console.log(event.data);
}
};
let timer;
let editor = new EditorView({
state: EditorState.create({
extensions: [
basicSetup,
html(),
EditorView.updateListener.of((v) => {
if (v.docChanged) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
runPython(v.state.doc.toString());
}, 100);
}
}),
],
doc: `<div>\n <p>Welcome to djLint online!</p>\n</div>`,
}),
parent: document.getElementById('djlint-input'),
});
let output = new EditorView({
state: EditorState.create({
extensions: [basicSetup, html()],
doc: ``,
readonly: true,
}),
parent: document.getElementById('djlint-output'),
});
// add pyodide returned value to the output
function setOutput(stdout) {
const currentValue = output.state.doc.toString();
const endPosition = currentValue.length;
output.dispatch({
changes: {
from: 0,
to: endPosition,
insert: stdout,
},
});
}
function setInput(stdout) {
const currentValue = editor.state.doc.toString();
const endPosition = currentValue.length;
editor.dispatch({
changes: {
from: 0,
to: endPosition,
insert: stdout,
},
});
}
document.getElementById('djlint-settings').addEventListener('change', () => {
runPython(editor.state.doc.toString());
});
} else {
// Sorry! No Web Worker support..
document
.getElementById('djlint-status')
.innerText(
'Sorry, a browser that supports web workers is required to use this online tool.',
);
}
// pass the editor value to the pyodide.runPython function and show the result in the output section
// document.getElementById("djlint-settings").addEventListener("change", () => {evaluatePython()})

View file

@ -0,0 +1,143 @@
importScripts('https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js');
function capitalize(raw_word) {
const word = raw_word.toString();
return word.charAt(0).toUpperCase() + word.slice(1);
}
async function loadPyodideAndPackages() {
const origin = location.origin;
self.pyodide = await loadPyodide();
// build wheels with pip wheel .
await self.pyodide.loadPackage([
`${origin}/static/py/djlint-99-py3-none-any.whl`,
`${origin}/static/py/click-99-py3-none-any.whl`,
`${origin}/static/py/colorama-99-py3-none-any.whl`,
`${origin}/static/py/cssbeautifier-99-py3-none-any.whl`,
`${origin}/static/py/EditorConfig-99-py3-none-any.whl`,
`${origin}/static/py/html_tag_names-99-py3-none-any.whl`,
`${origin}/static/py/html_void_elements-99-py3-none-any.whl`,
`${origin}/static/py/importlib_metadata-99-py3-none-any.whl`,
`${origin}/static/py/jsbeautifier-99-py3-none-any.whl`,
`${origin}/static/py/pathspec-99-py3-none-any.whl`,
`${origin}/static/py/PyYAML-99-py3-none-any.whl`,
`${origin}/static/py/zipp-99-py3-none-any.whl`,
]);
postMessage({
type: 'status',
message:
'Installing djlint, click, colorama, cssbeautifier, editorconfig, html_tag_names, html_void_elements, importlib_metadata, jsbeautifier, pathspec, pyyaml, zipp ..',
});
await self.pyodide.loadPackage('regex');
postMessage({ type: 'status', message: 'Installing regex..' });
await self.pyodide.loadPackage('six');
postMessage({ type: 'status', message: 'Installing six..' });
await self.pyodide.loadPackage('tomli');
postMessage({ type: 'status', message: 'Installing tomli..' });
await self.pyodide.loadPackage('tqdm');
postMessage({ type: 'status', message: 'Installing tqdm..' });
postMessage({
type: 'status',
message:
'Running Python ' +
pyodide.runPython(`
import sys
sys.version
`),
});
postMessage({ type: 'status', message: 'ready' });
return pyodide;
}
let pyodideReadyPromise = loadPyodideAndPackages();
self.onmessage = async (event) => {
await pyodideReadyPromise;
const { id, config, html } = event.data;
const profile = config.profile ? `\n,profile="${config.profile}"` : '';
const indent = config.indent ? `\n,indent=${config.indent}` : '';
const preserveLeadingSpace = config.preserveLeadingSpace
? `\n,preserve_leading_space=${capitalize(config.preserveLeadingSpace)}`
: '';
const preserveBlankSpace = config.preserveBlankSpace
? `\n,preserve_blank_lines=${capitalize(config.preserveBlankSpace)}`
: '';
const formatJs = config.formatJs
? `\n,format_js=${capitalize(config.formatJs)}`
: '';
const formatCss = config.formatCss
? `\n,format_css=${capitalize(config.formatCss)}`
: '';
const customBlocks = config.customBlocks
? `config.custom_blocks="${config.customBlocks}"`
: '';
const customHtml = config.customHtml
? `config.custom_html="${config.customHtml}"`
: '';
const maxLineLength = config.maxLineLength
? `config.max_line_length=${config.maxLineLength}`
: '';
const maxAttributeLength = config.maxAttributeLength
? `config.max_attribute_length=${config.maxAttributeLength}`
: '';
const formatAttributeTemplateTags = config.formatAttributeTemplateTags
? `config.format_attribute_template_tags=${capitalize(
config.formatAttributeTemplateTags,
)}`
: '';
const blankLineAfterTag = config.blankLineAfterTag
? `config.blank_line_after_tag="${config.blankLineAfterTag}"`
: '';
const blankLineBeforeTag = config.blankLineBeforeTag
? `config.blank_line_before_tag="${config.blankLineBeforeTag}"`
: '';
try {
await self.pyodide.runPythonAsync(`
import io
import os
sys.modules['_multiprocessing'] = object
from multiprocessing.pool import ThreadPool
sys.stdout = io.StringIO()
from pathlib import Path
from djlint.reformat import reformat_file
from djlint.settings import Config
import tempfile
`);
await self.pyodide.runPythonAsync('sys.stdout.flush()');
await pyodide.runPythonAsync(`
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.write(b"""${html}""")
temp_file.seek(0)
config = Config(
temp_file.name${indent}${profile}${preserveLeadingSpace}${preserveBlankSpace}${formatJs}${formatCss}
)
${customBlocks}
${customHtml}
${maxLineLength}
${maxAttributeLength}
${formatAttributeTemplateTags}
${blankLineAfterTag}
${blankLineBeforeTag}
print(Path(list(reformat_file(config, Path(temp_file.name)).keys())[0]).read_text().rstrip())
temp_file.close()
os.unlink(temp_file.name)
`);
let stdout = await self.pyodide.runPythonAsync('sys.stdout.getvalue()');
await self.pyodide.runPythonAsync('sys.stdout.flush()');
postMessage({ type: 'html', message: stdout, id: id });
} catch (err) {
self.postMessage({ type: 'error', message: err.message, id: id });
}
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1243
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "djlint",
"version": "1.19.7",
"version": "1.19.9",
"description": "HTML Template Linter and Formatter",
"main": "./bin/index.js",
"directories": {
@ -66,7 +66,7 @@
"cz-conventional-changelog": "3.3.0",
"lint-staged": "13.0.3",
"semantic-release": "19.0.5",
"xo": "0.52.4"
"xo": "0.53.1"
},
"config": {
"commitizen": {