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

blog-engine-sac

Package Overview
Dependencies
Maintainers
1
Versions
110
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

blog-engine-sac - npm Package Compare versions

Comparing version 4.0.3 to 5.1.0

source/cache/webCache.js

4

defaultSettings/default-blog-engine-sac.json

@@ -6,3 +6,5 @@ {

"mainTitle": "Blog",
"subTitle": "Change title and subtitle in blog-engine-sac.json"
"subTitle": "Change title and subtitle in blog-engine-sac.json",
"categories": [],
"defaultLicense": "[Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/)"
}

@@ -7,6 +7,9 @@ export { createAboutHtml };

import {makeBackGroundPicture} from "./images.js";
import { translate } from "../translations/translate.js";
const createAboutHtml = (options) => {
const { body, title, author, description } = options;
const { body, defaultAuthor: author, subTitle: description, defaultLang } = options;
const lang = defaultLang;
const translateDefault = translate.bind(undefined, lang);
return `<!doctype html>

@@ -17,5 +20,5 @@ <html lang="en">

<meta name="viewport" content="width=device-width">
<meta name="description" content="">
<meta name="description" content="${description}">
<meta name="author" content="${author}">
<title>About</title>
<title>${options.tabTitle} - ${translateDefault(`About`)}</title>
${styleSheets(options)}

@@ -25,3 +28,2 @@ </head>

${createHeaderHtml({ ...options, topLevel: true })}
<header class="masthead">

@@ -33,3 +35,3 @@ ${makeBackGroundPicture(`about`)}

<div class="page-heading">
<h1>About Me</h1>
<h1>${translateDefault(`About`)}</h1>
</div>

@@ -40,3 +42,2 @@ </div>

</header>
<main class="container">

@@ -51,4 +52,3 @@ <div class="row">

</body>
</html>
`;
</html>`;
};

@@ -12,8 +12,8 @@ export { createCategoryHtml };

const createCategoryHtml = (options) => {
const { posts, categoryName } = options;
const { posts, categoryName, defaultAuthor: author, subTitle: description } = options;
const MAX_ARTICLE_PREVIEW = Number.MAX_SAFE_INTEGER || 3;
// can make this number smaller once a ui element has been created to display all entries
const MAX_LINES_PREVIEW = 4; // try to make it more html safe ie not cut in middle of tag
const escapedCategoryName = escapeHtml(categoryName);
const listOfPosts = posts.map(function (post) {

@@ -36,4 +36,5 @@ // todo deduplicate from index

<meta name="viewport" content="width=device-width">
<meta name="description" content="">
<title>${categoryName}</title>
<meta name="description" content="${description}">
<meta name="author" content="${author}">
<title>${options.tabTitle} - ${escapedCategoryName}</title>
${styleSheets(options)}

@@ -51,3 +52,3 @@ </head>

<div class="site-heading">
<h1>${categoryName}</h1>
<h1>${escapedCategoryName}</h1>
<span class="subheading">Posts from this category:</span>

@@ -54,0 +55,0 @@ </div>

@@ -7,6 +7,9 @@ export { createContactHtml };

import { createFooterHtml } from "./footer.html.js";
import { translate } from "../translations/translate.js";
const createContactHtml = (options) => {
const { body, title, author, description } = options;
const { body, defaultAuthor: author, subTitle: description, defaultLang } = options;
const lang = defaultLang;
const translateDefault = translate.bind(undefined, lang);
return `<!doctype html>

@@ -19,3 +22,3 @@ <html lang="en">

<meta name="author" content="${author}">
<title>Contact</title>
<title>${options.tabTitle} - ${translateDefault(`Contact`)}</title>
${styleSheets(options)}

@@ -31,3 +34,3 @@ </head>

<div class="page-heading">
<h1>Contact Me</h1>
<h1>${translateDefault(`Contact`)}</h1>
</div>

@@ -34,0 +37,0 @@ </div>

@@ -5,3 +5,12 @@ export {createFooterHtml};

const createFooterHtml = (options) => {
const { footerText } = options;
const { footerText, defaultLicense, license } = options;
// footerText is html,
let licenseHtml;
// todo handle license shorthands and links
if (license) {
licenseHtml = `<p class="copyright text-muted">This content is licensed under ${license}</p>`;
} else {
licenseHtml = `<p class="copyright text-muted">Unless otherwise stated,
the content is licensed under ${defaultLicense}</p>`;
}
return `

@@ -12,3 +21,4 @@ <footer class="container">

<!--<p><a href="#nav">Go to the top</a></p>-->
<p class="copyright text-muted">${footerText}</p>
${licenseHtml}
${footerText}
</div>

@@ -44,4 +54,2 @@ </div>

//</ul>
};

@@ -18,3 +18,3 @@ export { createHeaderHtml };

<li class="nav-item">
<a class="nav-link" href="${prePath}/${indexFileName(lang, defaultLang)}">${translate(lang, `Home`)}</a>
<a class="nav-link home-link" href="${prePath}/${indexFileName(lang, defaultLang)}">${translate(lang, `Home`)}</a>
</li>

@@ -29,3 +29,3 @@ <li class="nav-item">

<li class="nav-item" id="searchBlock" hidden>
<input id="searchInput" placeholder="${translate(lang, `Search`)}">
<input class="nav-link" id="searchInput" placeholder="${translate(lang, `Search`)}">
<ol id="searchResults"></ol>

@@ -32,0 +32,0 @@ </li>

@@ -13,3 +13,3 @@ export { createIndexHtml };

const createIndexHtml = (options) => {
const { body, title, author, description, posts, categories, lang } = options;
const { body, title, defaultAuthor: author, subTitle: description, posts, categories, lang } = options;
const MAX_ARTICLE_PREVIEW = Number.MAX_SAFE_INTEGER || 3;

@@ -40,5 +40,5 @@ // can make this number smaller once a ui element has been created to display all entries

<meta name="viewport" content="width=device-width">
<meta name="description" content="">
<meta name="description" content="${description}">
<meta name="author" content="${author}">
<title>${options.mainTitle}</title>
<title>${options.tabTitle}</title>
${styleSheets(options)}

@@ -75,3 +75,3 @@ </head>

</div>
<div class="row">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">

@@ -85,2 +85,3 @@ <h3>Categories</h3>

</div>
</div>
</main>

@@ -87,0 +88,0 @@ ${createFooterHtml(options)}

export { makeUrl, linkFromPost, linkFromCategory, escapeHtml, indexFileName};
// rename as escape is a global function for urls
import {escape as escapeHtml, unescape as unescapeHtml} from 'html-escaper';
import slugify from '@sindresorhus/slugify';
const capitalize = (words) => {
return `${words[0].toUpperCase()}${words.substr(1)}`;
}
const linkFromCategory = (categoryName) => {
return `<a href="/c/${escape(categoryName)}.html">${escapeHtml(categoryName)}</a>`;
return `<a href="/c/${slugify(categoryName)}.html">${capitalize(escapeHtml(categoryName))}</a>`;
};

@@ -10,0 +13,0 @@

@@ -11,3 +11,3 @@ export {createPostHtml};

const createPostHtml = (options) => {
const { body, title, author, description, creationDateString, modifiedDateString, translations, lang } = options;
const { body, title, author, creationDateString, modifiedDateString, translations, lang } = options;
let lastEdit;

@@ -23,3 +23,3 @@

if (translations && translations.length) {
availableTranslations = `Translations <ul>${translations.map(({post}) => {
availableTranslations = `${translate(lang, `Translations`)} <ul>${translations.map(({post}) => {
return `<li>[${post.lang}] ${linkFromPost(post)}</li>`;

@@ -33,3 +33,2 @@ }).join(``)}</ul>`;

<meta name="viewport" content="width=device-width">
<meta name="description" content="${description}">
<meta name="author" content="${author}">

@@ -71,2 +70,3 @@ <title>${title}</title>

<nav class="container post-article-nav">
${nextInteractionHtml(options)}
<div class="row">

@@ -81,3 +81,2 @@ <div class="col-lg-8 col-md-10 mx-auto">

</div>
${nextInteractionHtml(options)}
</nav>

@@ -84,0 +83,0 @@ ${createFooterHtml(options)}

{
"name": "blog-engine-sac",
"version": "4.0.3",
"version": "5.0.0",
"lockfileVersion": 1,

@@ -64,2 +64,34 @@ "requires": true,

},
"@sindresorhus/slugify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz",
"integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==",
"requires": {
"@sindresorhus/transliterate": "^0.1.1",
"escape-string-regexp": "^4.0.0"
},
"dependencies": {
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
}
}
},
"@sindresorhus/transliterate": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.1.tgz",
"integrity": "sha512-QSdIQ5keUFAZ3KLbfbsntW39ox0Ym8183RqTwBq/ZEFoN3NQAtGV+qWaNdzKpIDHgj9J2CQ2iNDRVU11Zyr7MQ==",
"requires": {
"escape-string-regexp": "^2.0.0",
"lodash.deburr": "^4.1.0"
},
"dependencies": {
"escape-string-regexp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
}
}
},
"@types/color-name": {

@@ -242,2 +274,7 @@ "version": "1.1.1",

},
"data-uri-to-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz",
"integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og=="
},
"debug": {

@@ -445,2 +482,7 @@ "version": "4.1.1",

},
"fetch-blob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.1.tgz",
"integrity": "sha512-Uf+gxPCe1hTOFXwkxYyckn8iUSk6CFXGy5VENZKifovUTZC9eUODWSBhOBS7zICGrAetKzdwLMr85KhIcePMAQ=="
},
"file-entry-cache": {

@@ -652,2 +694,7 @@ "version": "5.0.1",

},
"lodash.deburr": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz",
"integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s="
},
"lunr": {

@@ -703,5 +750,9 @@ "version": "2.3.9",

"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
"version": "3.0.0-beta.9",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.0.0-beta.9.tgz",
"integrity": "sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg==",
"requires": {
"data-uri-to-buffer": "^3.0.1",
"fetch-blob": "^2.1.1"
}
},

