Skip to content

Commit

Permalink
feat: add html transform
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed Apr 10, 2024
1 parent 08ba5ed commit 358042a
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 52 deletions.
57 changes: 52 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,61 @@ The WBC file is a specially designed binary file that contains pre-compiled Java
npm install @openwebf/wbc --save
```

## Usage
## Cli Usage

**Install**
```
npm install @openwebf/wbc -g
```

**Convert JavaScript Into WBC file**

```
wbc -s /tmp/index.js -d /tmp
```

**Transform Inline Scripts in HTML**

```
wbc -s ./demo.html -d ./demo_wbc.html --convert-html
```

## Node Usage

**Convert JavaScript Into WBC buffer**

```javascript
const { compileJavaScriptToWbc } = require('@openwebf/wbc');

compileJavaScriptToWbc('function hello() { return 1 + 1};'); // <Buffer ...> the WBC bytes
```

**Transform Inline JavaScript Codes into WBC**

```javascript
const WBC = require('@openwebf/wbc');
const wbc = new WBC();
const { transformInlineScriptToWbc } = require('@openwebf/wbc');

const transformedHtml = transformInlineScriptToWbc(`
<!DOCTYPE html>
<html lang="en">
<body>
<script>
console.log('helloworld');
</script>
</body>
</html>
`);

console.log(transformedHtml); /*
<html lang="en">
<body>
<script>
// The WBC binary contents
</script>
</body></html>
*/

