diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df2a81b..81e68a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,12 +32,15 @@ jobs: debug-${{ runner.os }}- - name: Run tests run: cargo test --verbose + - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - - run: wasm-pack build --target nodejs + - name: Install wasm-opt + run: cargo install wasm-opt - uses: actions/setup-node@v3 with: node-version: 16 cache: 'npm' - - run: npm ci + - run: ./build.sh + - run: npm test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b04b8d0..d95286e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh # remove scope or update it once we decide exactly where we want to deploy this thing - - run: wasm-pack build --target nodejs + - run: npm run build - uses: actions/setup-node@v3 with: node-version: 20 diff --git a/.gitignore b/.gitignore index 50b6338..3274f69 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +pkg/ /target -/node_modules \ No newline at end of file +/node_modules diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c80c587..e7c6dcc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ Tests: Build wasm package: -`wasm-pack build --target=nodejs` +`npm run build` which will output your wasm package in `./pkg` @@ -36,4 +36,4 @@ and replace: ``` $1 = { path = "../swc/crates/$1" -``` \ No newline at end of file +``` diff --git a/Cargo.lock b/Cargo.lock index ca00b40..ff2534d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -276,7 +276,7 @@ dependencies = [ [[package]] name = "content-tag" -version = "1.1.1" +version = "1.1.2" dependencies = [ "base64 0.21.4", "difference", diff --git a/Cargo.toml b/Cargo.toml index 5e8ff19..4b6249b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,11 @@ edition = "2021" [lib] crate-type = ["cdylib", "rlib"] +[profile.release] +lto = true +opt-level = 'z' +codegen-units = 1 + [dependencies] swc_common = { git = "https://github.com/ef4/swc.git", branch = "content-tag", features=["tty-emitter"] } swc = { git = "https://github.com/ef4/swc.git", branch = "content-tag" } diff --git a/README.md b/README.md index aae6259..c380291 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,33 @@ npm install content-tag ## Usage +### Node (CommonJS) + ```js let { Preprocessor } = require('content-tag'); let p = new Preprocessor(); let output = p.process(''); + +console.log(output); +``` + +### Node (ESM) + +```js +import { Preprocessor } from 'content-tag'; +let p = new Preprocessor(); +let output = p.process(''); + +console.log(output); +``` + +### Browser (ESM) + +```js +import { createPreprocessor } from 'content-tag/standalone'; +let p = await createPreprocessor(); +let output = p.process(''); + console.log(output); ``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..ab9faea --- /dev/null +++ b/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# we need npm packages for the post-wasm phase +npm install + +rm -rf pkg + +# wasm-pack knows to use wasm-opt, when present +# NOTE: wasm-pack does not support multi-target building +# so we'll build twice, and then tweak package.json +# "exports" to point at the correct build depending on node or browser +wasm-pack build --target web --out-dir pkg/standalone --weak-refs --no-pack --release +wasm-pack build --target nodejs --out-dir pkg/node --weak-refs --no-pack --release + +# Rename the node js file to cjs, because we emit type=module +mv pkg/node/content_tag.js pkg/node/content_tag.cjs + +# generate the rest of the package for npm, since +# we disabled package.json generation above with --no-pack. +# this needs to be done because we're targeting +# both browser and node, which wasm-packg doesn't natively support. +node ./build/post-wasm-build.mjs + +# --------- +cp LICENSE pkg/LICENSE +cp README.md pkg/README.md diff --git a/build/post-wasm-build.mjs b/build/post-wasm-build.mjs new file mode 100644 index 0000000..6950c6a --- /dev/null +++ b/build/post-wasm-build.mjs @@ -0,0 +1,47 @@ +// This post-wasm-build.js script is called from build.sh +import fs from "node:fs/promises"; +import path from "node:path"; +import url from "node:url"; +import toml from "toml"; + +let cargo = await fs.readFile("Cargo.toml", "utf8"); +let config = toml.parse(cargo); + +const manifest = { + name: config.package.name, + description: config.package.description, + version: config.package.version, + license: config.package.license, + repository: { + type: "git", + url: "https://github.com/embroider-build/content-tag", + }, + files: ["standalone", "node"], + type: "module", + exports: { + ".": { + types: "./node/content_tag.d.ts", + default: "./node/content_tag.cjs", + }, + "./standalone": { + types: "./standalone/standalone.d.ts", + import: "./standalone/standalone.js", + }, + }, +}; + +const content = JSON.stringify(manifest, null, 2); + +const here = url.fileURLToPath(new URL(".", import.meta.url)); +const root = path.join(here, ".."); +const output = path.join(root, "pkg"); + +await fs.writeFile(path.join(output, "package.json"), content); +await fs.copyFile( + path.join(here, "src/standalone.js"), + path.join(output, "standalone/standalone.js") +); +await fs.copyFile( + path.join(here, "src/standalone.d.ts"), + path.join(output, "standalone/standalone.d.ts") +); diff --git a/build/src/standalone.d.ts b/build/src/standalone.d.ts new file mode 100644 index 0000000..c450256 --- /dev/null +++ b/build/src/standalone.d.ts @@ -0,0 +1,5 @@ +import type { Preprocessor } from './content_tag'; + +export * from "./content_tag"; + +export function createPreprocessor(): Promise; diff --git a/build/src/standalone.js b/build/src/standalone.js new file mode 100644 index 0000000..8260da0 --- /dev/null +++ b/build/src/standalone.js @@ -0,0 +1,12 @@ +export * from "./content_tag.js"; + +import init, { Preprocessor } from "./content_tag.js"; + +export async function createPreprocessor() { + // This no-ops if it's already ran + await init(); + + let processor = new Preprocessor(); + + return processor; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..ccc9326 --- /dev/null +++ b/index.html @@ -0,0 +1,25 @@ + + + + + + + + + + +

