ssg-api
Advanced tools
Comparing version 1.2.13 to 1.3.0
@@ -8,3 +8,3 @@ # Change Log | ||
## [1.3.0] - To be released | ||
## [1.3.0] - 2022-12-04 | ||
@@ -14,4 +14,4 @@ ### Changed | ||
- context variables scoped | ||
- under `context.` prefix to avoid collision with JS variables. | ||
- under reserved prefixes for each built-in object (like `context.inputFile`, etc.) | ||
- under `$context.` prefix to avoid collision with JS variables. | ||
- under reserved prefixes for each built-in object (like `$context._name`, `$context.inputFile.name`, etc.) | ||
@@ -18,0 +18,0 @@ ## [1.2.13] - 2022-12-03 |
@@ -1,12 +0,8 @@ | ||
import { BuiltInVars, SsgContext } from "./SsgContext"; | ||
import { HtmlLinks, HtmlMeta, HtmlSsgFile } from "./util/file/HtmlSsgFile"; | ||
declare type HtmlBuiltInVars = keyof HtmlMeta | keyof HtmlLinks; | ||
declare type AllHtmlBuiltInVars = BuiltInVars | HtmlBuiltInVars; | ||
export declare type HtmlVarProp<V> = keyof AllHtmlBuiltInVars | keyof V; | ||
import { SsgContext } from "./SsgContext"; | ||
import { HtmlSsgFile } from "./util/file/HtmlSsgFile"; | ||
export interface HtmlSsgContext<V = any> extends SsgContext<V> { | ||
inputFile: HtmlSsgFile; | ||
outputFile: HtmlSsgFile; | ||
getVar(varName: HtmlVarProp<V>): string | undefined; | ||
setVar(varName: HtmlVarProp<V>, value: any): void; | ||
getVar(varName: string): string | undefined; | ||
setVar(varName: string, value: any): void; | ||
} | ||
export {}; |
import { SsgFile } from "./util/file/SsgFile"; | ||
import { Logger } from "./Logger"; | ||
export declare type BuiltInVars = SsgFile | undefined; | ||
export declare type VarProp<V> = keyof BuiltInVars | keyof V; | ||
export interface SsgContext<V = any> extends Logger { | ||
@@ -28,4 +26,4 @@ /** | ||
outputFile: SsgFile; | ||
getVar(varName: VarProp<V>): string | undefined; | ||
setVar(varName: VarProp<V>, value: any): void; | ||
getVar(varName: string): string | undefined; | ||
setVar(varName: string, value: any): void; | ||
clone(): SsgContext<V>; | ||
@@ -32,0 +30,0 @@ /** |
import { SsgFile } from "./util/file/SsgFile"; | ||
import { BuiltInVars, SsgContext, VarProp } from "./SsgContext"; | ||
import { WithPropsOf } from "./util/WithPropsOf"; | ||
import { SsgContext } from "./SsgContext"; | ||
import { Logger } from "./Logger"; | ||
declare type AllVars<V> = V & BuiltInVars; | ||
export declare class SsgContextImpl<V = any> implements SsgContext<V> { | ||
readonly locale: string; | ||
protected vars: Map<string, any>; | ||
readonly logger: Logger; | ||
static readonly CONTEXT_PREFIX = "$context."; | ||
static readonly DEFAULT_NAME = "Ssg"; | ||
@@ -26,5 +26,4 @@ readonly log: { | ||
}; | ||
protected vars: WithPropsOf<AllVars<V>>; | ||
protected stack: string[]; | ||
constructor(locale: string, vars: WithPropsOf<V>, name?: string, logger?: Logger, currentFile?: SsgFile | undefined); | ||
constructor(locale: string, vars?: Map<string, any>, name?: string, logger?: Logger, currentFile?: SsgFile | undefined); | ||
protected _name: string; | ||
@@ -39,4 +38,4 @@ get name(): string; | ||
set outputFile(value: SsgFile); | ||
getVar(varName: VarProp<V>): string | undefined; | ||
setVar(varName: VarProp<V>, value: any): void; | ||
getVar(varName: string): string | undefined; | ||
setVar(varName: string, value: any): void; | ||
clone(): SsgContext<V>; | ||
@@ -46,2 +45,1 @@ push(newName: string): SsgContext; | ||
} | ||
export {}; |
@@ -1,7 +0,7 @@ | ||
import { SsgFile } from "./util/file/SsgFile"; | ||
import { ObjectUtil } from "./util/ObjectUtil"; | ||
import { DefaultLogger } from "./DefaultLogger"; | ||
export class SsgContextImpl { | ||
constructor(locale, vars, name = SsgContextImpl.DEFAULT_NAME, logger = new DefaultLogger(name), currentFile = undefined) { | ||
constructor(locale, vars = new Map(), name = SsgContextImpl.DEFAULT_NAME, logger = new DefaultLogger(name), currentFile = undefined) { | ||
this.locale = locale; | ||
this.vars = vars; | ||
this.logger = logger; | ||
@@ -15,4 +15,2 @@ this.log = this.logger.log; | ||
this._inputFile = this._outputFile = currentFile; | ||
const builtInVars = { ...currentFile }; | ||
this.vars = { ...builtInVars, ...vars }; | ||
this.stack.push(name); | ||
@@ -48,17 +46,26 @@ this.name = name; | ||
getVar(varName) { | ||
var _a; | ||
if ((_a = this._inputFile) === null || _a === void 0 ? void 0 : _a.hasOwnProperty(varName)) { | ||
const value = this.inputFile[varName]; | ||
return value === null || value === void 0 ? void 0 : value.toString(); | ||
if (varName.startsWith(SsgContextImpl.CONTEXT_PREFIX)) { | ||
const contextPath = varName.substring(SsgContextImpl.CONTEXT_PREFIX.length).split("."); | ||
let obj = this; | ||
for (const path of contextPath) { | ||
obj = obj[path]; | ||
} | ||
return obj.toString(); | ||
} | ||
else { | ||
return this.vars[varName]; | ||
return this.vars.get(varName); | ||
} | ||
} | ||
setVar(varName, value) { | ||
if (SsgFile.prototype.hasOwnProperty.call(SsgFile.prototype, varName)) { | ||
this.inputFile[varName] = value; | ||
if (varName.startsWith(SsgContextImpl.CONTEXT_PREFIX)) { | ||
const contextPath = varName.substring(SsgContextImpl.CONTEXT_PREFIX.length).split("."); | ||
let obj = this; | ||
for (let i = 0; i < contextPath.length - 1; i++) { | ||
const path = contextPath[i]; | ||
obj = obj[path]; | ||
} | ||
return obj[contextPath.length - 1] = value; | ||
} | ||
else { | ||
this.vars[varName] = value; | ||
this.vars.set(varName, value); | ||
} | ||
@@ -83,2 +90,3 @@ } | ||
} | ||
SsgContextImpl.CONTEXT_PREFIX = "$context."; | ||
SsgContextImpl.DEFAULT_NAME = "Ssg"; |
@@ -24,11 +24,22 @@ import { SsgStep } from "../SsgStep"; | ||
}; | ||
/** | ||
* A SsgStep that can perform replacements in files' contents. | ||
*/ | ||
export declare class ContentStep<C extends SsgContext = SsgContext> implements SsgStep<C, ContentStepResult> { | ||
protected contents: ContentStepConfig<C>[]; | ||
protected output: OutputFunc; | ||
/** | ||
* Logger name | ||
*/ | ||
readonly name = "content"; | ||
/** | ||
* | ||
* @param contents The content roots and associated replacements to perform. | ||
* @param output The function that writes the output contents once they are ready. | ||
*/ | ||
constructor(contents: ContentStepConfig<C>[], output: OutputFunc); | ||
execute(context: C): Promise<ContentStepResult>; | ||
protected processRoots(context: C, contentsConfig: ContentStepConfig): Promise<number>; | ||
protected processRoot(context: C, contentsRoot: string, contentsConfig: ContentStepConfig, contentCount: number): Promise<number>; | ||
protected processFile(context: C, filePath: string, contentsConfig: ContentStepConfig, contentCount: number): Promise<number>; | ||
protected processRoot(context: C, contentsRoot: string, contentsConfig: ContentStepConfig, fileCount: number): Promise<number>; | ||
protected processFile(context: C, filePath: string, contentsConfig: ContentStepConfig, fileCount: number): Promise<number>; | ||
} |
import { promise as glob } from "glob-promise"; | ||
import { HtmlSsgFile } from "../../util"; | ||
/** | ||
* A SsgStep that can perform replacements in files' contents. | ||
*/ | ||
export class ContentStep { | ||
/** | ||
* | ||
* @param contents The content roots and associated replacements to perform. | ||
* @param output The function that writes the output contents once they are ready. | ||
*/ | ||
constructor(contents, output) { | ||
this.contents = contents; | ||
this.output = output; | ||
/** | ||
* Logger name | ||
*/ | ||
this.name = "content"; | ||
@@ -19,17 +30,18 @@ } | ||
async processRoots(context, contentsConfig) { | ||
let contentCount = 0; | ||
let fileCount = 0; | ||
for (const contentsRoot of contentsConfig.roots) { | ||
contentCount = await this.processRoot(context, contentsRoot, contentsConfig, contentCount); | ||
fileCount = await this.processRoot(context, contentsRoot, contentsConfig, fileCount); | ||
} | ||
return contentCount; | ||
return fileCount; | ||
} | ||
async processRoot(context, contentsRoot, contentsConfig, contentCount) { | ||
async processRoot(context, contentsRoot, contentsConfig, fileCount) { | ||
context.debug("Processing root", contentsRoot); | ||
const contentFiles = await glob(contentsRoot); | ||
for (const filePath of contentFiles) { | ||
contentCount = await this.processFile(context, filePath, contentsConfig, contentCount); | ||
fileCount = await this.processFile(context, filePath, contentsConfig, fileCount); | ||
} | ||
return contentCount; | ||
return fileCount; | ||
} | ||
async processFile(context, filePath, contentsConfig, contentCount) { | ||
async processFile(context, filePath, contentsConfig, fileCount) { | ||
context.debug("Processing file", filePath); | ||
context.inputFile = HtmlSsgFile.read(context, filePath); | ||
@@ -40,6 +52,6 @@ context.outputFile = contentsConfig.getOutputFile(context); | ||
} | ||
contentCount++; | ||
fileCount++; | ||
await this.output(context, context.outputFile); | ||
return contentCount; | ||
return fileCount; | ||
} | ||
} |
import { RegexReplaceCommand } from "../RegexReplaceCommand"; | ||
export class AngularExpressionReplaceCommand extends RegexReplaceCommand { | ||
constructor() { | ||
super(new RegExp(`{{\\s*(.*?)(?:\\s*\\|\\s*(.*?))\\s*}}`, "gm")); | ||
super(new RegExp(`{{\\s*(.*?)(?:\\s*\\|\\s*(.*?))?\\s*}}`, "gm")); | ||
} | ||
@@ -9,13 +9,21 @@ async createReplacer(context) { | ||
replace(substring, ...args) { | ||
const value = args[0]; | ||
let replacement = value; | ||
const varName = args[0]; | ||
let replacement = context.getVar(varName); | ||
const filter = args[1]; | ||
switch (filter) { | ||
case "number": | ||
replacement = new Intl.NumberFormat(context.locale).format(value); | ||
break; | ||
default: | ||
context.warn("Unsupported Angular filter", filter); | ||
if (filter) { | ||
switch (filter) { | ||
case "number": | ||
if (replacement) { | ||
const num = Number.parseInt(replacement); | ||
replacement = new Intl.NumberFormat(context.locale).format(num); | ||
} | ||
else { | ||
throw Error(`Could not find variable "${varName}"`); | ||
} | ||
break; | ||
default: | ||
context.warn("Unsupported Angular filter", filter); | ||
} | ||
} | ||
return replacement; | ||
return replacement || ""; | ||
} | ||
@@ -22,0 +30,0 @@ }; |
import { RegexReplaceCommand } from "../../RegexReplaceCommand"; | ||
import { RegexReplacer } from "../../RegexReplacer"; | ||
import { HtmlSsgContext, HtmlVarProp } from "../../../../../HtmlSsgContext"; | ||
import { HtmlSsgContext } from "../../../../../HtmlSsgContext"; | ||
import { StringContextHandler } from "../StringContextHandler"; | ||
@@ -9,6 +9,6 @@ /** | ||
export declare class SsiEchoVarReplaceCommand<V = any, C extends HtmlSsgContext<V> = HtmlSsgContext<V>> extends RegexReplaceCommand<V, HtmlSsgContext<V>> { | ||
protected varName: HtmlVarProp<V>; | ||
protected varName: string; | ||
protected defaultHandlers: StringContextHandler[]; | ||
constructor(varName: HtmlVarProp<V>, defaultHandlers?: StringContextHandler[]); | ||
constructor(varName: string, defaultHandlers?: StringContextHandler[]); | ||
protected createReplacer(context: C): Promise<RegexReplacer>; | ||
} |
import { RegexReplaceCommand } from "../../RegexReplaceCommand"; | ||
import { RegexReplaceCallback, RegexReplacer } from "../../RegexReplacer"; | ||
import { SsgContext } from "../../../../../SsgContext"; | ||
/** | ||
* A Regex replace command that looks for SSI variable settings | ||
* (`<!--#set var="someVar" value="someValue"-->) | ||
*/ | ||
export declare class SsiSetVarReplaceCommand extends RegexReplaceCommand { | ||
protected replacer: RegexReplacer; | ||
/** | ||
* | ||
* @param varName The SSI variale to look for. | ||
* @param ssiVarReplacer The replacer that will provide the replacement string. | ||
*/ | ||
constructor(varName: string, ssiVarReplacer: RegexReplaceCallback); | ||
protected createReplacer(context: SsgContext): Promise<RegexReplacer>; | ||
} |
import { RegexReplaceCommand } from "../../RegexReplaceCommand"; | ||
/** | ||
* A Regex replace command that looks for SSI variable settings | ||
* (`<!--#set var="someVar" value="someValue"-->) | ||
*/ | ||
export class SsiSetVarReplaceCommand extends RegexReplaceCommand { | ||
/** | ||
* | ||
* @param varName The SSI variale to look for. | ||
* @param ssiVarReplacer The replacer that will provide the replacement string. | ||
*/ | ||
constructor(varName, ssiVarReplacer) { | ||
@@ -4,0 +13,0 @@ super(new RegExp(`<!--\\s*#set\\s+var="${varName}"\\s+value="(.+?)"\\s*-->`, "gs")); |
import { RegexReplaceCommand } from "../RegexReplaceCommand"; | ||
import { HtmlVarProp } from "../../../../HtmlSsgContext"; | ||
import { RegexReplacer } from "../RegexReplacer"; | ||
@@ -7,6 +6,6 @@ import { StringContextHandler } from "./StringContextHandler"; | ||
export declare class StringEchoVarReplaceCommand<V = any, C extends SsgContext = SsgContext<V>> extends RegexReplaceCommand<V, C> { | ||
protected varName: HtmlVarProp<V>; | ||
protected varName: string; | ||
protected defaultHandlers: StringContextHandler[]; | ||
constructor(varName: HtmlVarProp<V>, defaultHandlers?: StringContextHandler[]); | ||
constructor(varName: string, defaultHandlers?: StringContextHandler[]); | ||
protected createReplacer(context: SsgContext<V>): Promise<RegexReplacer>; | ||
} |
import { RegexReplacer } from "../RegexReplacer"; | ||
import { StringContextHandler } from "./StringContextHandler"; | ||
import { SsgContext, VarProp } from "../../../../SsgContext"; | ||
import { SsgContext } from "../../../../SsgContext"; | ||
export declare class VarRegexReplacer<V = any, C extends SsgContext = SsgContext> implements RegexReplacer { | ||
protected context: C; | ||
protected varName: VarProp<V>; | ||
protected varName: string; | ||
protected defaultHandlers: StringContextHandler<C>[]; | ||
constructor(context: C, varName: VarProp<V>, defaultHandlers: StringContextHandler<C>[]); | ||
constructor(context: C, varName: string, defaultHandlers: StringContextHandler<C>[]); | ||
replace(_match: string, ..._args: any[]): string; | ||
} |
@@ -6,3 +6,3 @@ import { RegexReplacer } from "./RegexReplacer"; | ||
/** | ||
* Performs replacements using a Regular Expression to find patterns to replace. | ||
* A command that performs replacements using a Regular Expression. | ||
*/ | ||
@@ -18,3 +18,9 @@ export declare abstract class RegexReplaceCommand<V = any, C extends SsgContext = SsgContext<V>> implements ReplaceCommand<C> { | ||
execute(context: C): Promise<SsgFile>; | ||
/** | ||
* Create the replacer for a given context. | ||
* | ||
* @param context | ||
* @protected | ||
*/ | ||
protected abstract createReplacer(context: C): Promise<RegexReplacer>; | ||
} |
/** | ||
* Performs replacements using a Regular Expression to find patterns to replace. | ||
* A command that performs replacements using a Regular Expression. | ||
*/ | ||
@@ -4,0 +4,0 @@ export class RegexReplaceCommand { |
export declare type RegexReplaceCallback = (substring: string, ...args: any[]) => string; | ||
/** | ||
* A class that implements the Regex standard replace callback. | ||
* | ||
* Sometimes replacers need some SsgContext to tune their replacements. | ||
* In such case, the replacer should be instantiated through a ReplacerFactory that will instantiate them with a | ||
* SsgContext parameter. | ||
*/ | ||
export interface RegexReplacer { | ||
replace: RegexReplaceCallback; | ||
} |
@@ -7,3 +7,3 @@ import { HtmlSsgFile } from "../src/util/file/HtmlSsgFile"; | ||
newContext(inputFileName, contents) { | ||
const context = new SsgContextImpl("fr", {}); | ||
const context = new SsgContextImpl("fr"); | ||
if (ObjectUtil.isUndefined(contents)) { | ||
@@ -10,0 +10,0 @@ context.inputFile = SsgFile.read(context, inputFileName); |
@@ -5,3 +5,3 @@ { | ||
"author": "Jérôme Beau", | ||
"version": "1.2.13", | ||
"version": "1.3.0", | ||
"description": "Static Site Generation TypeScript API", | ||
@@ -8,0 +8,0 @@ "exports": "./dist/src/index.js", |
@@ -26,3 +26,3 @@ # ssg-api [![CircleCI](https://dl.circleci.com/status-badge/img/gh/Javarome/ssg-api/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/Javarome/ssg-api/tree/main) | ||
const context = new SsgContextImpl("fr", {}) | ||
const context = new SsgContextImpl("fr") | ||
try { | ||
@@ -29,0 +29,0 @@ const result = await ssg.start(context) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
341737
2370