Socket
Socket
Sign inDemoInstall

ssg-api

Package Overview
Dependencies
Maintainers
1
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ssg-api - npm Package Compare versions

Comparing version 1.10.1 to 1.10.3

dist/src/util/file/FileContents.d.ts

12

CHANGELOG.md

@@ -8,2 +8,14 @@ # Change Log

## [1.10.3] - 2024-06-09
### Fixed
- Leave literal template unchanged if no var is found with this name.
## [1.10.1] - 2024-06-03
### Fixed
- Regression when using a var name in VarRegexReplacer.
## [1.10.0] - 2024-06-03

@@ -10,0 +22,0 @@

4

dist/src/OutputFunc.d.ts
import { SsgContext } from "./SsgContext.js";
import { SsgFile } from "./util";
export type OutputFunc = (context: SsgContext, outputFile: SsgFile) => Promise<void>;
import { FileContents } from "./util";
export type OutputFunc = (context: SsgContext, outputFile: FileContents) => Promise<void>;
/// <reference types="node" />
import { Logger } from "./Logger.js";
import { SsgFile } from "./util";
import { FileContents } from "./util";
export interface SsgContext<V = any> extends Logger {

@@ -22,3 +22,3 @@ /**

*/
file: SsgFile;
file: FileContents;
getVar(varName: string): string | undefined;

@@ -43,3 +43,3 @@ setVar(varName: string, value: any): void;

*/
read(filePath: string): SsgFile;
read(filePath: string): FileContents;
/**

@@ -52,3 +52,3 @@ * Reads a file and assign it to the context's `file`.

*/
newOutput(filePath: string, encoding?: BufferEncoding): SsgFile;
newOutput(filePath: string, encoding?: BufferEncoding): FileContents;
}
/// <reference types="node" />
import { SsgContext } from "./SsgContext.js";
import { Logger } from "./Logger.js";
import { SsgFile } from "./util";
import { FileContents } from "./util";
export declare class SsgContextImpl<V = any> implements SsgContext<V> {

@@ -28,9 +28,9 @@ readonly locale: string;

protected stack: string[];
constructor(locale: string, vars?: Map<string, any>, name?: string, logger?: Logger, currentFile?: SsgFile | undefined);
constructor(locale: string, vars?: Map<string, any>, name?: string, logger?: Logger, currentFile?: FileContents | undefined);
protected _name: string;
get name(): string;
set name(newName: string);
protected _file: SsgFile | undefined;
get file(): SsgFile;
set file(value: SsgFile);
protected _file: FileContents | undefined;
get file(): FileContents;
set file(value: FileContents);
getVar(varName: string): string | undefined;

@@ -41,4 +41,4 @@ setVar(varName: string, value: any): void;

pop(): SsgContext;
read(filePath: string): SsgFile;
newOutput(filePath: string, encoding?: BufferEncoding): SsgFile;
read(filePath: string): FileContents;
newOutput(filePath: string, encoding?: BufferEncoding): FileContents;
}
import { ObjectUtil } from "./util/ObjectUtil.js";
import { ConsoleLogger } from "./ConsoleLogger";
import { HtmlSsgFile, SsgFile } from "./util";
import { FileContents, HtmlSsgFile } from "./util";
import * as assert from "node:assert";

@@ -84,4 +84,4 @@ export class SsgContextImpl {

this.file = filePath.endsWith(".html")
? HtmlSsgFile.read(this, filePath)
: SsgFile.read(this, filePath);
? HtmlSsgFile.read(filePath)
: FileContents.read(filePath);
return this.file;

@@ -95,3 +95,3 @@ }

try {
lang = SsgFile.getLang(this, filePath);
lang = FileContents.getLang(filePath);
}

