Skip to content

Commit 03751df

Browse files
shakyShaneShane OsbournejonathanKingston
authored
fix: support building on windows (#374)
* fix: support building on windows * support more than 1 output * skipping the example build * windows compatible script * cross-platform file path * don't change node requirement * trying run on windows * ignore a symlink * drop symlinks + define build inputs/outputs * remove inline json from build script * unit tests * remove pr-flow for now --------- Co-authored-by: Shane Osbourne <[email protected]> Co-authored-by: Jonathan Kingston <[email protected]>
1 parent 0fb8b24 commit 03751df

File tree

16 files changed

+201
-113
lines changed

16 files changed

+201
-113
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ docs/
33
lib/
44
Sources/ContentScopeScripts/dist/
55
integration-test/extension/contentScope.js
6+
integration-test/pages/build
67
packages/special-pages/pages/**/public

.github/workflows/pr-flow.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

.github/workflows/tests.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ on: [push, pull_request]
44

55
jobs:
66
unit:
7-
runs-on: ubuntu-20.04
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
matrix:
10+
os: [ ubuntu-20.04, windows-latest ]
811
steps:
912
- uses: actions/checkout@v2
1013
- name: Use Node.js 18

build-output.eslintrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"root": true,
3+
"parserOptions": {
4+
"ecmaVersion": "latest",
5+
},
6+
"rules": {
7+
"no-implicit-globals": "error"
8+
},
9+
}

integration-test/pages/build

Lines changed: 0 additions & 1 deletion
This file was deleted.

integration-test/pages/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
<body>
33
<h1>Integration page</h1>
44
<p>This loads the injection file as if it were loaded through the content script.</p>
5-
<script src="./build/integration/contentScope.js"></script>
5+
<script src="./build/contentScope.js"></script>
66
</body>
77
</html>

package-lock.json

Lines changed: 11 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,20 @@
1111
"copy-sjcl": "node scripts/generateSJCL.js",
1212
"bundle-config": "node scripts/bundleConfig.mjs",
1313
"build": "npm run build-locales && npm run build-firefox && npm run build-chrome && npm run build-apple && npm run build-android && npm run build-windows && npm run build-integration && npm run build-chrome-mv3",
14-
"build-locales": "mkdir -p build/locales && node scripts/buildLocales src/locales/click-to-load > build/locales/ctl-locales.js",
15-
"build-firefox": "mkdir -p build/firefox/ && node scripts/inject.js firefox > build/firefox/inject.js",
16-
"build-chrome": "mkdir -p build/chrome/ && node scripts/inject.js chrome > build/chrome/inject.js",
17-
"build-chrome-mv3": "mkdir -p build/chrome-mv3/ && node scripts/inject.js chrome-mv3 > build/chrome-mv3/inject.js",
18-
"build-apple": "mkdir -p Sources/ContentScopeScripts/dist/ && node scripts/inject.js apple > Sources/ContentScopeScripts/dist/contentScope.js",
19-
"build-android": "mkdir -p build/android/ && node scripts/inject.js android > build/android/contentScope.js",
20-
"build-windows": "mkdir -p build/windows/ && node scripts/inject.js windows > build/windows/contentScope.js",
21-
"build-integration": "mkdir -p build/integration/ && node scripts/inject.js integration > build/integration/contentScope.js && npm run copy-build-integration",
22-
"copy-build-integration": "cp build/integration/contentScope.js integration-test/extension",
14+
"build-locales": "node scripts/buildLocales.js --dir src/locales/click-to-load --output build/locales/ctl-locales.js",
15+
"build-firefox": "node scripts/inject.js --platform firefox",
16+
"build-chrome": "node scripts/inject.js --platform chrome",
17+
"build-chrome-mv3": "node scripts/inject.js --platform chrome-mv3",
18+
"build-apple": "node scripts/inject.js --platform apple",
19+
"build-android": "node scripts/inject.js --platform android",
20+
"build-windows": "node scripts/inject.js --platform windows",
21+
"build-integration": "node scripts/inject.js --platform integration",
2322
"docs": "typedoc",
2423
"postbuild": "npm run build --workspaces --if-present",
2524
"tsc": "tsc",
2625
"tsc.watch": "tsc --watch",
2726
"lint": "eslint . && npm run tsc",
28-
"lint-no-output-globals": "eslint Sources/ContentScopeScripts/dist/contentScope.js --rule '{\"no-implicit-globals\": [\"error\"]}' --no-ignore --no-eslintrc --parser-options=ecmaVersion:latest",
27+
"lint-no-output-globals": "eslint --no-eslintrc --config=build-output.eslintrc --no-ignore Sources/ContentScopeScripts/dist/contentScope.js",
2928
"lint-fix": "eslint . --fix && npm run tsc",
3029
"test-unit": "jasmine --config=unit-test/config.json",
3130
"test-int": "npm run build-integration && jasmine --config=integration-test/config.js",
@@ -62,6 +61,7 @@
6261
"rollup": "^3.20.2",
6362
"rollup-plugin-dynamic-import-variables": "^1.1.0",
6463
"typedoc": "^0.23.28",
65-
"typescript": "^5.0.3"
64+
"typescript": "^5.0.3",
65+
"minimist": "^1.2.8"
6666
}
6767
}

