New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

simplest-sitegen

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simplest-sitegen - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

.vscode/launch.json

29

dist/index.d.ts

@@ -0,1 +1,17 @@

/// <reference types="node" resolution-mode="require"/>
declare type TemplatePlugin = (context: Context, template: string) => Promise<string>;
interface Rename {
file: string;
content: string | Buffer;
}
interface Remove {
file: 'remove';
}
interface Keep {
file: 'keep';
}
declare type FilesPlugin = {
extensions: string[];
parse: (context: Context, file: string) => Promise<string | Buffer | Rename | Remove | Keep>;
};
declare type HtmlParser = {

@@ -5,12 +21,17 @@ template: string;

};
declare const config: {
declare const defaultConfig: {
input: string;
output: string;
template: string;
ignoreExtensions: string[];
templatePlugins: TemplatePlugin[];
filesPlugin: FilesPlugin[];
};
declare const context: {
config: typeof config;
export declare type Config = typeof defaultConfig;
export declare type Context = {
config: Config;
parser: HtmlParser;
};
export declare type Context = typeof context;
export declare const simplest: (config?: Config) => Promise<void>;
export declare const simplestWatch: (config?: Config) => Promise<void>;
export {};

175

dist/index.js

@@ -15,79 +15,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

import path from 'upath';
import minimist from 'minimist';
import sane from 'sane';
import { cacheBust, htmlFiles } from './plugins.js';
import { cacheBust, compileSass, htmlFiles } from './plugins.js';
import { cwd } from 'process';
const config = {
const defaultConfig = {
input: "src",
output: "build",
template: "src/template.html"
template: "src/template.html",
ignoreExtensions: [".sass", ".scss", ".less"],
templatePlugins: [],
filesPlugin: []
};
const context = {
config,
parser: null
};
const d = debug('simplest');
const outputFile = (file) => path.join(config.output, file.slice(config.input.length));
const isNewer = (src, dest) => Promise.all([fs.stat(src), fs.stat(dest)])
.then(([src1, dest1]) => {
const output = src1.mtimeMs > dest1.mtimeMs;
return output;
})
.catch(e => {
return true;
});
const parseTemplate = (plugins) => __awaiter(void 0, void 0, void 0, function* () {
const { output, template } = config;
const templateOutputFile = path.join(output, path.basename(template));
const templateChanged = yield isNewer(template, templateOutputFile);
let templateContent = context.parser.template;
for (const plugin of plugins) {
templateContent = yield plugin(context, templateContent);
}
context.parser.template = templateContent;
if (templateChanged) {
fs.outputFile(templateOutputFile, templateContent);
return true;
}
const currentTemplate = yield fs.readFile(templateOutputFile, { encoding: 'utf8' });
if (currentTemplate != templateContent) {
fs.outputFile(templateOutputFile, templateContent);
return true;
}
return false;
});
const parseFiles = ((plugins, templateChanged) => __awaiter(void 0, void 0, void 0, function* () {
if (templateChanged)
d('Template content changed, unconditional update.');
const allFiles = yield fg(path.join(config.input, `/**/*.*`));
const parseFiles = (exts, parse) => __awaiter(void 0, void 0, void 0, function* () {
const files = allFiles.filter((f) => exts.some((ext) => f.endsWith('.' + ext)));
let queue = files;
if (!templateChanged) {
const newer = yield Promise.all(files.map((file) => isNewer(file, outputFile(file))));
queue = files.filter((file, i) => newer[i]);
}
return queue.map((f) => ({
file: f,
content: parse(context, f)
}));
});
for (const plugin of plugins) {
const files = yield parseFiles(plugin.extensions, plugin.parse);
const results = yield Promise.allSettled(files.map(f => f.content));
for (const [i, result] of results.entries()) {
if (result.status != 'fulfilled')
continue;
fs.outputFile(outputFile(files[i].file), result.value);
allFiles.splice(allFiles.indexOf(files[i].file), 1);
}
}
for (const file of allFiles) {
const output = outputFile(file);
if (!(yield isNewer(file, output)))
continue;
fs.outputFile(output, yield fs.readFile(file));
}
}));
const start = () => __awaiter(void 0, void 0, void 0, function* () {
const start = (config2, watch = false) => __awaiter(void 0, void 0, void 0, function* () {
const config = Object.assign({}, defaultConfig);
try {

@@ -98,2 +34,4 @@ const userConfig = yield import('file:///' + path.join(cwd(), 'simplest.config.js'));

catch (e) { }
if (config2)
Object.assign(config, config2);
try {

@@ -109,17 +47,86 @@ yield fs.access(config.template);

});
Object.assign(context, {
const context = {
config,
parser
};
const outputFile = (file) => path.join(config.output, file.slice(config.input.length));
const isNewer = (src, dest) => Promise.all([fs.stat(src), fs.stat(dest)])
.then(([src1, dest1]) => {
const output = src1.mtimeMs > dest1.mtimeMs;
return output;
})
.catch(e => {
return true;
});
const args = minimist(process.argv.slice(2));
const watch = args._.includes('watch');
const template = () => parseTemplate([cacheBust]);
const files = (templateChanged) => parseFiles([htmlFiles], templateChanged);
const hasExtension = (exts) => (input) => exts.some(ext => input.endsWith(`${ext}`));
const hasntExtension = (exts) => (input) => !exts.some(ext => input.endsWith(`${ext}`));
const parseTemplate = (plugins) => __awaiter(void 0, void 0, void 0, function* () {
const { output, template } = config;
const templateOutputFile = path.join(output, path.basename(template));
const templateChanged = yield isNewer(template, templateOutputFile);
let templateContent = context.parser.template;
for (const plugin of plugins) {
templateContent = yield plugin(context, templateContent);
}
context.parser.template = templateContent;
if (templateChanged) {
fs.outputFile(templateOutputFile, templateContent);
return true;
}
const currentTemplate = yield fs.readFile(templateOutputFile, { encoding: 'utf8' });
if (currentTemplate != templateContent) {
fs.outputFile(templateOutputFile, templateContent);
return true;
}
return false;
});
const parseFiles = ((plugins, templateChanged) => __awaiter(void 0, void 0, void 0, function* () {
const allFiles = new Set(yield fg(path.join(config.input, `/**/*.*`)));
const parseFiles = (exts, parse) => __awaiter(void 0, void 0, void 0, function* () {
const files = Array.from(allFiles).filter(hasExtension(exts));
let queue = files;
if (!templateChanged) {
const newer = yield Promise.all(files.map((file) => isNewer(file, outputFile(file))));
queue = files.filter((file, i) => newer[i]);
}
return queue.map((f) => ({
file: f,
content: parse(context, f)
}));
});
for (const plugin of plugins) {
const files = yield parseFiles(plugin.extensions, plugin.parse);
for (const parsed of files) {
const content = yield parsed.content;
const removeFile = () => allFiles.delete(parsed.file);
if (typeof content === 'string' || Buffer.isBuffer(content)) {
fs.outputFile(outputFile(parsed.file), content);
removeFile();
}
else if (content.file == 'remove') {
removeFile();
}
else if (content.file == 'keep') {
}
else {
const c = content;
fs.outputFile(outputFile(c.file), c.content);
removeFile();
}
}
}
for (const file of [...allFiles].filter(hasntExtension(config.ignoreExtensions))) {
const output = outputFile(file);
if (!(yield isNewer(file, output)))
continue;
fs.outputFile(output, yield fs.readFile(file));
}
}));
const run = () => __awaiter(void 0, void 0, void 0, function* () {
const templateChanged = yield template();
return files(templateChanged);
const templateChanged = yield parseTemplate(config.templatePlugins.concat([compileSass, cacheBust]));
return parseFiles(config.filesPlugin.concat([htmlFiles]), templateChanged);
});
const runWatch = (filepath, root, stat) => {
const relativePath = path.relative(path.join(config.input, '..'), path.join(root, filepath));
console.log('Update: ' + relativePath);
console.log('Updated: ' + relativePath);
return run();

@@ -132,9 +139,11 @@ };

console.log('Watching for file changes in "' + config.input + '"');
const watcher = sane(config.input);
const sane = yield import('sane');
const watcher = sane.default(config.input);
watcher.on('change', runWatch);
watcher.on('add', runWatch);
}
run();
return run();
});
start();
export const simplest = (config) => start(config);
export const simplestWatch = (config) => start(config, true);
//# sourceMappingURL=index.js.map
/// <reference types="node" resolution-mode="require"/>
import { type Context } from './index.js';
export declare const cacheBust: (context: Context, template: string) => Promise<string>;
export declare const compileSass: (context: Context, template: string) => Promise<string>;
export declare const htmlFiles: {

@@ -5,0 +6,0 @@ extensions: string[];

@@ -14,9 +14,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

import { hash } from './utils.js';
export const cacheBust = (context, template) => __awaiter(void 0, void 0, void 0, function* () {
const root = parse(template, { comment: true });
const includeScript = (el, attr) => !!el.attributes[attr] &&
!el.attributes[attr].includes('?') &&
!el.attributes[attr].includes('//');
const scripts = (selector, attr) => root.querySelectorAll(selector)
.filter((el) => includeScript(el, attr))
const isAbsolute = (url) => /^(?:[a-z+]+:)?\/\//i.test(url);
const cssScripts = (root) => srcScripts(root, 'link', 'href');
const jsScripts = (root) => srcScripts(root, 'script', 'src');
const srcScripts = (root, selector, attr) => {
return root.querySelectorAll(selector)
.filter((el) => !!el.attributes[attr])
.map((el) => ({

@@ -27,18 +26,43 @@ el,

}));
const cssFiles = scripts('link', 'href');
const jsFiles = scripts('script', 'src');
const scriptFiles = jsFiles.concat(cssFiles);
const content = yield Promise.allSettled(scriptFiles
.map(script => path.join(context.config.input, script.file))
.map(file => fs.readFile(file)));
content.forEach((res, i) => {
if (res.status != 'fulfilled')
return;
const { el, attr, file } = scriptFiles[i];
el.setAttribute(attr, file + '?' + hash(res.value));
});
};
export const cacheBust = (context, template) => __awaiter(void 0, void 0, void 0, function* () {
const root = parse(template, { comment: true });
const scriptFiles = cssScripts(root).concat(jsScripts(root))
.filter(f => !isAbsolute(f.file));
for (const { el, attr, file } of scriptFiles) {
const inputPath = path.join(context.config.input, file);
try {
const content = yield fs.readFile(inputPath).catch(() => {
const outputPath = path.join(context.config.output, file);
return fs.readFile(outputPath);
});
el.setAttribute(attr, file + '?' + hash(content));
}
catch (e) {
console.log('Warning: ' + file + ' not found, referenced in ' + context.config.template);
}
}
return root.toString();
});
let sass;
export const compileSass = (context, template) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const root = parse(template, { comment: true });
for (const link of cssScripts(root)) {
if (!(link.file.endsWith('.sass') || link.file.endsWith('.scss')))
continue;
if (!sass)
sass = (yield import('sass')).default.compile;
const compiled = sass(path.join(context.config.input, link.file));
const cssFileName = path.changeExt(link.file, '.css');
yield fs.outputFile(path.join(context.config.output, cssFileName), compiled.css);
link.el.setAttribute(link.attr, cssFileName);
if ((_a = compiled.sourceMap) === null || _a === void 0 ? void 0 : _a.file) {
yield fs.outputFile(path.join(context.config.output, path.changeExt(link.file, '.css.map', undefined, 8)), compiled.sourceMap.file);
}
}
return root.toString();
});
export const htmlFiles = {
extensions: ['html', 'htm'],
extensions: ['.html', '.htm'],
parse: (context, file) => __awaiter(void 0, void 0, void 0, function* () {

@@ -45,0 +69,0 @@ const content = yield fs.readFile(file);

{
"name": "simplest-sitegen",
"version": "0.6.0",
"version": "0.7.0",
"author": "",

@@ -10,11 +10,13 @@ "description": "The simplest static sitegen there is. Build a modern, fully working website with only HTML.",

"bin": {
"simplest": "dist/index.js"
"simplest": "dist/cli.js"
},
"type": "module",
"exports": "./dist/index.js",
"scripts": {
"build": "tsc",
"dev": "nodemon dist/index.js",
"dev": "nodemon -e \"js,css,html,sass\" -w dist -w expected -x \"npm run test\"",
"server": "http-server -c-1 build",
"prepublishOnly": "tsc",
"start": "node dist/index.js",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist/cli.js",
"test": "node dist/test.js",
"watch": "tsc -w"

@@ -35,3 +37,5 @@ },

"devDependencies": {
"@npmcli/disparity-colors": "^2.0.0",
"@types/debug": "^4.1.7",
"@types/diff": "^5.0.2",
"@types/fs-extra": "^9.0.13",

@@ -41,4 +45,12 @@ "@types/minimist": "^1.2.2",

"@types/sane": "^2.0.1",
"nodemon": "^2.0.19"
"ansi-colors": "^4.1.3",
"diff": "^5.1.0",
"dir-compare": "^4.0.0",
"http-server": "^14.1.1",
"nodemon": "^2.0.19",
"sass": "^1.54.5",
"ts-node": "^10.9.1",
"typescript": "^4.7.4",
"url": "^0.11.0"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc