Skip to content

Commit

Permalink
fix hulk script
Browse files Browse the repository at this point in the history
  • Loading branch information
rtfpessoa committed Apr 5, 2024
1 parent ba90bbd commit c7248f0
Show file tree
Hide file tree
Showing 4 changed files with 4,002 additions and 3,963 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"build:esm": "rm -rf lib-esm; tsc -p tsconfig.json -m ESNext --outDir lib-esm",
"build:bundles": "rm -rf ./bundles/js; webpack --mode production --config webpack.bundles.ts",
"build:css": "rm -rf ./bundles/css; postcss --config ./postcss.config.js --no-map -o ./bundles/css/diff2html.min.css ./src/ui/css/diff2html.css",
"build:templates": "ts-node ./scripts/hulk.ts --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts",
"build:templates": "node ./scripts/hulk.mjs --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts",
"build:website": "rm -rf docs; webpack --mode production --config webpack.website.ts",
"gen": "yarn run gen:toc",
"gen:toc-base": "markdown-toc --maxdepth 3 --bullets='-' -i",
Expand Down Expand Up @@ -160,5 +160,5 @@
"lib",
"lib-esm"
],
"packageManager": "yarn@3.6.3"
"packageManager": "yarn@4.1.1"
}
227 changes: 227 additions & 0 deletions scripts/hulk.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
* Copyright 2011 Twitter, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as path from "path"
import * as fs from "fs"

import hogan from "hogan.js"
import nopt from "nopt"
import * as mkderp from "mkdirp"

const options = nopt(
{
namespace: String,
outputdir: path,
variable: String,
wrapper: String,
version: true,
help: true
},
{
n: ["--namespace"],
o: ["--outputdir"],
vn: ["--variable"],
w: ["--wrapper"],
h: ["--help"],
v: ["--version"]
}
)

const specials = [
"/",
".",
"*",
"+",
"?",
"|",
"(",
")",
"[",
"]",
"{",
"}",
"\\"
]
const specialsRegExp = new RegExp("(\\" + specials.join("|\\") + ")", "g")
function escape(text) {
return text.replace(specialsRegExp, "\\$1")
}

function cyan(text) {
return "\x1B[36m" + text + "\x1B[39m"
}

function extractFiles(files) {
const usage = `${cyan(
"USAGE:"
)} hulk [--wrapper wrapper] [--outputdir outputdir] [--namespace namespace] [--variable variable] FILES
${cyan("OPTIONS:")} [-w, --wrapper] :: wraps the template (i.e. amd)
[-o, --outputdir] :: outputs the templates as individual files to a directory
[-n, --namespace] :: prepend string to template names
[-vn, --variable] :: variable name for non-amd wrapper
${cyan("EXAMPLE:")} hulk --wrapper amd ./templates/*.mustache
${cyan(
"NOTE:"
)} hulk supports the "*" wildcard and allows you to target specific extensions too
`

if (options.version) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
console.log(require("../package.json").version)
process.exit(0)
}

if (!files.length || options.help) {
console.log(usage)
process.exit(0)
}

return files
.map(fileGlob => {
if (/\*/.test(fileGlob)) {
const [fileGlobPrefix, fileGlobSuffix] = fileGlob.split("*")

return fs
.readdirSync(fileGlobPrefix || ".")
.reduce((previousFiles, relativeFilePath) => {
const file = path.join(fileGlobPrefix, relativeFilePath)
if (
new RegExp(`${escape(fileGlobSuffix)}$`).test(relativeFilePath) &&
fs.statSync(file).isFile()
) {
previousFiles.push(file)
}
return previousFiles
}, [])
} else if (fs.statSync(fileGlob).isFile()) {
return [fileGlob]
} else {
return []
}
})
.reduce((previous, current) => previous.concat(current), [])
}

// Remove utf-8 byte order mark, http://en.wikipedia.org/wiki/Byte_order_mark
function removeByteOrderMark(text) {
if (text.charCodeAt(0) === 0xfeff) {
return text.substring(1)
}
return text
}

// Wrap templates
function wrap(file, name, openedFile) {
const hoganTemplateString = `new Hogan.Template(${hogan.compile(openedFile, {
asString: true
})})`

const objectName = options.variable || "templates"
const objectAccessor = `${objectName}["${name}"]`
const objectStmt = `${objectAccessor} = ${hoganTemplateString};`

switch (options.wrapper) {
case "amd":
return `define(${
!options.outputdir ? `"${path.join(path.dirname(file), name)}", ` : ""
}["hogan.js"], function(Hogan) { return ${hoganTemplateString}; });`

case "node":
// If we have a template per file the export will expose the template directly
return options.outputdir
? `global.${objectStmt};\nmodule.exports = ${objectAccessor};`
: `global.${objectStmt}`

case "ts":
return `// @ts-ignore\n${objectStmt}`
default:
return objectStmt
}
}

function prepareOutput(content) {
const variableName = options.variable || "templates"
switch (options.wrapper) {
case "amd":
return content
case "node":
return `(function() {
if (!!!global.${variableName}) global.${variableName} = {};
var Hogan = require("hogan.js");
${content}
${!options.outputdir ? `module.exports = global.${variableName};\n` : ""})();`

case "ts":
return `import * as Hogan from "hogan.js";
type CompiledTemplates = { [name: string]: Hogan.Template };
export const ${variableName}: CompiledTemplates = {};
${content}`

default:
return (
"if (!!!" +
variableName +
") var " +
variableName +
" = {};\n" +
content
)
}
}

// Write the directory
if (options.outputdir) {
mkderp.sync(options.outputdir)
}

// Prepend namespace to template name
function namespace(name) {
return (options.namespace || "") + name
}

// Write a template foreach file that matches template extension
const templates = extractFiles(options.argv.remain)
.map(file => {
const timmedFileContents = fs.readFileSync(file, "utf8").trim()

if (!timmedFileContents) return

const name = namespace(path.basename(file).replace(/\..*$/, ""))
const cleanFileContents = wrap(
file,
name,
removeByteOrderMark(timmedFileContents)
)

if (!options.outputdir) return cleanFileContents

const fileExtension = options.wrapper === "ts" ? "ts" : "js"

return fs.writeFileSync(
path.join(options.outputdir, `${name}.${fileExtension}`),
prepareOutput(cleanFileContents)
)
})
.filter(templateContents => typeof templateContents !== "undefined")

// Output templates
if (!templates.length || options.outputdir) process.exit(0)

console.log(prepareOutput(templates.join("\n")))
Loading

0 comments on commit c7248f0

Please sign in to comment.