Skip to content

Commit 61a4a7f

Browse files
committed
initial commit (migrated from zuix-web-starter)
0 parents  commit 61a4a7f

File tree

239 files changed

+50954
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

239 files changed

+50954
-0
lines changed

.eleventy-zuix.js

+314
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
/*
2+
* Copyright 2020-2022 G-Labs. All Rights Reserved.
3+
* https://zuixjs.github.io/zuix
4+
*
5+
* Licensed under the MIT license. See LICENSE file.
6+
*
7+
*/
8+
9+
/*
10+
*
11+
* This file is part of
12+
* zUIx, Javascript library for component-based development.
13+
* https://zuixjs.github.io/zuix
14+
*
15+
* @author Generoso Martello - https://github.com/genemars
16+
* @version 1.0
17+
*
18+
*/
19+
20+
/**
21+
* @param eleventyConfig
22+
*/
23+
const path = require('path');
24+
const config = require('config');
25+
const fs = require('fs');
26+
const chokidar = require('chokidar');
27+
const moment = require('moment');
28+
const nunjucks = require('nunjucks');
29+
30+
const {
31+
compilePage,
32+
copyFolder,
33+
generateServiceWorker,
34+
generateAppConfig,
35+
wrapDom,
36+
wrapCss
37+
} = require('zuix');
38+
39+
// Read configuration either from './config/{default}.json'
40+
// or './config/production.json' based on current `NODE_ENV'
41+
// environment variable value
42+
let zuixConfig = config.get('zuix');
43+
const sourceFolder = zuixConfig.get('build.input');
44+
const buildFolder = zuixConfig.get('build.output');
45+
const copyFiles = zuixConfig.get('build.copy');
46+
const ignoreFiles = zuixConfig.get('build.ignore');
47+
const componentsFolders = zuixConfig.get('build.componentsFolders');
48+
const dataFolder = zuixConfig.get('build.dataFolder');
49+
const includesFolder = zuixConfig.get('build.includesFolder');
50+
// this file is a temporary file create to trigger 11ty build
51+
const triggerFile = path.join(sourceFolder, '.zuix.build.md');
52+
const triggerFileOut = path.join(buildFolder, '.zuix.build.tmp');
53+
// replace {{variables}} eventually employed in the config
54+
zuixConfig = JSON.parse(nunjucks.renderString(JSON.stringify(zuixConfig), zuixConfig));
55+
56+
const normalizeMarkup = (s) => s.trim().split('\n').filter((l) => {
57+
if (l.trim().length > 0) {
58+
return l;
59+
}
60+
}).join('\n');
61+
62+
function getZuixConfig() {
63+
return {
64+
sourceFolder,
65+
buildFolder,
66+
dataFolder,
67+
includesFolder,
68+
copyFiles,
69+
ignoreFiles,
70+
componentsFolders,
71+
baseUrl: zuixConfig.app.baseUrl,
72+
all: zuixConfig
73+
}
74+
}
75+
76+
function startWatcher(eleventyConfig, browserSync) {
77+
// Watch zuix.js folders and files (`./source/lib`, `./source/app`, zuixConfig.copy), ignored by 11ty
78+
const watchEvents = {add: true, change: true, unlink: true};
79+
const watchFiles = [];
80+
copyFiles.forEach((f) => {
81+
f = path.resolve(path.join(sourceFolder, f));
82+
watchFiles.push(f);
83+
});
84+
componentsFolders.map(f => {
85+
f = path.resolve(path.join(sourceFolder, f));
86+
watchFiles.push(f);
87+
});
88+
const copyFilesWatcher = chokidar.watch(watchFiles).on('all', (event, file, stats) => {
89+
if (watchEvents[event] && fs.existsSync(file)) {
90+
const outputFile = path.resolve(path.join(buildFolder, file.substring(path.resolve(sourceFolder).length)));
91+
const outputFolder = path.dirname(outputFile);
92+
if (!fs.existsSync(outputFolder)) {
93+
fs.mkdirSync(outputFolder, { recursive: true })
94+
}
95+
fs.copyFileSync(file, outputFile);
96+
} else {
97+
// TODO: maybe remove file from output folder as well?
98+
}
99+
if (browserSync) {
100+
browserSync.reload();
101+
}
102+
});
103+
const includes = path.join(sourceFolder, includesFolder);
104+
const allFilesWatcher = chokidar.watch([sourceFolder]).on('all', (event, file, stats) => {
105+
if (event.startsWith('unlink') && file !== triggerFile) {
106+
forceRebuild();
107+
} else if (!file.startsWith(includes) && file.indexOf(path.join('/', '_inc', '/')) !== -1) {
108+
forceRebuild();
109+
}
110+
});
111+
}
112+
113+
function forceRebuild() {
114+
fs.writeFileSync(triggerFile, `---
115+
permalink: .zuix.build.tmp
116+
---
117+
Temporary file to trigger 11ty build`);
118+
}
119+
120+
function initEleventyZuix(eleventyConfig) {
121+
const postProcessFiles = [];
122+
const changedFiles = [];
123+
let rebuildAll = true;
124+
copyDependencies();
125+
// zUIx.js specific code and life-cycle hooks
126+
eleventyConfig.addGlobalData("app", zuixConfig.app);
127+
eleventyConfig.addWatchTarget('./templates/tags/');
128+
// Add zUIx transform
129+
eleventyConfig.addTransform('zuix-js', function(content) {
130+
const inputPath = this.inputPath;
131+
const outputPath = this.outputPath;
132+
const hasChanged = changedFiles.find(f => path.resolve(f) === path.resolve(inputPath));
133+
if (!rebuildAll && !hasChanged) return content;
134+
// populates a list of `.html` files
135+
// to be post processed after build
136+
if (outputPath && outputPath.endsWith('.html')) {
137+
let file = path.resolve(outputPath);
138+
const baseFolder = path.resolve(zuixConfig.build.output);
139+
if (file.startsWith(baseFolder)) {
140+
file = file.substring(baseFolder.length + 1);
141+
}
142+
postProcessFiles.push({file, baseFolder: zuixConfig.build.output});
143+
}
144+
return content;
145+
});
146+
eleventyConfig.on('beforeWatch', (cf) => {
147+
// changedFiles is an array of files that changed
148+
// to trigger the watch/serve build
149+
changedFiles.length = 0;
150+
const baseFolder = path.resolve(zuixConfig.build.input);
151+
const dataFolder = path.join(baseFolder, zuixConfig.build.dataFolder);
152+
const includesFolder = path.join(baseFolder, zuixConfig.build.includesFolder);
153+
const templateChanged = cf.find(f => path.resolve(f).startsWith(includesFolder));
154+
const dataChanged = cf.find(f => path.resolve(f).startsWith(dataFolder));
155+
if (templateChanged || dataChanged) {
156+
rebuildAll = true;
157+
return;
158+
}
159+
changedFiles.push(...cf);
160+
});
161+
eleventyConfig.on('afterBuild', async function(args) {
162+
console.log();
163+
postProcessFiles.forEach((pf) => {
164+
const result = compilePage(pf.file, pf.file, {
165+
baseFolder: pf.baseFolder,
166+
...zuixConfig
167+
});
168+
// TODO: check result code and report
169+
});
170+
postProcessFiles.length = 0;
171+
if (zuixConfig.build.serviceWorker) {
172+
console.log('Updating Service Worker... ');
173+
await generateServiceWorker().then(function () {
174+
console.log('... done.');
175+
});
176+
} else {
177+
console.log();
178+
}
179+
if (rebuildAll) {
180+
// reverts to incremental build mode
181+
rebuildAll = false;
182+
}
183+
// delete temporary build-trigger file if found
184+
if (fs.existsSync(triggerFile)) {
185+
fs.unlinkSync(triggerFile);
186+
fs.unlinkSync(triggerFileOut);
187+
}
188+
});
189+
if (process.argv.indexOf('--serve') === -1) {
190+
// copy files in production mode
191+
copyFiles.forEach((f) => {
192+
f = path.join(sourceFolder, f);
193+
eleventyConfig.addPassthroughCopy(f);
194+
});
195+
componentsFolders.map(f => {
196+
f = path.join(sourceFolder, f);
197+
eleventyConfig.addPassthroughCopy(f);
198+
});
199+
}
200+
eleventyConfig.setDataDeepMerge(true);
201+
}
202+
203+
function copyDependencies() {
204+
// Copy last zUIx release
205+
copyFolder(`${process.cwd()}/node_modules/zuix-dist/js`, `${buildFolder}/js/zuix`, (err) => {
206+
if (err) console.log(err);
207+
});
208+
// Auto-generated config.js
209+
generateAppConfig(zuixConfig);
210+
// Copy other dependencies
211+
// - elasticlurn search engine
212+
copyFolder(`${process.cwd()}/node_modules/elasticlunr/release`, `${buildFolder}/js/elasticlunr`, (err) => {
213+
if (err) console.log(err);
214+
});
215+
// - Flex Layout Attribute
216+
copyFolder(`${process.cwd()}/node_modules/flex-layout-attribute/css`, `${buildFolder}/css/fla`, (err) => {
217+
if (err) console.log(err);
218+
});
219+
// - Animate.CSS
220+
fs.copyFileSync(`${process.cwd()}/node_modules/animate.css/animate.min.css`, `${buildFolder}/css/animate.min.css`);
221+
}
222+
223+
function rawFileInclude(page, fileName) {
224+
const inputPath = path.dirname(page.inputPath);
225+
let rawFile = path.join(inputPath, fileName);
226+
if (!fs.existsSync(rawFile)) {
227+
rawFile = path.join(inputPath, page.fileSlug, fileName);
228+
}
229+
if (!fs.existsSync(rawFile)) {
230+
rawFile = path.join(zuixConfig.build.input, fileName);
231+
}
232+
if (!fs.existsSync(rawFile)) {
233+
rawFile = path.join(zuixConfig.build.input, zuixConfig.build.includesFolder, fileName);
234+
}
235+
if (fs.existsSync(rawFile)) {
236+
return normalizeMarkup(fs.readFileSync(rawFile).toString('utf8'));
237+
} else {
238+
// TODO: report error
239+
throw new Error('File not found');
240+
}
241+
}
242+
243+
function configure(eleventyConfig) {
244+
initEleventyZuix(eleventyConfig);
245+
246+
/*
247+
|| Eleventy plugins
248+
*/
249+
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
250+
eleventyConfig.addPlugin(syntaxHighlight);
251+
252+
/*
253+
|| Add data collections
254+
*/
255+
256+
// this is used by the searchFilter
257+
eleventyConfig.addCollection('posts_searchIndex', (collection) => {
258+
return [...collection.getFilteredByGlob(path.join(zuixConfig.build.input, 'pages/**/*.md'))];
259+
});
260+
261+
/*
262+
|| Add custom data filters
263+
*/
264+
265+
// TODO: maybe scan folder and add automatically
266+
const filtersPath = path.resolve(sourceFolder, '_filters');
267+
eleventyConfig.addFilter(
268+
'search',
269+
require(path.join(filtersPath, 'searchFilter'))
270+
);
271+
eleventyConfig.addFilter(
272+
'date',
273+
(date, format) => moment(date).format(format || 'YYYY-MM-DD')
274+
);
275+
276+
/*
277+
|| Add short codes
278+
*/
279+
280+
eleventyConfig.addShortcode('rawFile', function(fileName) {
281+
return rawFileInclude(this.page, fileName);
282+
});
283+
284+
eleventyConfig.addPairedShortcode('unpre', function(content) {
285+
content = content.substring(content.indexOf('```') + 3);
286+
content = content.substring(content.indexOf('\n') + 1);
287+
content = content.substring(0, content.lastIndexOf('```'));
288+
return normalizeMarkup(content);
289+
});
290+
291+
eleventyConfig.addPairedShortcode('layout', function(content, ...args) {
292+
return `<div layout="${args[0]}" ${args[1]}>${normalizeMarkup(content)}</div>`;
293+
});
294+
295+
eleventyConfig.addPairedShortcode('zx', function(content, template, ...args) {
296+
const p = `./templates/tags/${template}.js`;
297+
if (fs.existsSync(p)) {
298+
delete require.cache[require.resolve(p)];
299+
return normalizeMarkup(require(p)(nunjucks.renderString, content, ...args));
300+
}
301+
return ''; // 'Not implemented! (' + content + ') [' + args + ']';
302+
});
303+
304+
eleventyConfig.addPairedShortcode('wrapDom', function(content, cssId) {
305+
return wrapDom(content, cssId);
306+
});
307+
eleventyConfig.addPairedShortcode('wrapCss', function(content, cssId, encapsulate) {
308+
return wrapCss(`[${cssId}]`, content, encapsulate);
309+
});
310+
}
311+
312+
module.exports = {
313+
startWatcher, configure, getZuixConfig
314+
}

0 commit comments

Comments
 (0)