+
+
+
diff --git a/package-lock.json b/package-lock.json
index 5ec38f5..c63e8a9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,9 +11,11 @@
         "@release-it/bumper": "^5.1.0",
         "chai": "^4.3.7",
         "code-equality-assertions": "github:mansona/code-equality-assertions#add-chai-build",
+        "content-tag": "file:./pkg",
         "eslint": "^8.44.0",
         "mocha": "^10.2.0",
-        "release-it": "^16.2.1"
+        "release-it": "^16.2.1",
+        "toml": "^3.0.0"
       }
     },
     "node_modules/@aashutoshrathi/word-wrap": {
@@ -2086,6 +2088,10 @@
         "url": "https://github.com/yeoman/configstore?sponsor=1"
       }
     },
+    "node_modules/content-tag": {
+      "resolved": "pkg",
+      "link": true
+    },
     "node_modules/convert-source-map": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
@@ -7734,6 +7740,12 @@
         "node": ">=8.0"
       }
     },
+    "node_modules/toml": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
+      "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
+      "dev": true
+    },
     "node_modules/tr46": {
       "version": "0.0.3",
       "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -8354,6 +8366,12 @@
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
       }
+    },
+    "pkg": {
+      "name": "content-tag",
+      "version": "1.1.2",
+      "dev": true,
+      "license": "MIT"
     }
   }
 }
diff --git a/package.json b/package.json
index 7e4b8b5..a1fd455 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,8 @@
     "url": "git@github.com:embroider-build/content-tag.git"
   },
   "scripts": {
+    "web": "npx html-pages . --no-cache",
+    "build": "./build.sh",
     "test": "mocha"
   },
   "devDependencies": {
@@ -12,8 +14,10 @@
     "@release-it/bumper": "^5.1.0",
     "chai": "^4.3.7",
     "code-equality-assertions": "github:mansona/code-equality-assertions#add-chai-build",
+    "content-tag": "file:./pkg",
     "eslint": "^8.44.0",
     "mocha": "^10.2.0",
+    "toml": "^3.0.0",
     "release-it": "^16.2.1"
   },
   "publishConfig": {
diff --git a/test/node-api-esm.mjs b/test/node-api-esm.mjs
new file mode 100644
index 0000000..55a3c02
--- /dev/null
+++ b/test/node-api-esm.mjs
@@ -0,0 +1,65 @@
+import chai from "chai";
+import { codeEquality } from "code-equality-assertions/chai";
+
+chai.use(codeEquality);
+
+const { expect } = chai;
+
+import { Preprocessor } from "content-tag";
+const p = new Preprocessor();
+
+describe("Node ESM", function () {
+  it("works for a basic example", function () {
+    let output = p.process("");
+
+    expect(output).to
+      .equalCode(`import { template } from "@ember/template-compiler";
+export default template(\`Hi\`, {
+    eval () {
+        return eval(arguments[0]);
+    }
+});`);
+  });
+
+  it("Emits parse errors with anonymous file", function () {
+    expect(function () {
+      p.process(`const thing = "face";
+