Comparing version 1.7.7 to 1.8.0
@@ -8,2 +8,9 @@ # Change Log | ||
## [1.8.0] - 2024-05-18 | ||
### Changed | ||
- `SsgContext.inputFile` and `SsgContext.inputFile` are replaced by `SsgContext.file` | ||
## [1.7.7] - 2024-05-17 | ||
@@ -14,3 +21,3 @@ | ||
- `ContentStepConfig.getOutputFile(context)` can now return SsgFile or file path | ||
- | ||
## [1.7.6] - 2024-05-17 | ||
@@ -17,0 +24,0 @@ |
import { SsgContext } from "./SsgContext.js"; | ||
import { HtmlSsgFile } from './util/index.js'; | ||
import { HtmlSsgFile } from "./util"; | ||
export interface HtmlSsgContext<V = any> extends SsgContext<V> { | ||
inputFile: HtmlSsgFile; | ||
outputFile: HtmlSsgFile; | ||
file: HtmlSsgFile; | ||
getVar(varName: string): string | undefined; | ||
setVar(varName: string, value: any): void; | ||
} |
import { SsgContext } from './SsgContext.js'; | ||
import { SsgFile } from './util/index.js'; | ||
import { SsgFile } from "./util"; | ||
export type OutputFunc = (context: SsgContext, outputFile: SsgFile) => Promise<void>; |
@@ -19,9 +19,5 @@ import { Logger } from "./Logger.js"; | ||
/** | ||
* The file that has been read (a template for instance). | ||
* The file that is being processed (a template for instance). | ||
*/ | ||
inputFile: SsgFile; | ||
/** | ||
* The file that will be written. | ||
*/ | ||
outputFile: SsgFile; | ||
file: SsgFile; | ||
getVar(varName: string): string | undefined; | ||
@@ -28,0 +24,0 @@ setVar(varName: string, value: any): void; |
@@ -32,8 +32,5 @@ /// <reference types="node" /> | ||
set name(newName: string); | ||
protected _inputFile: SsgFile | undefined; | ||
get inputFile(): SsgFile; | ||
set inputFile(value: SsgFile); | ||
protected _outputFile: SsgFile | undefined; | ||
get outputFile(): SsgFile; | ||
set outputFile(value: SsgFile); | ||
protected _file: SsgFile | undefined; | ||
get file(): SsgFile; | ||
set file(value: SsgFile); | ||
getVar(varName: string): string | undefined; | ||
@@ -40,0 +37,0 @@ setVar(varName: string, value: any): void; |
@@ -15,3 +15,3 @@ import { ObjectUtil } from "./util/ObjectUtil.js"; | ||
this._name = SsgContextImpl.DEFAULT_NAME; | ||
this._inputFile = this._outputFile = currentFile; | ||
this._file = currentFile; | ||
this.stack.push(name); | ||
@@ -31,17 +31,8 @@ this.name = name; | ||
} | ||
get inputFile() { | ||
return ObjectUtil.asSet(this._inputFile, "Should have a inputFile"); | ||
get file() { | ||
return ObjectUtil.asSet(this._file, "Should have a inputFile"); | ||
} | ||
set inputFile(value) { | ||
this._inputFile = value; | ||
if (!this._outputFile) { | ||
this._outputFile = this._inputFile; | ||
} | ||
set file(value) { | ||
this._file = value; | ||
} | ||
get outputFile() { | ||
return ObjectUtil.asSet(this._outputFile, "Should have a outputFile"); | ||
} | ||
set outputFile(value) { | ||
this._outputFile = value; | ||
} | ||
getVar(varName) { | ||
@@ -75,3 +66,3 @@ if (varName.startsWith(SsgContextImpl.CONTEXT_PREFIX)) { | ||
clone() { | ||
return new SsgContextImpl(this.locale, this.vars, this.name, this.logger, this._inputFile); | ||
return new SsgContextImpl(this.locale, this.vars, this.name, this.logger, this._file); | ||
} | ||
@@ -100,3 +91,3 @@ push(newName) { | ||
if (e.code === "ENOENT") { | ||
outFile = this.createOutput(filePath, ((_a = this._outputFile) === null || _a === void 0 ? void 0 : _a.encoding) || "utf-8"); | ||
outFile = this.createOutput(filePath, ((_a = this._file) === null || _a === void 0 ? void 0 : _a.encoding) || "utf-8"); | ||
} | ||
@@ -107,8 +98,7 @@ else { | ||
} | ||
this.outputFile = outFile; | ||
return this.outputFile; | ||
return outFile; | ||
} | ||
getInputFrom(filePath) { | ||
this.inputFile = this.readFile(filePath); | ||
return this.inputFile; | ||
this.file = this.readFile(filePath); | ||
return this.file; | ||
} | ||
@@ -129,7 +119,7 @@ createOutput(filePath, encoding) { | ||
if (filePath.endsWith(".html")) { | ||
const fileInfo = new SsgFile(filePath, encoding, this.inputFile.contents, creationDate, lang); | ||
const fileInfo = new SsgFile(filePath, encoding, this.file.contents, creationDate, lang); | ||
outFile = HtmlSsgFile.create(fileInfo); | ||
} | ||
else { | ||
outFile = new SsgFile(filePath, encoding, this.inputFile.contents, creationDate, lang); | ||
outFile = new SsgFile(filePath, encoding, this.file.contents, creationDate, lang); | ||
} | ||
@@ -136,0 +126,0 @@ this.logger.debug("Created new output file", outFile.name); |
@@ -12,3 +12,3 @@ import { SsgStep } from "../SsgStep.js"; | ||
export declare class ContentStep<C extends SsgContext = SsgContext> implements SsgStep<C, ContentStepResult> { | ||
protected contents: ContentStepConfig<C>[]; | ||
protected contentsConfigs: ContentStepConfig<C>[]; | ||
protected output: OutputFunc; | ||
@@ -21,6 +21,6 @@ /** | ||
* | ||
* @param contents The content roots and associated replacements to perform. | ||
* @param contentsConfigs 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); | ||
constructor(contentsConfigs: ContentStepConfig<C>[], output: OutputFunc); | ||
execute(context: C): Promise<ContentStepResult>; | ||
@@ -47,6 +47,7 @@ protected processRoots(context: C, contentsConfig: ContentStepConfig): Promise<number>; | ||
* @param context | ||
* @param contentsConfig | ||
* @return If the for this context should be processed or not. | ||
* @protected | ||
*/ | ||
protected shouldProcess(context: C): boolean; | ||
protected shouldProcess(context: C, contentsConfig: ContentStepConfig): boolean; | ||
} |
import fs from "fs"; | ||
import { promise as glob } from "glob-promise"; | ||
import { SsgFile } from "../../util"; | ||
/** | ||
@@ -10,7 +9,7 @@ * A SsgStep that can perform replacements in files' contents. | ||
* | ||
* @param contents The content roots and associated replacements to perform. | ||
* @param contentsConfigs 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; | ||
constructor(contentsConfigs, output) { | ||
this.contentsConfigs = contentsConfigs; | ||
this.output = output; | ||
@@ -24,6 +23,6 @@ /** | ||
let contentCount = 0; | ||
for (const contents of this.contents) { | ||
contentCount += await this.processRoots(context, contents); | ||
for (const contentsConfig of this.contentsConfigs) { | ||
contentCount += await this.processRoots(context, contentsConfig); | ||
} | ||
for (const contents of this.contents) { | ||
for (const contents of this.contentsConfigs) { | ||
for (const replacement of contents.replacements) { | ||
@@ -64,11 +63,11 @@ await replacement.contentStepEnd(); | ||
context.debug("Processing file", filePath); | ||
context.inputFile = context.getInputFrom(filePath); | ||
const outputFile = contentsConfig.getOutputFile(context); | ||
context.outputFile = outputFile instanceof SsgFile ? outputFile : context.getOutputFrom(outputFile); | ||
const processed = this.shouldProcess(context); | ||
context.file = context.getInputFrom(filePath); | ||
const outputPath = contentsConfig.getOutputFile(context); | ||
const outputFile = context.getOutputFrom(outputPath); | ||
const processed = this.shouldProcess(context, contentsConfig); | ||
if (processed) { | ||
for (const replacement of contentsConfig.replacements) { | ||
context.outputFile = await replacement.execute(context); | ||
await replacement.execute(context); | ||
} | ||
await this.output(context, context.outputFile); | ||
await this.output(context, outputFile); | ||
} | ||
@@ -82,20 +81,22 @@ return processed; | ||
* @param context | ||
* @param contentsConfig | ||
* @return If the for this context should be processed or not. | ||
* @protected | ||
*/ | ||
shouldProcess(context) { | ||
let process; | ||
const exists = fs.existsSync(context.outputFile.name); | ||
if (exists) { | ||
const outStats = fs.statSync(context.outputFile.name); | ||
process = outStats.mtime < context.inputFile.lastModified; | ||
if (!process) { | ||
console.debug(context.inputFile.name, "is not older that current out file"); | ||
shouldProcess(context, contentsConfig) { | ||
let inputHasChanged; | ||
const outputPath = contentsConfig.getOutputFile(context); | ||
const outputExists = fs.existsSync(outputPath); | ||
if (outputExists) { | ||
const outputStats = fs.statSync(outputPath); | ||
inputHasChanged = context.file.lastModified > outputStats.mtime; | ||
if (!inputHasChanged) { | ||
console.debug(context.file.name, "is not older that current out file"); | ||
} | ||
} | ||
else { | ||
process = true; | ||
inputHasChanged = true; | ||
} | ||
return process; | ||
return inputHasChanged; | ||
} | ||
} |
@@ -1,4 +0,3 @@ | ||
import { SsgContext } from '../../SsgContext'; | ||
import { ReplaceCommand } from './replace'; | ||
import { SsgFile } from '../../util'; | ||
import { SsgContext } from "../../SsgContext"; | ||
import { ReplaceCommand } from "./replace"; | ||
export type ContentStepConfig<C extends SsgContext = SsgContext> = { | ||
@@ -17,3 +16,3 @@ /** | ||
*/ | ||
getOutputFile(context: C): SsgFile | string; | ||
getOutputFile(context: C): string; | ||
}; |
@@ -8,3 +8,3 @@ import { RegexReplaceCommand } from "../RegexReplaceCommand.js"; | ||
return { | ||
replace(substring, ...args) { | ||
replace(_substring, ...args) { | ||
const varName = args[0]; | ||
@@ -11,0 +11,0 @@ let replacement = context.getVar(varName); |
import { ReplaceCommand } from "./ReplaceCommand.js"; | ||
import { SsgFile } from '../../../util/index.js'; | ||
import { HtmlSsgContext } from "../../../HtmlSsgContext.js"; | ||
@@ -8,3 +7,3 @@ import { DomReplacer } from "./DomReplacer.js"; | ||
constructor(selector: string); | ||
execute(context: C): Promise<SsgFile>; | ||
execute(context: C): Promise<void>; | ||
/** | ||
@@ -11,0 +10,0 @@ * Creates a replacer in a given context. |
@@ -6,3 +6,3 @@ export class DomReplaceCommand { | ||
async execute(context) { | ||
const inputFile = context.inputFile; | ||
const inputFile = context.file; | ||
let contents = inputFile.contents; | ||
@@ -23,5 +23,4 @@ let result = contents; | ||
} while (result != contents); | ||
context.outputFile.contents = result; | ||
context.file.contents = result; | ||
await this.postExecute(context); | ||
return inputFile; | ||
} | ||
@@ -28,0 +27,0 @@ /** |
import { ReplaceCommand } from "../ReplaceCommand.js"; | ||
import { SsgFile } from '../../../../util/index.js'; | ||
import { SsgContext } from "../../../../SsgContext.js"; | ||
export declare abstract class HtAccessReplaceCommand implements ReplaceCommand<SsgContext> { | ||
execute(context: SsgContext): Promise<SsgFile>; | ||
protected abstract handleDirectoryIndex(args: string[], result: string): string; | ||
execute(context: SsgContext): Promise<void>; | ||
protected abstract handleDirectoryIndex(args: string[], result: string[]): void; | ||
protected abstract handleRedirect(from: string, to: string): string; | ||
contentStepEnd(): Promise<void>; | ||
} |
@@ -16,6 +16,6 @@ var HtAccessCommands; | ||
async execute(context) { | ||
const inputFileInfo = context.inputFile; | ||
const inputFileInfo = context.file; | ||
const contents = inputFileInfo.contents; | ||
const lines = contents.split("\n").map(line => line.trim()); | ||
let result = ""; | ||
let outLines = []; | ||
for (const line of lines) { | ||
@@ -25,15 +25,15 @@ const args = line.split(" "); | ||
if (command) { | ||
let commandOutLines = []; | ||
switch (command) { | ||
case HtAccessCommands.DirectoryIndex: | ||
result = this.handleDirectoryIndex(args, result); | ||
this.handleDirectoryIndex(args, commandOutLines); | ||
break; | ||
case HtAccessCommands.Redirect: | ||
result += this.handleRedirect(args[1], args[2]); | ||
commandOutLines.push(this.handleRedirect(args[1], args[2])); | ||
break; | ||
} | ||
outLines.push(...commandOutLines); | ||
} | ||
} | ||
const outputFileInfo = context.outputFile; | ||
outputFileInfo.contents += result; | ||
return outputFileInfo; | ||
context.file.contents = outLines.join("\n"); | ||
} | ||
@@ -40,0 +40,0 @@ async contentStepEnd() { |
@@ -5,4 +5,4 @@ import { HtAccessReplaceCommand } from "./HtAccessReplaceCommand.js"; | ||
constructor(host: string); | ||
protected handleDirectoryIndex(args: string[], result: string): string; | ||
protected handleDirectoryIndex(args: string[], result: string[]): void; | ||
protected handleRedirect(from: string, to: string): string; | ||
} |
@@ -8,3 +8,2 @@ import { HtAccessReplaceCommand } from "./HtAccessReplaceCommand.js"; | ||
handleDirectoryIndex(args, result) { | ||
return ""; | ||
} | ||
@@ -11,0 +10,0 @@ handleRedirect(from, to) { |
@@ -6,3 +6,3 @@ import { HtAccessReplaceCommand } from "./HtAccessReplaceCommand.js"; | ||
protected handleRedirect(from: string, to: string): string; | ||
protected handleDirectoryIndex(args: string[], result: string): string; | ||
protected handleDirectoryIndex(args: string[], result: string[]): void; | ||
} |
@@ -15,3 +15,3 @@ import { HtAccessReplaceCommand } from "./HtAccessReplaceCommand.js"; | ||
} | ||
return `${from} /${path}\n`; | ||
return `${from} /${path}`; | ||
} | ||
@@ -21,7 +21,6 @@ handleDirectoryIndex(args, result) { | ||
for (const file of files) { | ||
result += `/* ${file}\n`; | ||
result.push(`/* ${file}`); | ||
} | ||
//result += `/*/ /:splat/${args[1]}\n` | ||
return result; | ||
//result.push(`/*/ /:splat/${args[1]}`) | ||
} | ||
} |
@@ -13,7 +13,7 @@ import path from "path"; | ||
return { | ||
replace: (match, ...args) => { | ||
replace: (_match, ...args) => { | ||
let currentDir = process.cwd(); | ||
const toInclude = args[0]; | ||
if (!toInclude.startsWith("/")) { | ||
const currentFile = context.inputFile; | ||
const currentFile = context.file; | ||
if (currentFile) { | ||
@@ -20,0 +20,0 @@ const currentFileName = currentFile.name; |
@@ -11,3 +11,3 @@ import { RegexReplaceCommand } from '../../RegexReplaceCommand.js'; | ||
const timeFormat = args[0]; // TODO: Support it | ||
const fileInfo = context.inputFile; | ||
const fileInfo = context.file; | ||
return fileInfo.lastModified.toLocaleDateString(context.locale, this.options); | ||
@@ -14,0 +14,0 @@ } |
import { RegexReplacer } from "./RegexReplacer.js"; | ||
import { ReplaceCommand } from "./ReplaceCommand.js"; | ||
import { SsgFile } from "../../../util/file/SsgFile.js"; | ||
import { SsgContext } from "../../../SsgContext.js"; | ||
@@ -16,3 +15,3 @@ /** | ||
*/ | ||
execute(context: C): Promise<SsgFile>; | ||
execute(context: C): Promise<void>; | ||
/** | ||
@@ -19,0 +18,0 @@ * Create the replacer for a given context. |
@@ -14,3 +14,3 @@ /** | ||
async execute(context) { | ||
const fileInfo = context.inputFile; | ||
const fileInfo = context.file; | ||
let contents = fileInfo.contents; | ||
@@ -24,4 +24,3 @@ let result = contents; | ||
} while (result != contents); | ||
fileInfo.contents = result; | ||
return fileInfo; | ||
context.file.contents = result; | ||
} | ||
@@ -28,0 +27,0 @@ async contentStepEnd() { |
@@ -1,2 +0,1 @@ | ||
import { SsgFile } from '../../../util/index.js'; | ||
import { SsgContext } from "../../../SsgContext.js"; | ||
@@ -10,3 +9,3 @@ export interface ReplaceCommand<C extends SsgContext> { | ||
*/ | ||
execute(context: C): Promise<SsgFile>; | ||
execute(context: C): Promise<void>; | ||
/** | ||
@@ -13,0 +12,0 @@ * Called when content step is terminating. |
import { SsgStep } from "./SsgStep.js"; | ||
import { SsgContext } from "../SsgContext.js"; | ||
import { SsgConfig } from "../SsgConfig"; | ||
import { SsgFile } from "../util"; | ||
export interface DirectoryResult { | ||
@@ -41,5 +42,5 @@ directoryCount: number; | ||
*/ | ||
protected abstract processDirs(context: SsgContext, dirames: string[]): Promise<void>; | ||
protected abstract processDirs(context: SsgContext, dirNames: string[], outputFile: SsgFile): Promise<void>; | ||
protected findDirs(fromDirs: string[]): Promise<string[]>; | ||
protected findSubDirs(ofDir: string): Promise<string[]>; | ||
} |
@@ -32,8 +32,8 @@ import path from "path"; | ||
async execute(context) { | ||
context.inputFile = context.getInputFrom(this.templateFileName); | ||
context.file = context.getInputFrom(this.templateFileName); | ||
const outputFilePath = path.join(this.config.outDir, this.templateFileName); | ||
context.outputFile = context.getOutputFrom(outputFilePath); | ||
const outputFile = context.getOutputFrom(outputFilePath); | ||
const dirNames = (await this.findDirs(this.rootDirs)) | ||
.filter(dirName => !this.excludedDirs.includes(dirName)); | ||
await this.processDirs(context, dirNames); | ||
await this.processDirs(context, dirNames, outputFile); | ||
return { directoryCount: dirNames.length }; | ||
@@ -40,0 +40,0 @@ } |
import { TestRunner } from '@javarome/testscript'; | ||
let runner = new TestRunner(); | ||
let runner = new TestRunner(["**/*Test.ts"], ['node_modules/**/*.*']); | ||
runner.run().then(result => { | ||
console.log('Executed', result.suites.length, 'test suites in', runner.durationStr(result.duration)); | ||
}); |
@@ -5,3 +5,3 @@ { | ||
"author": "Jérôme Beau <javarome@gmail.com> (https://javarome.com)", | ||
"version": "1.7.7", | ||
"version": "1.8.0", | ||
"description": "Static Site Generation TypeScript API", | ||
@@ -37,3 +37,3 @@ "exports": "./dist/src/index.js", | ||
"tsx": "3.14.0", | ||
"@javarome/testscript": "^0.6.1" | ||
"@javarome/testscript": "^0.10.7" | ||
}, | ||
@@ -40,0 +40,0 @@ "keywords": [ |
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
84693
2089