packages/special-pages/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
*/
1414
import { join } from 'node:path'
1515
import { existsSync, cpSync, rmSync } from 'node:fs'
16-
const CWD = new URL('.', import.meta.url).pathname
17-
const ROOT = new URL('../../', import.meta.url).pathname
16+
import { cwd } from '../../scripts/script-utils.js'
17+
const CWD = cwd(import.meta.url)
18+
const ROOT = join(CWD, '../../')
1819
const BUILD = join(ROOT, 'build')
1920

2021
export const support = {

packages/special-pages/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"main": "index.js",
77
"type": "module",
88
"scripts": {
9-
"build": "npm run build.pages; node index.js",
9+
"build": "npm run build.pages && node index.js",
1010
"build.pages": "node scripts/build.js",
1111
"test": "echo '✅ No tests yet'",
1212
"test.headed": "playwright test --headed",

packages/special-pages/scripts/build.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { join } from 'node:path'
22
import { buildSync } from 'esbuild'
3-
const CWD = new URL('..', import.meta.url).pathname
3+
import { cwd } from '../../../scripts/script-utils.js'
4+
const CWD = join(cwd(import.meta.url), '..')
45

56
// build example page js
67
buildSync({

scripts/buildLocales.js

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,42 @@
11
import { readdirSync, readFileSync } from 'fs'
22
import { join } from 'path'
3+
import { parseArgs, write } from './script-utils.js'
34

4-
// This script loads the current JSON-based locales files and merges them into
5-
// a single importable ES module for bundling purposes
6-
const localesRoot = process.argv[2]
7-
if (!localesRoot) {
8-
console.log('usage: buildLocales <locales/feature dir>')
9-
}
10-
11-
const locales = {}
12-
const localeDirs = readdirSync(localesRoot).filter(f => !f.startsWith('.'))
13-
for (const locale of localeDirs) {
14-
locales[locale] = {}
15-
const dir = join(localesRoot, locale)
16-
const files = readdirSync(dir)
17-
for (const file of files) {
18-
const localeJSON = readFileSync(join(dir, file))
19-
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
20-
const stringObj = JSON.parse(localeJSON)
21-
locales[locale][file] = {}
22-
for (const [key, value] of Object.entries(stringObj)) {
23-
if (key !== 'smartling') {
24-
locales[locale][file][key] = value.title
5+
/**
6+
* This script loads the current JSON-based locales files and merges them into
7+
* a single importable ES module for bundling purposes
8+
* @param localesRoot
9+
* @return {string}
10+
*/
11+
function bundle (localesRoot) {
12+
const locales = {}
13+
const localeDirs = readdirSync(localesRoot).filter(f => !f.startsWith('.'))
14+
for (const locale of localeDirs) {
15+
locales[locale] = {}
16+
const dir = join(localesRoot, locale)
17+
const files = readdirSync(dir)
18+
for (const file of files) {
19+
const localeJSON = readFileSync(join(dir, file))
20+
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
21+
const stringObj = JSON.parse(localeJSON)
22+
locales[locale][file] = {}
23+
for (const [key, value] of Object.entries(stringObj)) {
24+
if (key !== 'smartling') {
25+
locales[locale][file][key] = value.title
26+
}
2527
}
2628
}
2729
}
30+
31+
return 'export default `' +
32+
JSON.stringify(locales).replace('`', '\\`') +
33+
'`'
2834
}
2935

30-
const output = 'export default `' +
31-
JSON.stringify(locales).replace('`', '\\`') +
32-
'`'
33-
console.log(output)
36+
const requiredFields = ['dir', 'output']
37+
const help = 'usage: buildLocales <locales/feature dir>'
38+
const args = parseArgs(process.argv.slice(2), requiredFields, help)
39+
40+
// run the build and write the files
41+
const bundled = bundle(args.dir)
42+
write(args.output, bundled)

scripts/generateSJCL.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ async function init () {
1212
return
1313
}
1414

15+
if (process.platform === 'win32') {
16+
console.log('skipping sjcl on windows')
17+
return
18+
}
19+
1520
await exec('cd node_modules/sjcl/ && perl ./configure --no-export --compress=none --without-all --with-hmac --with-codecHex && make')
1621
const sjclFileContents = await fs.readFile('node_modules/sjcl/sjcl.js')
1722
// Reexport the file as es6 module format

scripts/inject.js

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,83 @@
11
import { rollupScript } from './utils/build.js'
2+
import { parseArgs, write } from './script-utils.js'
23

34
const contentScopePath = 'src/content-scope-features.js'
45
const contentScopeName = 'contentScopeFeatures'
56

6-
async function init () {
7-
if (process.argv.length !== 3) {
8-
throw new Error('Specify the build type as an argument to this script.')
9-
}
10-
if (process.argv[2] === 'firefox') {
11-
initOther('inject/mozilla.js', process.argv[2])
12-
} else if (process.argv[2] === 'apple') {
13-
initOther('inject/apple.js', process.argv[2])
14-
} else if (process.argv[2] === 'android') {
15-
initOther('inject/android.js', process.argv[2])
16-
} else if (process.argv[2] === 'windows') {
17-
initOther('inject/windows.js', process.argv[2])
18-
} else if (process.argv[2] === 'integration') {
19-
initOther('inject/integration.js', process.argv[2])
20-
} else if (process.argv[2] === 'chrome-mv3') {
21-
initOther('inject/chrome-mv3.js', 'chrome_mv3')
22-
} else {
23-
initChrome()
7+
const builds = {
8+
firefox: {
9+
input: 'inject/mozilla.js',
10+
output: ['build/firefox/inject.js']
11+
},
12+
apple: {
13+
input: 'inject/apple.js',
14+
output: ['Sources/ContentScopeScripts/dist/contentScope.js']
15+
},
16+
android: {
17+
input: 'inject/android.js',
18+
output: ['build/android/contentScope.js']
19+
},
20+
windows: {
21+
input: 'inject/windows.js',
22+
output: ['build/windows/contentScope.js']
23+
},
24+
integration: {
25+
input: 'inject/integration.js',
26+
output: [
27+
'build/integration/contentScope.js',
28+
'integration-test/extension/contentScope.js',
29+
'integration-test/pages/build/contentScope.js'
30+
]
31+
},
32+
'chrome-mv3': {
33+
input: 'inject/chrome-mv3.js',
34+
output: ['build/chrome-mv3/inject.js']
35+
},
36+
chrome: {
37+
input: 'inject/chrome.js',
38+
output: ['build/chrome/inject.js']
2439
}
2540
}
2641

2742
async function initOther (injectScriptPath, platformName) {
2843
const injectScript = await rollupScript(injectScriptPath, `inject${platformName}`)
2944
const outputScript = injectScript
30-
console.log(outputScript)
45+
return outputScript
3146
}
3247

33-
async function initChrome () {
48+
/**
49+
* @param {string} entry
50+
*/
51+
async function initChrome (entry) {
3452
const replaceString = '/* global contentScopeFeatures */'
35-
const injectScriptPath = 'inject/chrome.js'
36-
const injectScript = await rollupScript(injectScriptPath)
53+
const injectScript = await rollupScript(entry)
3754
const contentScope = await rollupScript(contentScopePath, contentScopeName)
3855
// Encode in URI format to prevent breakage (we could choose to just escape ` instead)
3956
// NB: .replace(/\r\n/g, "\n") is needed because in Windows rollup generates CRLF line endings
4057
const encodedString = encodeURI(contentScope.toString().replace(/\r\n/g, '\n'))
4158
const outputScript = injectScript.toString().replace(replaceString, '${decodeURI("' + encodedString + '")}')
42-
console.log(outputScript)
59+
return outputScript
60+
}
61+
62+
async function init () {
63+
// verify the input
64+
const requiredFields = ['platform']
65+
const args = parseArgs(process.argv.slice(2), requiredFields)
66+
const build = builds[args.platform]
67+
68+
if (!build) {
69+
throw new Error('unsupported platform: ' + args.platform)
70+
}
71+
72+
let output
73+
if (args.platform === 'chrome') {
74+
output = await initChrome(build.input)
75+
} else {
76+
output = await initOther(build.input)
77+
}
78+
79+
// bundle and write the output
80+
write(build.output, output)
4381
}
4482

4583
init()

0 commit comments

Comments
 (0)