Skip to content

Commit cf2f66f

Browse files
committed
Add QuickJS support
1 parent d333b7b commit cf2f66f

File tree

10 files changed

+108
-4
lines changed

10 files changed

+108
-4
lines changed

CONTRIBUTING-CODE.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Next, run npm's `install` command:
4242

4343
You're now ready to build Asciidoctor.js.
4444

45-
TIP: Opal.js, the Ruby runtime in JavaScript is available in `packages/core/node_modules/asciidoctor-opal-runtime/src/opal.js`
45+
TIP: Opal.js, the Ruby runtime in JavaScript is available in `packages/core/node_modules/@asciidoctor/opal-runtime/src/opal.js`
4646

4747
== Building
4848

docs/modules/setup/pages/runtime.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
:uri-spidermonkey-read: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Introduction_to_the_JavaScript_shell#Built-in_functions
44
:uri-phantomjs-read: http://phantomjs.org/api/fs/method/read.html
55
:uri-node-fs: https://nodejs.org/api/fs.html
6+
:uri-quickjs-read: https://bellard.org/quickjs/
67

78
:uri-v8: https://developers.google.com/v8
89
:uri-graalvm: https://www.graalvm.org
@@ -89,6 +90,9 @@ The implementation will use the {uri-spidermonkey-read}[`read` function].
8990
`phantomjs`::
9091
The implementation will use the {uri-phantomjs-read}[`fs.read` function].
9192

93+
`quickjs`::
94+
The implementation will use the {uri-quickjs-read}[`std.loadFile` module].
95+
9296
== Retrieve the runtime environment
9397

9498
Once Asciidoctor.js is instantiated, you can retrieve the runtime environment with the `getRuntime` function:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# TODO: add QuickJS-specific class override here
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
%x(
2+
var platform, engine, framework, ioModule;
3+
4+
if (typeof moduleConfig === 'object' && typeof moduleConfig.runtime === 'object') {
5+
var runtime = moduleConfig.runtime;
6+
platform = runtime.platform;
7+
engine = runtime.engine;
8+
framework = runtime.framework;
9+
ioModule = runtime.ioModule;
10+
}
11+
ioModule = ioModule || 'quickjs';
12+
platform = platform || 'quickjs';
13+
engine = engine || '';
14+
framework = framework || '')
15+
16+
JAVASCRIPT_IO_MODULE = %x(ioModule)
17+
JAVASCRIPT_PLATFORM = %x(platform)
18+
JAVASCRIPT_ENGINE = %x(engine)
19+
JAVASCRIPT_FRAMEWORK = %x(framework)
20+
21+
require 'asciidoctor/js/opal_ext/quickjs/file'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class File
2+
3+
def self.read(path)
4+
%x{
5+
const body = std.loadFile(path);
6+
if (body === null) {
7+
console.log(`unable to loadFile:"${path}" from:"${os.getcwd()[0]}" realpath:"${os.realpath(path)[0]}"`);
8+
}
9+
return body || '';
10+
}
11+
end
12+
13+
end