@@ -708,0 +759,0 @@ "node-html-parser": {

{
"name": "blog-engine-sac",
"version": "4.0.3",
"version": "5.1.0",
"type": "module",

@@ -9,2 +9,3 @@ "bin": {

"scripts": {
"prepublishOnly": "node -c source/main.js",
"lint-fix": "eslint --ignore-path .gitignore --fix source html",

@@ -14,2 +15,3 @@ "lint": "eslint --ignore-path .gitignore source html"

"dependencies": {
"@sindresorhus/slugify": "^1.1.0",
"filesac": "^11.1.1",

@@ -19,3 +21,3 @@ "html-escaper": "^3.0.0",

"markdown": "^0.5.0",
"node-fetch": "^2.6.1",
"node-fetch": "^3.0.0-beta.9",
"node-html-parser": "^1.1.12",

@@ -22,0 +24,0 @@ "rollup": "^2.0.0",

@@ -27,7 +27,27 @@ # Blog

{
"mainTitle": "BLOG",
"subTitle": "FOOD AND FUN",
"defaultLang": "en",
"defaultAuthor": "AUTHOR NAME"
"defaultAuthor": "AUTHOR NAME",
"defaultLicense": "LICENSE",
"categories": [{
"tag": "categorieA",
"name": "categorieA"
},{
"tag": "categorieB",
"name": "categorieB"
}]
}
```
Change the values as you see fit.
#### categories
categories are provided by the user as an array for the entire blog
for example: travel, cuisine, sports
Each category will have a dedicated index page that acts like the main index page but only lists post of that category. Posts will be in that category if they have a corresponding tag.
### about page

@@ -46,23 +66,3 @@

### categories
Create file `source/extras/categories.json`
With the following content
```json
[{
"tag": "categorieA",
"name": "categorieA"
},{
"tag": "categorieB",
"name": "categorieB"
}]
```
categories are provided by the user as an array for the entire blog
for example: travel, cuisine, sports
Each category will have a dedicated index page that acts like the main index page but only lists post of that category. Posts will be in that category if they have a corresponding tag.
### Edit Images

@@ -69,0 +69,0 @@

@@ -1,2 +0,2 @@

export { processPost, supportedFormats, getDetailsFromPost };
export { processPost, processExternalPost, supportedFormats, getDetailsFromPost };

@@ -8,9 +8,14 @@ import { statSync, readdir, fstat } from "fs";

import { isLocalUrl } from "./urls.js";
import markdownModule from "markdown";
const { markdown } = markdownModule;
import nodeHtmlParser from "node-html-parser";
const { parse } = nodeHtmlParser;
import { processPostAsJSON, formatJSON } from "./processors/json.js";
import { processPostAsHTML, formatHTML } from "./processors/html.js";
import { processPostAsTXT, formatTXT } from "./processors/txt.js";
import { processPostAsMD, formatMD } from "./processors/md.js";
const supportedFormats = [`md`, `json`, `html`];
const supportedFormats = [
...formatJSON,
...formatHTML,
...formatTXT,
...formatMD,
];

@@ -33,65 +38,27 @@ const isMeta = (post) => {

if (extension === `html`) {
if (formatHTML.includes(extension)) {
return processPostAsHTML(meta);
}
if (extension === `md`) {
if (formatMD.includes(extension)) {
return processPostAsMD(meta);
}
if (extension === `json`) {
return processPostAsJSON(meta, detailedFiles);
if (formatTXT.includes(extension)) {
return processPostAsTXT(meta);
}
};
const processPostAsHTML = function (post) {
const { content } = post;
const htmlContainers = [`html`, `body`, `head`];
const rootOriginal = parse(content);
const root = rootOriginal.firstChild;
const rawText = root.text;
let htmlBody;
if (!htmlContainers.includes(root.tagName)) {
htmlBody = rootOriginal.innerHTML;
} else if (root.tagName === `html`) {
const html = root;
const head = html.querySelector(`head`);
const body = html.querySelector(`body`);
if (body) {
htmlBody = body.innerHTML;
} else {
htmlBody = root.innerHTML;
}
} else if (root.tagName === `body`) {
const body = root;
htmlBody = body.innerHTML;
} else {
console.warn(`${root.tagName} as root is not supported`);
htmlBody = ``;
if (formatJSON.includes(extension)) {
return processPostAsJSON(meta, detailedFiles);
}
return Object.assign(post, {
body: htmlBody,
raw: rawText,
});
};
const processPostAsMD = function (post) {
const { content } = post;
let postHTML;
if (content) {
postHTML = markdown.toHTML(content);
} else {
postHTML = `<p>Empty</p>`;
}
return Object.assign(post, {
body: postHTML,
raw: content,
});
};
const processExternalPost = function ({ src, meta }) {
const processExternalPost = function (post) {
const { src } = post;
let contentType;
return fetch(src).then(response => {
if (response.ok) {
contentType = response.headers.get('Content-Type');
return response.text();

@@ -101,2 +68,8 @@ }

}).then(text => {
// process as md maybe
// todo make generic
if (contentType === `text/md` || src.slice(-3) === `.md`) {
post.content = text;
return processPostAsMD(post);
}
return Object.assign({

@@ -106,3 +79,3 @@ body: text,

title: src,
}, meta);
}, post);
}).catch(error => {

@@ -116,27 +89,6 @@ console.warn(`could not fetch ${src}`);

title: src,
}, meta);
}, post);
});
};
const processPostAsJSON = function (post, detailedFiles, metas, commonOptions) {
const { content, fullPath } = post;
let postObject;
try {
postObject = JSON.parse(content);
} catch (error) {
console.error(`could not parse as JSON ${fullPath}`);
console.error(error);
return;
}
const { src } = postObject;
if (!src) {
return;
}
if (isLocalUrl(src)) {
// open from file
return processPost(getDetailsFromPost(src), detailedFiles, metas, commonOptions);
}
return processExternalPost({ ...post, src });
};
const defaultMetaFromPost = function ({ fullPath, title}, {defaultLang, defaultAuthor }) {

@@ -172,2 +124,3 @@ let stats;

sortedWords: [],
translations: [],
lang: defaultLang,

@@ -174,0 +127,0 @@ };

@@ -7,2 +7,3 @@ /* stats.birthtime, can be later than modified date

import { textFileContent, writeTextInFile, namesInDirectory } from "filesac";
import slugify from "@sindresorhus/slugify";
import { generateTags, wordCount, setFinalTags } from "./tags.js";

@@ -14,2 +15,3 @@ import { niceDateString, normalizeDate } from "./dates.js";

import { processMetaFile } from "./meta.js";
import { consoleOutputEarly, consoleOutputReady } from "./reporter/consoleOutput.js";
import {chainPromises} from "utilsac";

@@ -41,3 +43,2 @@ import { dirname, parse as parsePath } from "path";

const footerSource = `${postsPath}/extras/footer.md`;
const categoriesSource = `${postsPath}/extras/categories.json`;
// output

@@ -99,3 +100,3 @@ const builtBlog = `./result`;

}, commonOptions));
return writeTextInFile(`${categoriesPath}${categoryName}.html`,
return writeTextInFile(`${categoriesPath}${slugify(categoryName)}.html`,
categoryHTML

@@ -108,7 +109,7 @@ );

const createIndex = function (posts, categories, lang, commonOptions) {
const indexHTML = createIndexHtml(Object.assign({
const indexHTML = createIndexHtml(Object.assign({}, commonOptions, {
posts,
categories,
lang,
}, commonOptions));
}));

@@ -150,3 +151,3 @@ const indexPath = `${builtBlog}/${indexFileName(lang, commonOptions.defaultLang)}`;

return Promise.all(posts.map(function (post) {
const postInsideHTML = createPostHtml(Object.assign(post, commonOptions));
const postInsideHTML = createPostHtml(Object.assign({}, commonOptions, post));
return writeTextInFile(`${blogPath}${post.base}.html`, postInsideHTML);

@@ -156,7 +157,2 @@ }));

const getCategoriesList = async () => {
const listJson = await textFileContent(categoriesSource);
return JSON.parse(listJson);
};
const buildSite = async () => {

@@ -167,3 +163,2 @@ // independent

});
const categoriesPromise = getCategoriesList();
const [sourceFileNames, footerText, userOptionsText, defaultOptionsText] = await Promise.all([

@@ -183,2 +178,4 @@ namesInDirectory(postsPath),

commonOptions.footerText = footerHTML;
commonOptions.tabTitle = commonOptions.tabTitle || commonOptions.mainTitle;
commonOptions.lang = commonOptions.defaultLang;

@@ -198,6 +195,3 @@ const sourceFileNames2 = sourceFileNames.map((file) => {

return post.src;
}).filter(post => {
if (!post.ready) {
console.log(`\t-- ${post.title} not ready`);
}
}).map(consoleOutputEarly).filter(post => {
return post.ready;

@@ -211,10 +205,2 @@ });

});
posts.forEach(function (post, i) {
const { indexed } = post;
if (indexed) {
console.log(`\t++ ${post.title}`);
} else {
console.log(`\t+- ${post.title} not indexed`);
}
});

@@ -240,8 +226,11 @@ /*

return !posts.some(postB => {
// todo (set and) use isTranslation
return post !== postB && postB.translations && postB.translations.some(translation => {
if (parsePath(translation.src).name === post.base) {
langUsed.add(translation.lang)
linkedTranslations.add(postB)
langUsed.add(translation.lang);
linkedTranslations.add(postB);
const temp = Object.assign({}, postB, post);
delete temp[`translations`];
Object.assign(post, temp);
Object.assign(post, translation);
post.isTranslation = true;
translation.post = post;

@@ -262,5 +251,3 @@ };

const nonLinkedYet = nonLinkedYetLink.post;
if (nonLinkedYet.translations) {
return;
}
nonLinkedYet.translations = postWithTranslations.translations.filter(a => {

@@ -274,2 +261,7 @@ return a.post === nonLinkedYetLink;

posts.sort((a, b) => {
return Number(a.indexed) - Number(b.indexed);
});
posts.forEach(consoleOutputReady);
indexedPosts.forEach(function (post, i) {

@@ -282,5 +274,4 @@ post.next = indexedPosts[i - 1];

const aboutPromise = createAbout(commonOptions);
const categories = await categoriesPromise;
const categoryMap = createCategoryMap(indexedPosts, categories, commonOptions);
const hiddenCategoryMap = createHiddenCategoryMap(indexedPosts, categories, categoryMap, commonOptions);
const categoryMap = createCategoryMap(indexedPosts, commonOptions.categories, commonOptions);
const hiddenCategoryMap = createHiddenCategoryMap(indexedPosts, commonOptions.categories, categoryMap, commonOptions);
createCategoryPages(categoryMap, hiddenCategoryMap, commonOptions);

@@ -287,0 +278,0 @@ const indexesPromise = createIndexes(indexedPosts, categoryMap, langUsed, commonOptions);

@@ -0,0 +0,0 @@ export { processMetaFile };

@@ -0,0 +0,0 @@ export { isLocalUrl };

@@ -6,2 +6,3 @@ export { translations };

fr: {
Translations: `Traductions`,
Home: `Accueil`,

@@ -15,3 +16,6 @@ About: `À propos`,

[`Next`]: `Suivant`,
},
en: {
Home: `Home`
}
}

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