Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Initial Node/DOM compatibility
Browse files Browse the repository at this point in the history
1. Introduces an abstract subset of DOM APIs corresponding to previous usage of semantically equivalent `libxmljs` APIs. It would have been nicer to import these types and export the subset we care about, but this is inconsistent with how TypeScript `lib` works (it always augments the global scope).

2. Provides a Node implementation of those DOM APIs by extending `libxmljs` prototypes. This kind of extension isn't ideal, but it's the most reasonable way to achieve such a compatibility layer without sacrificing performance. An ealirer alternative approach used `WeakMap`s to cross reference the DOM/`libxmljs` interfaces, but this had a significant impact on perf. This implementation is type checked by default.

3. Provides a web implementation by... just exporting the relevant globals. This implementation is type checked by `tsc` using the `tsconfig.web.json` project file. This ensures that the abstract DOM interfaces are actully consistent with the built in DOM `lib` types.

4. Refactors transformer.ts to use the abstract DOM APIs. This uses the Node DOM compatibility implementation by default, and the native web DOM implementation when the environment variable `ENV` is set to "web".

5. Also when `ENV` is web, tests and benchmarks call `transform` in the specified `BROWSER` environment variable (defaulting to "fiefox") via a simple `playwright` bridge. In CI, all tests and benchmarks are run in: Node 14, Node 16, Firefox, Chromium, Webkit.

6. Build is updated to produce both Node and web targets. The build config itself is fairly complex, but it's been consolidated in `vite.config.ts`. This also includes a corresponding change to build `app.ts` rather than the previous, much more complex `app.js` using a Vite dev server (and roughly restores its implementation to what it had been prior to the initial TypeScript migration).

7. There are several known issues at the point of this commit. These either correspond to XSLT extensions not supported by browser targets, or to differences in behavior between DOM/`libxmljs`, all of which will be addressed in separate commits discussing each in greater detail.
  • Loading branch information
eyelidlessness committed Feb 19, 2023
1 parent e02efa9 commit 6242fbe
Show file tree
Hide file tree
Showing 47 changed files with 1,646 additions and 714 deletions.
14 changes: 12 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
{
"devDependencies": [
"app.js",
"app.ts",
"vite.config.ts",
"src/api.ts",
"src/app.ts",
"test/**/*.ts"
],
"optionalDependencies": false,
Expand Down Expand Up @@ -95,10 +95,19 @@
{
"files": ["./**/*.ts"],
"rules": {
"consistent-return": "off",
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": "error",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"no-dupe-class-members": "off",
"@typescript-eslint/no-dupe-class-members": "error",
"no-empty-function": "off",
"@typescript-eslint/no-empty-function": "error",
"no-undef": "off",
Expand Down Expand Up @@ -129,6 +138,7 @@
{
"files": ["./**/*.d.ts"],
"rules": {
"lines-between-class-members": "off",
"no-unused-vars": "off"
}
},
Expand Down
23 changes: 19 additions & 4 deletions .github/workflows/npmjs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,26 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
target: ['node']
node: ['14', '16']
include:
- target: web
node: 16
browser: firefox
- target: web
node: 16
browser: chromium
- target: web
node: 16
browser: webkit
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache
with:
path: node_modules
path: |
node_modules
~/.cache/ms-playwright
key: ${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}
- uses: actions/setup-node@v2
with:
Expand All @@ -27,9 +40,11 @@ jobs:
- run: npm install -g npm@^6
- if: steps.cache.outputs.cache-hit != 'true'
run: npm ci
- run: npm test
- run: npm run benchmarks
- if: github.event_name == 'release' && github.event.action == 'published' && matrix.node == '16'
- if: matrix.node == '16' && matrix.browser == 'webkit'
run: sudo npx playwright install-deps
- run: ENV=${{ matrix.target }} BROWSER=${{ matrix.browser }} npm test
- run: ENV=${{ matrix.target }} BROWSER=${{ matrix.browser }} npm run benchmarks
- if: github.event_name == 'release' && github.event.action == 'published' && matrix.node == '16' && matrix.target == 'node'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},

// Note: it would be nice to reverse this! But it's currently preventing a *ton* of whitespace diff noise
"[xml]": {
"editor.formatOnSave": false
Expand All @@ -32,5 +31,6 @@
},

// Code navigation
"javascript.referencesCodeLens.enabled": true
"javascript.referencesCodeLens.enabled": true,
"typescript.tsdk": "node_modules/typescript/lib"
}
64 changes: 1 addition & 63 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,63 +1 @@
// @ts-check

import { createServer } from 'vite';
import { VitePluginNode } from 'vite-plugin-node';
import {
config,
external,
resolvePath,
rootDir,
} from './config/build.shared.js';

const appPath = resolvePath('./app.ts');

const init = async () => {
/** @type {import('vite').UserConfig} */
const baseOptions = {
mode: 'development',
build: {
rollupOptions: {
external,
},
},
optimizeDeps: {
disabled: true,
},
root: rootDir,
ssr: {
target: 'node',
},
};

const servers = await Promise.all([
createServer({
...baseOptions,
configFile: false,
plugins: VitePluginNode({
adapter: 'express',
appPath,
exportName: 'app',
tsCompiler: 'esbuild',
}),
server: {
port: config.port,
},
}),
createServer({
...baseOptions,
configFile: false,
publicDir: resolvePath('./test/forms'),
server: {
port: 8081,
},
}),
]);

await Promise.all(servers.map((server) => server.listen()));

servers.forEach((server) => {
server.printUrls();
});
};

init();
import './dist/enketo-transformer/app.cjs';
7 changes: 0 additions & 7 deletions config/build.shared.d.ts

This file was deleted.

42 changes: 0 additions & 42 deletions config/build.shared.js

This file was deleted.

18 changes: 18 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="./icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Enketo Transformer (web)</title>
</head>
<body>
<script type="module">
import { transform } from './src/transformer.ts';

globalThis.enketo = {
transformer: { transform },
};
</script>
</body>
</html>
Loading

0 comments on commit 6242fbe

Please sign in to comment.