Convert copy-res to typescript
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
501f01cdd5
commit
c944a273d0
8 changed files with 127 additions and 38 deletions
|
@ -19,7 +19,7 @@ module.exports = {
|
|||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}"],
|
||||
files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", "scripts/*.ts"],
|
||||
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
|
||||
// NOTE: These rules are frozen and new rules should not be added here.
|
||||
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"build": "yarn clean && yarn build:genfiles && yarn build:bundle",
|
||||
"build-stats": "yarn clean && yarn build:genfiles && yarn build:bundle-stats",
|
||||
"build:jitsi": "ts-node scripts/build-jitsi.ts",
|
||||
"build:res": "node scripts/copy-res.js",
|
||||
"build:res": "ts-node scripts/copy-res.ts",
|
||||
"build:genfiles": "yarn build:res && yarn build:jitsi && yarn build:module_system",
|
||||
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
|
||||
"build:bundle": "webpack --progress --bail --mode production",
|
||||
|
@ -47,7 +47,7 @@
|
|||
"dist": "scripts/package.sh",
|
||||
"start": "yarn build:module_system && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js\"",
|
||||
"start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js --https\"",
|
||||
"start:res": "yarn build:jitsi && node scripts/copy-res.js -w",
|
||||
"start:res": "yarn build:jitsi && ts-node scripts/copy-res.ts -w",
|
||||
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --mode development --disable-host-check --hot",
|
||||
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
|
||||
"lint:js": "yarn lint:js:src && yarn lint:js:module_system",
|
||||
|
@ -106,9 +106,11 @@
|
|||
"@sentry/webpack-plugin": "^2.0.0",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@testing-library/react": "^12.1.5",
|
||||
"@types/cpx": "1.5.0",
|
||||
"@types/jest": "^29.0.0",
|
||||
"@types/jitsi-meet": "^2.0.2",
|
||||
"@types/jsrsasign": "^10.5.4",
|
||||
"@types/loader-utils": "^2.0.4",
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/modernizr": "^3.5.3",
|
||||
"@types/node": "^16",
|
||||
|
@ -123,7 +125,7 @@
|
|||
"babel-loader": "^8.2.2",
|
||||
"chokidar": "^3.5.1",
|
||||
"concurrently": "^8.0.0",
|
||||
"cpx": "^1.5.0",
|
||||
"cpx": "1.5.0",
|
||||
"css-loader": "^4",
|
||||
"dotenv": "^16.0.2",
|
||||
"eslint": "8.48.0",
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const loaderUtils = require("loader-utils");
|
||||
|
||||
// copies the resources into the webapp directory.
|
||||
|
||||
import parseArgs from "minimist";
|
||||
import * as chokidar from "chokidar";
|
||||
import * as fs from "node:fs";
|
||||
import * as _ from "lodash";
|
||||
import * as Cpx from "cpx";
|
||||
import * as loaderUtils from "loader-utils";
|
||||
|
||||
const I18N_BASE_PATH = "src/i18n/strings/";
|
||||
const INCLUDE_LANGS = fs.readdirSync(I18N_BASE_PATH).filter((fn) => fn.endsWith(".json"));
|
||||
|
||||
// cpx includes globbed parts of the filename in the destination, but excludes
|
||||
// common parents. Hence, "res/{a,b}/**": the output will be "dest/a/..." and
|
||||
// "dest/b/...".
|
||||
const COPY_LIST = [
|
||||
const COPY_LIST: [
|
||||
sourceGlob: string,
|
||||
outputPath: string,
|
||||
opts?: {
|
||||
directwatch?: 1;
|
||||
},
|
||||
][] = [
|
||||
["res/apple-app-site-association", "webapp"],
|
||||
["res/manifest.json", "webapp"],
|
||||
["res/sw.js", "webapp"],
|
||||
|
@ -24,19 +35,12 @@ const COPY_LIST = [
|
|||
["./config.json", "webapp", { directwatch: 1 }],
|
||||
["contribute.json", "webapp"],
|
||||
];
|
||||
|
||||
const parseArgs = require("minimist");
|
||||
const Cpx = require("cpx");
|
||||
const chokidar = require("chokidar");
|
||||
const fs = require("fs");
|
||||
const _ = require("lodash");
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {});
|
||||
|
||||
const watch = argv.w;
|
||||
const verbose = argv.v;
|
||||
|
||||
function errCheck(err) {
|
||||
function errCheck(err?: Error): void {
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
process.exit(1);
|
||||
|
@ -52,7 +56,7 @@ if (!fs.existsSync("webapp/i18n/")) {
|
|||
fs.mkdirSync("webapp/i18n/");
|
||||
}
|
||||
|
||||
function next(i, err) {
|
||||
function next(i: number, err?: Error): void {
|
||||
errCheck(err);
|
||||
|
||||
if (i >= COPY_LIST.length) {
|
||||
|
@ -63,13 +67,9 @@ function next(i, err) {
|
|||
const source = ent[0];
|
||||
const dest = ent[1];
|
||||
const opts = ent[2] || {};
|
||||
let cpx = undefined;
|
||||
const cpx = new Cpx.Cpx(source, dest);
|
||||
|
||||
if (!opts.lang) {
|
||||
cpx = new Cpx.Cpx(source, dest);
|
||||
}
|
||||
|
||||
if (verbose && cpx) {
|
||||
if (verbose) {
|
||||
cpx.on("copy", (event) => {
|
||||
console.log(`Copied: ${event.srcPath} --> ${event.dstPath}`);
|
||||
});
|
||||
|
@ -78,7 +78,7 @@ function next(i, err) {
|
|||
});
|
||||
}
|
||||
|
||||
const cb = (err) => {
|
||||
const cb = (err?: Error): void => {
|
||||
next(i + 1, err);
|
||||
};
|
||||
|
||||
|
@ -88,7 +88,7 @@ function next(i, err) {
|
|||
// which in the case of config.json is '.', which inevitably takes
|
||||
// ages to crawl. So we create our own watcher on the files
|
||||
// instead.
|
||||
const copy = () => {
|
||||
const copy = (): void => {
|
||||
cpx.copy(errCheck);
|
||||
};
|
||||
chokidar.watch(source).on("add", copy).on("change", copy).on("ready", cb).on("error", errCheck);
|
||||
|
@ -102,7 +102,7 @@ function next(i, err) {
|
|||
}
|
||||
}
|
||||
|
||||
function genLangFile(lang, dest) {
|
||||
function genLangFile(lang: string, dest: string): string {
|
||||
const reactSdkFile = "node_modules/matrix-react-sdk/src/i18n/strings/" + lang + ".json";
|
||||
const riotWebFile = I18N_BASE_PATH + lang + ".json";
|
||||
|
||||
|
@ -120,7 +120,7 @@ function genLangFile(lang, dest) {
|
|||
|
||||
const json = JSON.stringify(translations, null, 4);
|
||||
const jsonBuffer = Buffer.from(json);
|
||||
const digest = loaderUtils.getHashDigest(jsonBuffer, null, null, 7);
|
||||
const digest = loaderUtils.getHashDigest(jsonBuffer, null, "hex", 7);
|
||||
const filename = `${lang}.${digest}.json`;
|
||||
|
||||
fs.writeFileSync(dest + filename, json);
|
||||
|
@ -131,8 +131,8 @@ function genLangFile(lang, dest) {
|
|||
return filename;
|
||||
}
|
||||
|
||||
function genLangList(langFileMap) {
|
||||
const languages = {};
|
||||
function genLangList(langFileMap: Record<string, string>): void {
|
||||
const languages: Record<string, string> = {};
|
||||
INCLUDE_LANGS.forEach(function (lang) {
|
||||
const normalizedLanguage = lang.toLowerCase().replace("_", "-");
|
||||
const languageParts = normalizedLanguage.split("-");
|
||||
|
@ -144,7 +144,7 @@ function genLangList(langFileMap) {
|
|||
});
|
||||
fs.writeFile("webapp/i18n/languages.json", JSON.stringify(languages, null, 4), function (err) {
|
||||
if (err) {
|
||||
console.error("Copy Error occured: " + err);
|
||||
console.error("Copy Error occured: " + err.message);
|
||||
throw new Error("Failed to generate languages.json");
|
||||
}
|
||||
});
|
||||
|
@ -158,15 +158,15 @@ function genLangList(langFileMap) {
|
|||
* regenerate the file, adding its content-hashed filename to langFileMap
|
||||
* and regenerating languages.json with the new filename
|
||||
*/
|
||||
function watchLanguage(lang, dest, langFileMap) {
|
||||
function watchLanguage(lang: string, dest: string, langFileMap: Record<string, string>): void {
|
||||
const reactSdkFile = "node_modules/matrix-react-sdk/src/i18n/strings/" + lang + ".json";
|
||||
const riotWebFile = I18N_BASE_PATH + lang + ".json";
|
||||
|
||||
// XXX: Use a debounce because for some reason if we read the language
|
||||
// file immediately after the FS event is received, the file contents
|
||||
// appears empty. Possibly https://github.com/nodejs/node/issues/6112
|
||||
let makeLangDebouncer;
|
||||
const makeLang = () => {
|
||||
let makeLangDebouncer: number;
|
||||
const makeLang = (): void => {
|
||||
if (makeLangDebouncer) {
|
||||
clearTimeout(makeLangDebouncer);
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ function watchLanguage(lang, dest, langFileMap) {
|
|||
|
||||
// language resources
|
||||
const I18N_DEST = "webapp/i18n/";
|
||||
const I18N_FILENAME_MAP = INCLUDE_LANGS.reduce((m, l) => {
|
||||
const I18N_FILENAME_MAP = INCLUDE_LANGS.reduce<Record<string, string>>((m, l) => {
|
||||
const filename = genLangFile(l, I18N_DEST);
|
||||
m[l] = filename;
|
||||
return m;
|
||||
|
@ -192,7 +192,7 @@ const I18N_FILENAME_MAP = INCLUDE_LANGS.reduce((m, l) => {
|
|||
genLangList(I18N_FILENAME_MAP);
|
||||
|
||||
if (watch) {
|
||||
INCLUDE_LANGS.forEach((l) => watchLanguage(l.value, I18N_DEST, I18N_FILENAME_MAP));
|
||||
INCLUDE_LANGS.forEach((l) => watchLanguage(l, I18N_DEST, I18N_FILENAME_MAP));
|
||||
}
|
||||
|
||||
// non-language resources
|
43
src/@types/cpx.d.ts
vendored
Normal file
43
src/@types/cpx.d.ts
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import "cpx";
|
||||
import type EventEmitter from "events";
|
||||
|
||||
declare module "cpx" {
|
||||
export class Cpx extends EventEmitter {
|
||||
public constructor(source: string, outDir: string, options?: object);
|
||||
|
||||
/**
|
||||
* Copy all files that matches `this.source` pattern to `this.outDir`.
|
||||
*
|
||||
* @param {function} [cb = null] - A callback function.
|
||||
* @returns {void}
|
||||
*/
|
||||
public copy(cb: Function | null): void;
|
||||
|
||||
/**
|
||||
* Copy all files that matches `this.source` pattern to `this.outDir`.
|
||||
* And watch changes in `this.base`, and copy only the file every time.
|
||||
*
|
||||
* @returns {void}
|
||||
* @throws {Error} This had been watching already.
|
||||
*/
|
||||
public watch(): void;
|
||||
}
|
||||
}
|
||||
|
||||
export as namespace Cpx;
|
28
src/@types/loader-utils.d.ts
vendored
Normal file
28
src/@types/loader-utils.d.ts
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import * as LoaderUtils from "loader-utils";
|
||||
|
||||
declare module "loader-utils" {
|
||||
export function getHashDigest(
|
||||
buffer: Buffer,
|
||||
hashType: null,
|
||||
digestType: LoaderUtils.DigestType,
|
||||
maxLength: number,
|
||||
): string;
|
||||
}
|
||||
|
||||
export as namespace Cpx;
|
|
@ -24,6 +24,7 @@
|
|||
"./src/**/*.ts",
|
||||
"./src/**/*.tsx",
|
||||
"./test/**/*.ts",
|
||||
"./test/**/*.tsx"
|
||||
"./test/**/*.tsx",
|
||||
"./scripts/*.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -507,7 +507,7 @@ module.exports = (env, argv) => {
|
|||
},
|
||||
{
|
||||
// cache-bust languages.json file placed in
|
||||
// element-web/webapp/i18n during build by copy-res.js
|
||||
// element-web/webapp/i18n during build by copy-res.ts
|
||||
test: /\.*languages.json$/,
|
||||
type: "javascript/auto",
|
||||
loader: "file-loader",
|
||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -2398,6 +2398,13 @@
|
|||
dependencies:
|
||||
"@babel/types" "^7.20.7"
|
||||
|
||||
"@types/cpx@1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/cpx/-/cpx-1.5.0.tgz#d2a44b0ab5ec32bfdd743f64aae84847858bce0c"
|
||||
integrity sha512-kuGK3lZqEvHTSDbJcaA6tcPoEXV4/e88YrltZMcQUewZhzYQwNSTMGIiPBqeeFd4LCBo1CX5U6CV6LaHG3wXSg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/events@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
||||
|
@ -2492,6 +2499,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/jsrsasign/-/jsrsasign-10.5.8.tgz#0d6c638505454b5e95c684d6f604d57641417336"
|
||||
integrity sha512-1oZ3TbarAhKtKUpyrCIqXpbx3ZAfoSulleJs6/UzzyYty0ut+kjRX7zHLAaHwVIuw8CBjIymwW4J2LK944HoHQ==
|
||||
|
||||
"@types/loader-utils@^2.0.4":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-2.0.4.tgz#f1c9dd27392f163ee92394454563286dfc6e4778"
|
||||
integrity sha512-I71X8yySVQW6DuXr78/McC+enpUYQ68JxAYlgVyuMvl5mb7jFUZpFAu1qURZcwvbITXwxPnrA7hbV0W3HHsbbg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/webpack" "^4"
|
||||
|
||||
"@types/lodash@^4.14.197":
|
||||
version "4.14.198"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.198.tgz#4d27465257011aedc741a809f1269941fa2c5d4c"
|
||||
|
@ -2651,7 +2666,7 @@
|
|||
"@types/source-list-map" "*"
|
||||
source-map "^0.7.3"
|
||||
|
||||
"@types/webpack@^4.41.8":
|
||||
"@types/webpack@^4", "@types/webpack@^4.41.8":
|
||||
version "4.41.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.33.tgz#16164845a5be6a306bcbe554a8e67f9cac215ffc"
|
||||
integrity sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==
|
||||
|
@ -4449,7 +4464,7 @@ counterpart@^0.18.6:
|
|||
pluralizers "^0.1.7"
|
||||
sprintf-js "^1.0.3"
|
||||
|
||||
cpx@^1.5.0:
|
||||
cpx@1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/cpx/-/cpx-1.5.0.tgz#185be018511d87270dedccc293171e37655ab88f"
|
||||
integrity sha512-jHTjZhsbg9xWgsP2vuNW2jnnzBX+p4T+vNI9Lbjzs1n4KhOfa22bQppiFYLsWQKd8TzmL5aSP/Me3yfsCwXbDA==
|
||||
|
|
Loading…
Reference in a new issue