// Dump bytecode from javascript source;
wbc.compile('function hello() { return 1 + 1};'); // <Buffer ...>
```

## Contribute
Expand Down
36 changes: 18 additions & 18 deletions bin/wbc.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#!/usr/bin/env node
const Wbc = require('./wbc_lib').Wbc;
const path = require('path');
const fs = require('fs');
const { program } = require('commander');
const packageConfig = require('../package.json');
const Qjsc = require('../index');
const { compileJavaScriptToWbc, transformInlineScriptToWbc, legacyCompileJavaScriptToKBC } = require('../index');

program
.version(packageConfig.version)
.description('The WBC file generator')
.requiredOption('-s, --source <source>', 'the Javascript source file path')
.requiredOption('-d, --dist <dist>', 'the generated bytecode file path')
.option('--legacy_kbc1', 'generate legacy kbc1 file, (compact with openkraken project)')
.option('--convert-html', 'Given an HTML string as input, convert all inline JavaScript code to WBC format.')
.parse(process.argv);

let options = program.opts();
Expand All @@ -30,21 +30,21 @@ if (!path.isAbsolute(dist)) {
dist = path.join(process.cwd(), dist);
}

const qjsc = new Qjsc();

const sourceFileName = source.split('/').slice(-1)[0].split('.')[0];
const sourceCode = fs.readFileSync(source, {encoding: 'utf-8'});

let buffer = qjsc.compile(sourceCode);

if (type == 'kbc1') {
let distPath = path.join(dist, sourceFileName + '.kbc1');
fs.writeFileSync(distPath, buffer);
console.log('Quickjs bytecode generated kbc1 at: \n' + distPath);
} else if (type == 'wbc') {
const wbc = new Wbc();
let wbcBytecode = wbc.generateWbcBytecode(buffer);
let distPath = path.join(dist, sourceFileName + '.wbc1');
fs.writeFileSync(distPath, wbcBytecode);
console.log('Quickjs bytecode generated wbc1 at: \n' + distPath);
const sourceCode = fs.readFileSync(source, { encoding: 'utf-8' });

if (options.convertHtml) {
const output = transformInlineScriptToWbc(sourceCode);
fs.writeFileSync(dist, output);
console.log('Quickjs bytecode generated wbc1 at: \n' + dist);
} else {
if (type == 'kbc1') {
let distPath = path.join(dist, sourceFileName + '.kbc1');
fs.writeFileSync(distPath, legacyCompileJavaScriptToKBC(sourceCode));
console.log('Quickjs bytecode generated kbc1 at: \n' + distPath);
} else if (type == 'wbc') {
let distPath = path.join(dist, sourceFileName + '.wbc1');
fs.writeFileSync(distPath, compileJavaScriptToWbc(sourceCode));
console.log('Quickjs bytecode generated wbc1 at: \n' + distPath);
}
}
8 changes: 8 additions & 0 deletions demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<body>
<script>
console.log('helloworld');
</script>
</body>
</html>
25 changes: 25 additions & 0 deletions html_converter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const Qjsc = require('./qjsc');
const { Wbc } = require('./wbc');

function parseAndConvertHTML(html, version = '1') {
let dom = new JSDOM(html);
const scripts = dom.window.document.querySelectorAll('script');

[].slice.call(scripts).forEach(script => {
const textContent = script.textContent;
if (textContent.length == 0) return;
const qjsc = new Qjsc();
const wbc = new Wbc();
const buffer = qjsc.compile(textContent);
let wbcBytecode = wbc.generateWbcBytecode(buffer);
let code = wbcBytecode.toString('binary');
script.textContent = code;
})

return dom.window.document.documentElement.outerHTML;
}


module.exports = parseAndConvertHTML;
47 changes: 19 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
const supportedVersions = ['1'];
const { Wbc } = require('./wbc');
const Qjsc = require('./qjsc');
const parseAndConvertHTML = require('./html_converter');

class Qjsc {
constructor(options = {}) {
let version = options.version || '1';
if (supportedVersions.indexOf(version) === -1) {
throw new Error('Unsupported WBC version: ' + version);
}
this._bindings = require('node-gyp-build')(__dirname);
}
help() {
console.log('Supported WBC versions: ' + supportedVersions.join(', '));
}

getSupportedVersions() {
return supportedVersions;
}

compile(code, options = {}) {
let sourceURL = options.sourceURL || 'internal://';
return this._bindings.dumpByteCode(code, sourceURL);
}
function compileJavaScriptToWbc(code, version = '1') {
const qjsc = new Qjsc({version: version});
const wbc = new Wbc();
const quickjsBuffer = qjsc.compile(code);
let wbcBytecode = wbc.generateWbcBytecode(quickjsBuffer);
return wbcBytecode;
}

get version() {
return this._bindings.version;
}
function legacyCompileJavaScriptToKBC(code) {
const qjsc = new Qjsc();
return qjsc.compile(code);
}

_evalByteCode(buffer) {
return this._bindings.evalByteCode(buffer);
}
function transformInlineScriptToWbc(html, version = '1') {
return parseAndConvertHTML(html, version);
}

module.exports = Qjsc;
exports.compileJavaScriptToWbc = compileJavaScriptToWbc;
exports.transformInlineScriptToWbc = transformInlineScriptToWbc;
exports.legacyCompileJavaScriptToKBC = legacyCompileJavaScriptToKBC;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"bindings": "^1.5.0",
"commander": "^8.2.0",
"crc32": "^0.2.2",
"jsdom": "^24.0.0",
"lz4": "^0.6.5",
"nan": "^2.15.0",
"node-addon-api": "^4.1.0",
Expand Down
33 changes: 33 additions & 0 deletions qjsc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const supportedVersions = ['1'];

class Qjsc {
constructor(options = {}) {
let version = options.version || '1';
if (supportedVersions.indexOf(version) === -1) {
throw new Error('Unsupported WBC version: ' + version);
}
this._bindings = require('node-gyp-build')(__dirname);
}
help() {
console.log('Supported WBC versions: ' + supportedVersions.join(', '));
}

getSupportedVersions() {
return supportedVersions;
}

compile(code, options = {}) {
let sourceURL = options.sourceURL || 'internal://';
return this._bindings.dumpByteCode(code, sourceURL);
}

get version() {
return this._bindings.version;
}

_evalByteCode(buffer) {
return this._bindings.evalByteCode(buffer);
}
}

module.exports = Qjsc;
2 changes: 1 addition & 1 deletion bin/wbc_lib.js → wbc.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const HEADER_FIELDS = [

class Wbc {
constructor(options = {}) {
const rootDir = path.resolve(__dirname, '..');
const rootDir = path.resolve(__dirname, '.');
this._bindings = require('node-gyp-build')(rootDir);
}

Expand Down

0 comments on commit 358042a

Please sign in to comment.