Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@edemaine/shtml2html

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@edemaine/shtml2html - npm Package Compare versions

Comparing version 0.0.0 to 0.1.0

11

package.json
{
"name": "@edemaine/shtml2html",
"version": "0.0.0",
"version": "0.1.0",
"description": "Convert Apache server-side rendered HTML to static HTML",
"type": "module",
"main": "shtml2html.js",

@@ -9,3 +10,6 @@ "bin": {

},
"files": ["shtml2html.civet", "tsconfig.json"],
"files": [
"shtml2html.civet",
"tsconfig.json"
],
"scripts": {

@@ -22,4 +26,5 @@ "prepare": "civet -c shtml2html.civet --js -o .js",

"@danielx/civet": "^0.6.6",
"@types/node": "^20.2.5"
"@types/node": "^20.2.5",
"@types/strftime": "^0.9.4"
}
}

@@ -21,3 +21,3 @@ # shtml2html

## Supported Features
## Supported Directives

@@ -28,6 +28,14 @@ * `<!--#include file="path"-->` includes a non-relative path

TODO: way to specify document root.
* `<!--#include virtual="path1" virtual="path2"-->` for multiple inclusions
* `<!--#flastmod file="path"-->`:
modified date of non-relative path (via `timefmt`)
* `<!--#flastmod virtual="path"-->`:
modified date of relative path (via `timefmt`)
* `<!--#fsize file="path"-->`: size of non-relative path (via `sizefmt`)
* `<!--#fsize virtual="path"-->`: size of relative path (via `sizefmt`)
* `<!--#config key="value"-->` where `key` is among:
* `echomsg`: message for unsupported `#echo`
* `errormsg` (not currently used)
* `sizefmt` (not currently used)
* `errormsg`: error to include in the file when a directive fails
(a more descriptive error message should also be printed to console)
* `sizefmt`: format for `#fsize`, either "bytes" (default) or "abbrev"
* `timefmt`: strftime format for `LAST_MODIFIED`

@@ -37,1 +45,2 @@ * `<!--#echo var="value"-->` where `value` is among:

* `LAST_MODIFIED`: modified date of `.shtml` input (via `timefmt`)
* `<!--#comment ...-->` gets removed
#!/usr/bin/env node
import fs from "fs"
import path from "path"
import strftime from "strftime"
import url from "url"
const fs = require('fs')
const path = require('path')
const strftime = require('strftime')
class Convert {

@@ -17,3 +17,2 @@ // Maintains state of converter, including configuration and variables.

this.rootFilename = rootFilename1;
const stat = fs.statSync(this.rootFilename)
this.config = {

@@ -27,39 +26,132 @@ echomsg: '(none)',

DOCUMENT_NAME: outFilename,
LAST_MODIFIED: () => {
return strftime(this.config.timefmt, stat.mtime)
},
LAST_MODIFIED: () => this.flastmod(this.rootFilename),
}
}
convertToString(filename = this.rootFilename) {
let html = fs.readFileSync(filename, {encoding: 'utf8'})
while(true) {
const old = html
html = html
.replace(/<!--#include\s+(file|virtual)\s*=\s*"([^"]+)"\s*-->/g,
(match, type, url) => {
if (type == 'file' && (url.includes('../') || path.isAbsolute(url))) {
console.log(`* Invalid #include file: ${url}`)
return this.config.errormsg
flastmod(filename) {
try {
return strftime(this.config.timefmt, fs.statSync(filename).mtime)
}
catch (error) {
console.log(`!! flastmod error: ${error}`)
return this.config.errormsg
}
}
fsize(filename) {
try {
const size = fs.statSync(filename).size
switch(this.config.sizefmt) {
case 'bytes': {
return `${size}`
}
case 'abbrev': {
if (size < 973) {
return `${size}`
}
else if (size < 973 * 1024) {
return `${(size / 1024).toFixed(1)}K`
}
else {
return this.convertToString(path.join(path.dirname(filename), url))
return `${(size / (1024 * 1024)).toFixed(1)}M`
}
},)
.replace(/<!--#config\s+(\w+)="([^"]+)"\s*-->/g,
}
default: {
console.log(`!! Invalid sizefmt: ${this.config.sizefmt}`)
return this.config.errormsg
}
}
}
catch (error) {
console.log(`!! fsize error: ${error}`)
return this.config.errormsg
}
}
convertToString(filename = this.rootFilename) {
return fs.readFileSync(filename, {encoding: 'utf8'})
.replace(/<!--\#(include|flastmod|fsize|config|echo)\b(.*?)-->/g, (match, command, rest) => {
// #comment can have arbitrary content
if (command == 'comment') { return '' };
// Parse arguments
const args = []
rest = rest.replace(/\s*([\w\-]+)\s*=\s*"([^"]*)"\s*/g,
(match, key, value) => {
this.config[key] = value
args.push([key, value])
return ''
},)
.replace(/<!--#echo\s+var="([^"]+)"\s*-->/g,
(match, key) => {
let val = this.vars[key] ?? this.config.echomsg
if (val instanceof Function) { val = val() }
return val
},)
if (old == html) { break }
}
return html
if (rest) {
console.log(`!! Invalid #${command} directive: ${rest}`)
return this.config.errormsg
}
function getArg(desired) {
for (const [key, value] of args) {
if (key == desired) { return value }
}
return undefined
}
const fileCommand = (func, multi) => {
let done = false;
return (()=>{const results=[];for (const [key, value] of args) {
if (done && !multi) { break }
switch(key) {
case 'file': {
if (value.includes('../') || path.isAbsolute(value)) {
console.log(`!! Invalid file argument: ${value}`)
results.push(this.config.errormsg)
}
else {
done = true
results.push(func(path.join(path.dirname(filename), value)))
};break;
}
case 'virtual': {
done = true
results.push(func(path.join(path.dirname(filename), value)));break;
}
default: {
continue
}
}
}; return results})().join('')
}
switch(command) {
// CIVET: shouldn't need parens below
case 'include': {
return fileCommand(this.convertToString.bind(this), true)
}
case 'flastmod': {
return fileCommand(this.flastmod.bind(this))
}
case 'fsize': {
return fileCommand(this.fsize.bind(this))
}
case 'config': {
for (const [key, value] of args) {
this.config[key] = value
}
return ''
}
case 'echo': {
const varName = getArg('var')
if (varName != null) {
let val = this.vars[varName] ?? this.config.echomsg
if (val instanceof Function) { val = val() }
return val
}
else {
console.log(`!! #echo directive missing var: ${rest}`)
return this.config.errormsg
}
}
default: {
return this.config.errormsg
}
}
})
}
}
} // should never happen; to satisfy TypeScript

@@ -76,7 +168,9 @@ function convertFile(filename, outFilename) {

function main() {
const results=[];for (const arg of process.argv.slice(2)) {
results.push(convertFile(arg))
};return results;
const results1=[];for (const arg of process.argv.slice(2)) {
results1.push(convertFile(arg))
};return results1;
}
if (require.main == module) { main() }
if (import.meta.url.startsWith('file:') &&
fs.realpathSync(process.argv[1]) ==
fs.realpathSync(url.fileURLToPath(import.meta.url))) { main() }
{
"compilerOptions": {
"module": "nodenext",
"strict": true,
"noImplicitAny": true,
"jsx": "preserve",
"lib": ["es2021", "node"],
"lib": ["es2021"],
"forceConsistentCasingInFileNames": true,

@@ -7,0 +9,0 @@ "resolveJsonModule": true,

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