djLint/docs/.eleventy.js
2023-01-23 11:09:31 -06:00

375 lines
9.6 KiB
JavaScript

const Image = require('@11ty/eleventy-img');
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight');
const criticalCss = require('eleventy-critical-css');
const slugify = require('slugify');
const metagen = require('eleventy-plugin-metagen');
const i18n = require('eleventy-plugin-i18n');
const translations = require('./src/_data/i18n');
const locales = require('./src/_data/locales');
const fs = require('fs');
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');
process.setMaxListeners(0);
const slugifyCustom = (s) =>
slugify(s, { lower: true, remove: /[*+~.()'"!:@]/g });
async function imageShortcode(
src,
alt,
sizes,
type = 'asdf',
loading = 'lazy',
decoding = 'async',
) {
let metadata = await Image(src, {
widths: [24, 300, 400, 500, 600, 800, 1200],
formats: ['webp', 'png'],
sharpWebpOptions: {
options: {
quality: 70,
},
},
outputDir: './_site/static/img/',
urlPath: '/static/img/',
});
let imageAttributes = {
alt,
sizes,
loading: loading,
decoding: decoding,
};
if (type == 'boxed') {
return (
`<div class="block"><div class="box is-inlineblock">` +
Image.generateHTML(metadata, imageAttributes) +
`</div></div>`
);
}
// using custom code so that we can return the highest src in img as old browsers don't auto upscale.
let lowsrc = metadata.png[0];
let highsrc = metadata.png[metadata.png.length - 1];
return `<picture>
${Object.values(metadata)
.map((imageFormat) => {
return ` <source type="${
imageFormat[0].sourceType
}" srcset="${imageFormat
.map((entry) => entry.srcset)
.join(', ')}" sizes="${sizes}">`;
})
.join('\n')}
<img
src="${highsrc.url}"
width="${highsrc.width}"
height="${highsrc.height}"
alt="${alt}"
loading="lazy"
decoding="async">
</picture>`;
}
// from https://github.com/pusher/docs/blob/main/.eleventy.js
// widont is a function that takes a string and replaces the space between the last two words with a non breaking space. This stops typographic widows forming
const widont = (string) => {
return string.split(' ').length > 2
? string.replace(/\s([^\s<]+)\s*$/, '\u00A0$1')
: string;
};
module.exports = function (eleventyConfig) {
eleventyConfig.addGlobalData(
'djlint_version',
require('../package.json').version,
);
eleventyConfig.setUseGitIgnore(false);
eleventyConfig.addFilter('widont', widont);
eleventyConfig.addWatchTarget('./src/static/');
eleventyConfig.addNunjucksAsyncShortcode('image', imageShortcode);
eleventyConfig.addTransform(
'htmlmin',
require('./src/_utils/minify-html.js'),
);
eleventyConfig.addPlugin(syntaxHighlight);
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',
// optional: defaults
github_edit_path: '/docs/', // non-root location in git url. root is assumed
github_edit_branch: 'master',
github_edit_text: (page) => {
i18n_options = Object.assign(
{},
{
translations,
fallbackLocales: {
'*': 'en-US',
},
},
);
return `<span class="icon-text"><span class="icon mr-1"><i class="fas fa-pencil"></i></span><span>${i18n_func(
'edit_page',
undefined,
undefined,
i18n_options,
page,
)}</span></span>`;
return x.inputPath;
},
github_edit_class: 'edit-on-github',
github_edit_tag: 'a',
github_edit_attributes: 'target="_blank" rel="noopener"',
github_edit_wrapper: undefined, //ex: "<div stuff>${edit_on_github}</div>"
});
/* Markdown Plugins */
const markdownItAnchor = require('markdown-it-anchor');
const markdownIt = require('markdown-it')({
html: true,
breaks: true,
linkify: true,
typographer: true,
});
const opts = {
level: [2, 3, 4, 5],
permalink: markdownItAnchor.permalink.linkInsideHeader({
class: 'link bn',
symbol: '∞',
placement: 'before',
}),
slugify: slugifyCustom,
};
const mapping = {
h1: 'title is-1',
h2: 'title is-2',
h3: 'title is-3',
h4: 'title is-4',
h5: 'title is-5',
h6: 'title is-5',
p: 'block',
table: 'table',
};
markdownIt
.use(markdownItAnchor, opts)
.use(require('markdown-it-imsize'), { autofill: true })
.use(require('@toycode/markdown-it-class'), mapping)
.use(require('markdown-it-div'), 'div', {});
eleventyConfig.setLibrary('md', markdownIt);
// copy font
eleventyConfig.addPassthroughCopy({
'./node_modules/@fontsource/inter/files': 'static/font/inter/files',
});
eleventyConfig.addPassthroughCopy({
'./node_modules/@fontsource/rasa/files': 'static/font/rasa/files',
});
eleventyConfig.addPassthroughCopy({
'./node_modules/@fontsource/crimson-pro/files':
'static/font/crimson-pro/files',
});
// copy images
eleventyConfig.addPassthroughCopy({
'src/static/img': 'static/img',
});
// copy robots
eleventyConfig.addPassthroughCopy({
'src/robots.txt': 'robots.txt',
});
// copy favicon
eleventyConfig.addPassthroughCopy({
'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');
});
eleventyConfig.addFilter('niceDate', (value) => {
try {
const options = { year: 'numeric', month: 'short', day: 'numeric' };
return value.toLocaleDateString('en-us', options);
} catch (e) {
return value;
}
});
eleventyConfig.addFilter('year', (value) => {
try {
const options = { year: 'numeric' };
return value.toLocaleDateString('en-us', options);
} catch (e) {
return value;
}
});
eleventyConfig.addFilter('algExcerpt', (text) => {
return text
.replace(/<code class="language-.*?">.*?<\/code>/gs, '')
.replace(/<.*?>/g, '')
.substring(0, 8000);
});
eleventyConfig.addCollection('algolia', function (collection) {
return collection.getFilteredByGlob('**/*.md');
});
const icons = {
note: '<span class="icon has-text-info mr-1"><i class="fas fa-pencil"></i></span>',
};
eleventyConfig.addShortcode('admonition', function (icon, title, text) {
return outdent`
<article class="message ${icon} box">
<div class="message-header">
<p>${icons[icon]} ${title}</p>
</div>
<div class="message-body">${markdownIt.render(text)}</div>
</article>`;
});
eleventyConfig.addFilter('markdown', (value) => {
return `${markdownIt.render(value)}`;
});
const { fontawesomeSubset } = require('fontawesome-subset');
fontawesomeSubset(
{
brands: ['discord', 'github'],
regular: ['envelope'],
solid: [
'globe',
'circle-arrow-right',
'pencil',
'infinity',
'download',
'code-commit',
'spinner',
'circle-question',
],
},
'_site/static/font/fontawesome/webfonts',
);
eleventyConfig.addPlugin(i18n, {
translations,
fallbackLocales: {
'*': 'en-US',
},
});
eleventyConfig.addFilter('baseUrl', (text) => {
return text.replace(/(?:ru)\//g, '');
});
eleventyConfig.addFilter('i18n_locale', (current_locale, locale_list) => {
return locale_list.filter((x) => {
return x.code === (current_locale ?? 'en-US');
})[0].label;
});
eleventyConfig.addFilter('i18n_urls', (page, all) => {
var locale_urls = locales
.map((x) => {
if (x.url != '') return x.url;
})
.filter((x) => {
return x !== undefined;
});
var split_url = page.split('/').length > 1 ? page.split('/')[1] : '';
// find the current locale
var active_local = '';
locale_urls.forEach((locale) => {
if (locale === split_url) {
active_local = locale;
return true;
}
return false;
});
// get remaining locales
var remaining_locals = locales
.map((x) => {
return x.url;
})
.filter((x) => {
return x !== active_local;
});
var i18n_pages = [];
var valid_urls = all.map((x) => {
return x.url;
});
remaining_locals.forEach((x) => {
var new_url = ('/' + page.replace(active_local, x)).replace(
/\/{2,}/,
'/',
);
if (valid_urls.indexOf(new_url) !== -1) {
i18n_pages.push({
url: new_url,
meta: locales.filter((y) => {
return y.url === x;
})[0],
});
}
});
return i18n_pages;
});
return {
dir: {
input: 'src',
formats: 'njk',
includes: '_includes',
data: '_data',
output: '_site',
},
templateFormats: ['md', 'html', 'njk', '11ty.js'],
htmlTemplateEngine: 'njk',
markdownTemplateEngine: 'njk',
passthroughFileCopy: true,
};
};