packages/core/lib/asciidoctor/js/opal_ext/umd.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
var isNode = typeof process === 'object' && typeof process.versions === 'object' && process.browser != true,
33
isElectron = typeof navigator === 'object' && typeof navigator.userAgent === 'string' && typeof navigator.userAgent.indexOf('Electron') !== -1,
44
isBrowser = typeof window === 'object',
5+
isQuickjs = typeof std === 'object',
56
isGraalVM = typeof Polyglot === 'object' && Polyglot.import,
67
isPhantomJS = typeof window === 'object' && typeof window.phantom === 'object',
78
isWebWorker = typeof importScripts === 'function',
@@ -36,6 +37,10 @@
3637
platform = platform || 'standalone';
3738
framework = framework || 'spidermonkey';
3839
}
40+
else if (isQuickjs) {
41+
platform = platform || 'browser';
42+
framework = framework || 'quickjs';
43+
}
3944
else if (isBrowser) {
4045
platform = platform || 'browser';
4146
if (isPhantomJS) {
@@ -65,15 +70,18 @@
6570
if (ioModule !== 'spidermonkey'
6671
&& ioModule !== 'phantomjs'
6772
&& ioModule !== 'node'
73+
&& ioModule !== 'quickjs'
6874
&& ioModule !== 'graalvm'
6975
&& ioModule !== 'xmlhttprequest') {
70-
throw new Error('Invalid IO module, `config.ioModule` must be one of: spidermonkey, phantomjs, node, graalvm or xmlhttprequest');
76+
throw new Error('Invalid IO module, `config.ioModule` must be one of: spidermonkey, quickjs, phantomjs, node, graalvm or xmlhttprequest');
7177
}
7278
} else {
7379
if (framework === 'spidermonkey') {
7480
ioModule = 'spidermonkey';
7581
} else if (framework === 'phantomjs') {
7682
ioModule = 'phantomjs';
83+
} else if (framework === 'quickjs') {
84+
ioModule = 'quickjs';
7785
} else if (platform === 'node') {
7886
ioModule = 'node';
7987
} else if (engine === 'graalvm') {
@@ -107,6 +115,9 @@
107115
if JAVASCRIPT_IO_MODULE == 'spidermonkey'
108116
require 'asciidoctor/js/opal_ext/spidermonkey/file'
109117
end
118+
if JAVASCRIPT_IO_MODULE == 'quickjs'
119+
require 'asciidoctor/js/opal_ext/quickjs/file'
120+
end
110121
if JAVASCRIPT_IO_MODULE == 'xmlhttprequest'
111122
require 'asciidoctor/js/opal_ext/browser/file'
112123
end

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"test:node": "mocha spec/*/*.spec.cjs && npm run test:node:esm",
3737
"test:node:esm": "mocha --experimental-json-modules spec/node/asciidoctor.spec.js",
3838
"test:browser": "node spec/browser/run.cjs",
39+
"test:quickjs": "qjs --unhandled-rejection spec/quickjs/run.mjs",
3940
"test:types": "rm -f types/tests.js && eslint types --ext .ts && tsc --build types/tsconfig.json && node --input-type=commonjs types/tests.js",
4041
"test": "node tasks/test/unsupported-features.cjs && npm run test:node && npm run test:browser && npm run test:types",
4142
"build": "node tasks/build.cjs && npm run test && npm run lint",

packages/core/spec/quickjs/run.mjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* global Asciidoctor */
2+
import Asciidoctor from '../../build/asciidoctor-quickjs.js'
3+
const asciidoctor = Asciidoctor()
4+
5+
const data = '= asciidoctor.js, AsciiDoc in JavaScript\n' +
6+
'Doc Writer <[email protected]>\n\n' +
7+
'Asciidoctor and Opal come together to bring\n' +
8+
'http://asciidoc.org[AsciiDoc] to the browser!.\n\n' +
9+
'== Technologies\n\n' +
10+
'* AsciiDoc\n' +
11+
'* Asciidoctor\n' +
12+
'* Opal\n\n' +
13+
'NOTE: That\'s all she wrote!!!\n\n' +
14+
'include::spec/fixtures/include.adoc[]'
15+
16+
const options = { safe: 0, header_footer: true, attributes: { stylesheet: "spec/fixtures/css/simple.css", showtitle: true } }
17+
const html = asciidoctor.convert(data, options)
18+
console.log(html)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* global Asciidoctor, ASCIIDOCTOR_JS_VERSION */
2+
import * as std from 'std';
3+
import * as os from 'os';
4+
5+
//{{opalCode}}
6+
7+
const __path__ = {
8+
separator: os.platform == "win32" ? '\\' : '/',
9+
split(path) { return path.split(this.separator); },
10+
join(compo) { return compo.join(this.separator); },
11+
basename(path) { return this.join(this.split(path).slice(0,-1)); },
12+
dirname(path) { return this.split(path).pop(); },
13+
};
14+
const __asciidoctorDistDir__ = os.realpath(scriptArgs[0])[0].match(os.platform == "win32" ? /.*\\/ : /.*\//);
15+
16+
export default function (moduleConfig) {
17+
//{{asciidoctorCode}}
18+
19+
//{{asciidoctorAPI}}
20+
21+
//{{asciidoctorVersion}}
22+
23+
/**
24+
* Get Asciidoctor.js version number.
25+
*
26+
* @memberof Asciidoctor
27+
* @returns {string} - returns the version number of Asciidoctor.js.
28+
*/
29+
Asciidoctor.prototype.getVersion = function () {
30+
return ASCIIDOCTOR_JS_VERSION
31+
}
32+
return Opal.Asciidoctor
33+
}

packages/core/tasks/module/builder.cjs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ const generateFlavors = async (asciidoctorCoreTarget, environments) => {
135135
const opalExtData = fs.readFileSync(`build/opal-ext-${environment}.js`, 'utf8')
136136
const asciidoctorCoreData = fs.readFileSync(asciidoctorCoreTarget, 'utf8')
137137
let data
138-
if (['node', 'browser'].includes(environment)) {
138+
if (['node', 'browser', 'quickjs'].includes(environment)) {
139139
const asciidoctorExtData = fs.readFileSync(`build/asciidoctor-ext-${environment}.js`, 'utf8')
140140
data = opalExtData.concat('\n').concat(asciidoctorExtData).concat('\n').concat(asciidoctorCoreData)
141141
} else {
@@ -150,6 +150,8 @@ const generateFlavors = async (asciidoctorCoreTarget, environments) => {
150150
const target = `build/asciidoctor-${environment}.js`
151151
if (environment === 'node') {
152152
templateFile = 'src/template-asciidoctor-node.js'
153+
} else if (environment === 'quickjs') {
154+
templateFile = 'src/template-asciidoctor-quickjs.js'
153155
} else {
154156
templateFile = 'src/template-asciidoctor-browser.js'
155157
}
@@ -216,7 +218,7 @@ module.exports = class Builder {
216218
this.benchmarkBuildDir = path.join('build', 'benchmark')
217219
this.examplesBuildDir = path.join('build', 'examples')
218220
this.asciidocRepoBaseURI = 'https://raw.githubusercontent.com/asciidoc/asciidoc/d43faae38c4a8bf366dcba545971da99f2b2d625'
219-
this.environments = ['node', 'graalvm', 'browser']
221+
this.environments = ['node', 'graalvm', 'browser', 'quickjs']
220222
this.asciidoctorCoreTarget = path.join('build', 'asciidoctor-core.js')
221223
}
222224

0 commit comments

Comments
 (0)