@@ -106,7 +106,7 @@ catch (e) {

if (filePath.endsWith(".html")) {
const fileInfo = new SsgFile(filePath, encoding, this.file.contents, creationDate, lang);
const fileInfo = new FileContents(filePath, encoding, this.file.contents, creationDate, lang);
outFile = HtmlSsgFile.create(fileInfo);
}
else {
outFile = new SsgFile(filePath, encoding, this.file.contents, creationDate, lang);
outFile = new FileContents(filePath, encoding, this.file.contents, creationDate, lang);
}

@@ -113,0 +113,0 @@ this.logger.debug("Created new output file", outFile.name);

import path from "path";
import { RegexReplaceCommand } from "../../RegexReplaceCommand.js";
import { SsgFile } from "../../../../../util/index.js";
import { FileContents } from "../../../../../util";
/**

@@ -27,3 +27,3 @@ * Replaces SSI's `<!-- #include virtual="myFileName" -->` by fileName's contents.

const fileName = path.join(currentDir, toInclude);
const replacement = SsgFile.read(context, fileName);
const replacement = FileContents.read(fileName);
return replacement.contents;

@@ -30,0 +30,0 @@ }

@@ -10,3 +10,3 @@ import { RegexReplacer } from "../RegexReplacer.js";

constructor(context: C, varName?: string, defaultHandlers?: StringContextHandler<C>[]);
replace(_match: string, ...args: any[]): string;
replace(match: string, ...args: any[]): string;
}

@@ -7,3 +7,3 @@ export class VarRegexReplacer {

}
replace(_match, ...args) {
replace(match, ...args) {
let varStr = this.context.getVar(this.varName === VarRegexReplacer.REGEXP_DEFAULT ? args[0] : this.varName);

@@ -13,5 +13,5 @@ if (!varStr) {

}
return varStr || "";
return varStr || match;
}
}
VarRegexReplacer.REGEXP_DEFAULT = "(.*?)";

@@ -16,3 +16,3 @@ import * as process from "process";

context.log("Copying to", dest, copies);
const copiedFiles = await FileUtil.ssgCopy(dest, copies, this.config.options);
const copiedFiles = await FileUtil.copy(dest, copies, this.config.options);
const cwd = process.cwd();

@@ -19,0 +19,0 @@ const files = copiedFiles.map(file => file.startsWith(cwd) ? file.substring(cwd.length + 1) : file);

import { SsgStep } from "./SsgStep.js";
import { SsgContext } from "../SsgContext.js";
import { SsgConfig } from "../SsgConfig";
import { SsgFile } from "../util";
import { FileContents } from "../util";
export interface DirectoryStepConfig extends SsgConfig {

@@ -50,5 +50,3 @@ /**

*/
protected abstract processDirs(context: SsgContext, dirNames: string[], outputFile: SsgFile): Promise<void>;
protected findDirs(fromDirs: string[]): Promise<string[]>;
protected findSubDirs(ofDir: string): Promise<string[]>;
protected abstract processDirs(context: SsgContext, dirNames: string[], outputFile: FileContents): Promise<void>;
}
import { FileUtil } from "../util";
import path from "path";
/**

@@ -29,35 +28,6 @@ * A step to enrich a template from some subdirectories processing.

const outputFile = context.newOutput(outputFilePath);
const dirNames = (await this.findDirs(this.config.rootDirs))
.filter(dirName => !this.config.excludedDirs.includes(dirName));
const dirNames = await FileUtil.findDirs(this.config.rootDirs, this.config.excludedDirs);
await this.processDirs(context, dirNames, outputFile);
return { directoryCount: dirNames.length };
}
async findDirs(fromDirs) {
let dirNames = [];
for (let fromDir of fromDirs) {
const subDirs = await this.findSubDirs(fromDir);
dirNames = dirNames.concat(subDirs);
}
return dirNames;
}
async findSubDirs(ofDir) {
let subDirs = [];
if (ofDir.endsWith("/*/")) {
const baseDir = ofDir.substring(0, ofDir.length - 3);
if (baseDir.endsWith("/*")) {
const dirs = (await this.findDirs([baseDir + "/"]))
.filter(dirName => !this.config.excludedDirs.includes(dirName));
for (const dir of dirs) {
subDirs = subDirs.concat(await this.findDirs([dir + "/*/"]));
}
}
else {
subDirs = (await FileUtil.dirNames(baseDir)).map(x => path.join(baseDir, x));
}
}
else {
subDirs = [ofDir];
}
return subDirs;
}
}
/// <reference types="node" />
/// <reference types="node" />
import { IOptions } from "glob";
import { Dirent } from "node:fs";
/**
* File utility functions
*/
export declare class FileUtil {
/**
* Converts encoding names to Node's buffer encoding names.
*
* @param encoding The encoding name ("iso-8859-1", "windows-1252", etc.)
* @return The matching BufferEncoding, or undefined if not supported.
*/
static toBufferEncoding(encoding: string | undefined): BufferEncoding | undefined;
/**
* Detect the encoding of some file contents.
*
* @param fileName The name of the file to read.
*/
static detectEncoding(fileName: string): BufferEncoding | undefined;
static getCharSet(html: HTMLElement): BufferEncoding | undefined;
/**
* Detect the encoding of some contents.
*
* @param buffer The buffer holding the contents.
*/
static detectContentsEncoding(buffer: Buffer): BufferEncoding | undefined;
/**
* Checks if a directory exists and, if not, creates it.
*
* @param dir The path of the directory that must exist.
* @param filePath The path of the directory that must exist.
*/
static ensureDirectoryExistence(dir: string): string;
static writeFile(fileName: string, contents: string, encoding: BufferEncoding): Promise<void>;
static dirNames(dir: string): Promise<string[]>;
static ensureDirectoryOf(filePath: string): string;
/**
* Writes a file. If the file directory doesn't exit, it is created.
*
* @param filePath The path of the file to write.
* @param contents The file contents to write.
* @param encoding The file contents encoding scheme.
*/
static writeFile(filePath: string, contents: string, encoding: BufferEncoding): Promise<void>;
/**
* Get a list of subdirectories' names.
*
* @param fromDir The name of the root directory to look from.
*/
static subDirs(fromDir: string): Promise<Dirent[]>;
/**
* Get a list of subdirectories' names.
*
* @param fromDir The name of the root directory to look from.
*/
static subDirsNames(fromDir: string): Promise<string[]>;
static findDirs(fromDirs: string[], excludedDirs?: string[]): Promise<string[]>;
static findSubDirs(ofDir: string, excludedDirs?: string[]): Promise<string[]>;
/**
* Copy files to a destination directory.

@@ -23,6 +64,5 @@ *

*/
static ssgCopy(toDir: string, sourcePatterns: string[], options?: IOptions): Promise<string[]>;
static copy(toDir: string, sourcePatterns: string[], options?: IOptions): Promise<string[]>;
static copyFiles(sourceFiles: string[], toDir: string): string[];
static copyFile(sourceFile: string, toDir: string): string;
static getContentType(html: HTMLElement): BufferEncoding | undefined;
}
import * as fs from "fs";
import { promises as fsAsync } from "fs";
import { detectEncoding } from "char-encoding-detector";
import { detectEncoding as _detectEncoding } from "char-encoding-detector";
import path from "path";
import { readdir } from "fs/promises";
import { promise as glob } from "glob-promise";
/**
* File utility functions
*/
export class FileUtil {
/**
* Converts encoding names to Node's buffer encoding names.
*
* @param encoding The encoding name ("iso-8859-1", "windows-1252", etc.)
* @return The matching BufferEncoding, or undefined if not supported.
*/
static toBufferEncoding(encoding) {

@@ -22,7 +31,20 @@ switch (encoding === null || encoding === void 0 ? void 0 : encoding.toLowerCase()) {

}
/**
* Detect the encoding of some file contents.
*
* @param fileName The name of the file to read.
*/
static detectEncoding(fileName) {
const fileBuffer = fs.readFileSync(fileName);
return FileUtil.detectContentsEncoding(fileBuffer);
}
/**
* Detect the encoding of some contents.
*
* @param buffer The buffer holding the contents.
*/
static detectContentsEncoding(buffer) {
let guessedEncoding = undefined;
try {
guessedEncoding = detectEncoding(fileBuffer);
guessedEncoding = _detectEncoding(buffer);
}

@@ -38,34 +60,73 @@ catch (e) {

}
static getCharSet(html) {
let charSet;
const charsetEl = html.querySelector("html[charset]");
if (charsetEl) {
const charSetValue = charsetEl.getAttribute("charset") || undefined;
charSet = this.toBufferEncoding(charSetValue);
}
return charSet;
}
/**
* Checks if a directory exists and, if not, creates it.
*
* @param dir The path of the directory that must exist.
* @param filePath The path of the directory that must exist.
*/
static ensureDirectoryExistence(dir) {
const dirname = path.dirname(dir);
static ensureDirectoryOf(filePath) {
const dirname = path.dirname(filePath);
if (!fs.existsSync(dirname)) {
this.ensureDirectoryExistence(dirname); // Recursive to create the whole directories chain.
this.ensureDirectoryOf(dirname); // Recursive to create the whole directories chain.
fs.mkdirSync(dirname);
}
return path.resolve(dir);
return path.resolve(filePath);
}
static async writeFile(fileName, contents, encoding) {
this.ensureDirectoryExistence(fileName);
return fsAsync.writeFile(fileName, contents, { encoding });
/**
* Writes a file. If the file directory doesn't exit, it is created.
*
* @param filePath The path of the file to write.
* @param contents The file contents to write.
* @param encoding The file contents encoding scheme.
*/
static async writeFile(filePath, contents, encoding) {
this.ensureDirectoryOf(filePath);
return fsAsync.writeFile(filePath, contents, { encoding });
}
static async dirNames(dir) {
const dirs = await readdir(dir, { withFileTypes: true });
return dirs.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name);
/**
* Get a list of subdirectories' names.
*
* @param fromDir The name of the root directory to look from.
*/
static async subDirs(fromDir) {
const dirs = await readdir(fromDir, { withFileTypes: true });
return dirs.filter(dirEntry => dirEntry.isDirectory());
}
/**
* Get a list of subdirectories' names.
*
* @param fromDir The name of the root directory to look from.
*/
static async subDirsNames(fromDir) {
const subDirs = await this.subDirs(fromDir);
return subDirs.map(dirEntry => dirEntry.name);
}
static async findDirs(fromDirs, excludedDirs = []) {
let dirNames = [];
for (let fromDir of fromDirs) {
const subDirs = await this.findSubDirs(fromDir, excludedDirs);
dirNames = dirNames.concat(subDirs);
}
return dirNames;
}
static async findSubDirs(ofDir, excludedDirs = []) {
let subDirs = [];
if (ofDir.endsWith("/*/")) {
const baseDir = ofDir.substring(0, ofDir.length - 3);
if (baseDir.endsWith("/*")) {
const dirs = (await this.findDirs([baseDir + "/"]))
.filter(dirName => !excludedDirs.includes(dirName));
for (const dir of dirs) {
subDirs = subDirs.concat(await this.findDirs([dir + "/*/"]));
}
}
else {
subDirs = (await FileUtil.subDirsNames(baseDir)).map(x => path.join(baseDir, x));
}
}
else {
subDirs = [ofDir];
}
return subDirs;
}
/**
* Copy files to a destination directory.

@@ -78,3 +139,3 @@ *

*/
static async ssgCopy(toDir, sourcePatterns, options) {
static async copy(toDir, sourcePatterns, options) {
let result = [];

@@ -99,26 +160,6 @@ for (const sourcePattern of sourcePatterns) {

const to = path.join(toDir, sourceFile);
this.ensureDirectoryExistence(to);
this.ensureDirectoryOf(to);
fs.copyFileSync(from, to);
return to;
}
static getContentType(html) {
let contentType;
const contentTypeEl = html.querySelector("meta[http-equiv='Content-Type']");
if (contentTypeEl) {
const content = contentTypeEl.getAttribute("content");
if (content) {
const values = content.split(";");
if (values.length > 0) {
let value = values[1];
let key = "charset=";
let charsetPos = value.indexOf(key);
if (charsetPos >= 0) {
const charset = value.substring(charsetPos + key.length).toLowerCase().trim();
contentType = this.toBufferEncoding(charset);
}
}
}
}
return contentType;
}
}
/// <reference types="node" />
import { SsgContext } from "../../SsgContext.js";
import { SsgFile, SsgFileLang } from "./SsgFile.js";
import { FileContents, SsgFileLang } from "./FileContents";
import { JSDOM } from "jsdom";

@@ -36,3 +35,3 @@ export type HtmlMeta = {

*/
export declare class HtmlSsgFile extends SsgFile {
export declare class HtmlSsgFile extends FileContents {
readonly meta: HtmlMeta;

@@ -52,4 +51,9 @@ readonly links: HtmlLinks;

set contents(value: string);
static read(context: SsgContext, fileName: string): HtmlSsgFile;
static create(fileInfo: SsgFile): HtmlSsgFile;
static read(fileName: string): HtmlSsgFile;
/**
* Create an HtmlSsgFile from a SsgFile
*
* @param fileInfo
*/
static create(fileInfo: FileContents): HtmlSsgFile;
static getMeta(name: string, doc: Document): string[];

@@ -56,0 +60,0 @@ static getLink(rel: LinkType, doc: Document): Link | undefined;

@@ -1,3 +0,4 @@

import { SsgFile } from "./SsgFile.js";
import { FileContents } from "./FileContents";
import { JSDOM } from "jsdom";
import { HtmlUtil } from "./HtmlUtil";
export var LinkType;

@@ -17,3 +18,3 @@ (function (LinkType) {

*/
export class HtmlSsgFile extends SsgFile {
export class HtmlSsgFile extends FileContents {
constructor(name, encoding, contents, lastModified, lang, meta, links, title) {

@@ -48,8 +49,17 @@ super(name, encoding, contents, lastModified, lang);

}
static read(context, fileName) {
const fileInfo = super.read(context, fileName);
static read(fileName) {
const fileInfo = super.read(fileName);
return this.create(fileInfo);
}
/**
* Create an HtmlSsgFile from a SsgFile
*
* @param fileInfo
*/
static create(fileInfo) {
const dom = new JSDOM(fileInfo.contents);
const declaredEncoding = HtmlUtil.getHtmlDeclaredEncoding(dom);
if (declaredEncoding !== fileInfo.encoding) {
console.warn(`Encoding of ${fileInfo.name} is ${fileInfo.encoding} but declares ${declaredEncoding}`);
}
let title;

@@ -56,0 +66,0 @@ const doc = dom.window.document;

@@ -1,3 +0,4 @@

export * from "./SsgFile.js";
export * from "./FileContents.js";
export * from "./FileUtil.js";
export * from "./HtmlSsgFile.js";
export * from "./HtmlUtil.js";

@@ -1,3 +0,4 @@

export * from "./SsgFile.js";
export * from "./FileContents.js";
export * from "./FileUtil.js";
export * from "./HtmlSsgFile.js";
export * from "./HtmlUtil.js";

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

"author": "Jérôme Beau <javarome@gmail.com> (https://javarome.com)",
"version": "1.10.1",
"version": "1.10.3",
"description": "Static Site Generation TypeScript API",

@@ -20,5 +20,5 @@ "exports": "./dist/src/index.js",

"scripts": {
"prebuild": "npm install",
"prebuild": "npm install && npm test",
"build": "rm -Rf dist && tsc --project tsconfig.prod.json",
"prepublishOnly": "npm run build && npm test",
"prepublishOnly": "npm run build",
"test": "rm -Rf out && tsx src/testAll.ts",

@@ -25,0 +25,0 @@ "test-one": "rm -Rf out && tsx src/step/content/replace/html/StringEchoVarReplaceCommandTest.ts",

@@ -20,6 +20,3 @@ {

"src"
],
"exclude": [
"test/**/*.*"
]
}

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

"sourceMap": false
}
},
"exclude": [
"test/**/*.*"
]
}
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