From e5738667b4331f670adfa33935c690cdafb0fb1f Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 9 Jan 2023 13:45:32 +0700 Subject: [PATCH] change(web): main web's source cleaner tool now based on new common tool --- web/build.sh | 8 +- .../tools/building/sourcemap-root/build.sh | 7 +- .../tools/building/sourcemap-root/index.ts | 86 +++++++------------ .../building/sourcemap-root/tsconfig.json | 4 +- 4 files changed, 42 insertions(+), 63 deletions(-) diff --git a/web/build.sh b/web/build.sh index ce49bc866d..49aa23c3dd 100755 --- a/web/build.sh +++ b/web/build.sh @@ -166,7 +166,7 @@ minifycmd="$JAVA -jar $minifier --compilation_level WHITESPACE_ONLY $minifier_wa readonly minifier readonly minifycmd -minified_sourcemap_cleaner="build/tools/building/sourcemap-root" +minified_sourcemap_cleaner="build/tools/building/sourcemap-root/index.mjs" # Fails the build if a specified file does not exist. assert_exists ( ) { @@ -183,9 +183,9 @@ assert_exists ( ) { # $5 - additional output wrapper minify ( ) { if [ $# -ge 4 ]; then - cleanerOptions="--suffix $4" + cleanerOptions="--clean --suffix $4" else - cleanerOptions= + cleanerOptions="--clean" fi if [ $# -ge 5 ]; then @@ -209,7 +209,7 @@ minify ( ) { --source_map_location_mapping "$INPUT_DIR|../../.." \ --js "$INPUT" --compilation_level $3 \ --js_output_file "$OUTPUT" --warning_level VERBOSE --output_wrapper "$wrapper -//# sourceMappingURL=$1.map" +//# sourceMappingURL=$INPUT_FILE.map" # Now to clean the source map. assert_exists "$OUTPUT" diff --git a/web/src/tools/building/sourcemap-root/build.sh b/web/src/tools/building/sourcemap-root/build.sh index a3004db5d3..453a1888f8 100755 --- a/web/src/tools/building/sourcemap-root/build.sh +++ b/web/src/tools/building/sourcemap-root/build.sh @@ -18,13 +18,14 @@ cd "$THIS_SCRIPT_PATH" ################################ Main script ################################ builder_describe "Builds the sourcemap-sanitizing script used for Keyman Engine for Web builds" \ + "@../../../../../common/tools/sourcemap-path-remapper" \ "clean" \ "configure" \ "build" \ builder_describe_outputs \ configure /node_modules \ - build index.js + build ../../../../build/tools/sourcemap-root/index.js builder_parse "$@" @@ -43,5 +44,9 @@ fi if builder_start_action build; then npm run tsc -- -b "$THIS_SCRIPT_PATH/tsconfig.json" + # Necessary until the Web project is converted over to ES modules. + # Node defaults to CommonJS format otherwise. + cp ../../../../build/tools/building/sourcemap-root/index.js ../../../../build/tools/building/sourcemap-root/index.mjs + builder_finish_action success build fi diff --git a/web/src/tools/building/sourcemap-root/index.ts b/web/src/tools/building/sourcemap-root/index.ts index ba17a2c4f9..5c362e3b80 100644 --- a/web/src/tools/building/sourcemap-root/index.ts +++ b/web/src/tools/building/sourcemap-root/index.ts @@ -1,12 +1,13 @@ -var fs = require("fs"); +import SourcemapRemapper from "@keymanapp/sourcemap-path-remapper" function displayHelp() { console.log("KeymanWeb's sourcemap-cleansing tool. This tool is designed to produce clean filepaths"); console.log("in the sourcemaps for ease of reference in browser and Sentry, copying the clean paths TS"); console.log("is able to provide, whereas Closure's minification is not."); console.log(""); - console.log("Usage: node sourcemap-root [-s|--suffix ]"); - console.log(" -s|--suffix Appends to the input sourcemap's 'sourceRoot'.") + console.log("Usage: node sourcemap-root [-c|--clean] [-s|--sourceRoot ]"); + console.log(" -c|--clean Runs source-filepath cleaning operations."); + console.log(" -s|--suffix Sets the input sourcemap's 'sourceRoot' to ."); } // By default, any node-based process has two command-line args: @@ -38,85 +39,56 @@ function assert_is_map(filename: string) { } } // Verify the first parameter is a sourcemap filepath. -let sourceFile = process.argv[2]; +// let sourceFile = process.argv[2]; // Used to be necessary, but no longer is. let destFile = process.argv[3]; -assert_is_map(sourceFile); assert_is_map(destFile); // Now to process any additional flags. -var sourceRootSuffix = ""; +var sourceRoot = ""; +let shouldClean = false; // Starting at [5] - optional command-line arguments for(let procArgIndex = 4; procArgIndex < process.argv.length; procArgIndex++) { let flag = process.argv[procArgIndex]; - + if(flag.indexOf('-') != 0) { console.error("Error: Unexpected command-line argument provided: \"" + flag + "\" is not an argument flag") process.exit(1); } switch(flag) { + case "-c": + case "--clean": + shouldClean = true; + break; case "-s": case "--suffix": procArgIndex++; - sourceRootSuffix = process.argv[procArgIndex]; + sourceRoot = process.argv[procArgIndex]; break; default: console.warn("Unrecognized flag found in argument list: \"" + flag + "\""); } } -let sourceContent: string; -let destContent: string; -try { - sourceContent = fs.readFileSync(sourceFile) as string; - destContent = fs.readFileSync(destFile) as string; -} catch(err) { - console.error("Could not read specified input files"); - console.error(""); - console.error(err); - process.exit(1); +let srcMap = SourcemapRemapper.fromFile(destFile); + +if(shouldClean) { + // First pass: remove any closure prepended ../../../ pathing. + srcMap.remapPaths([ + { from: "../../../", to: "" } + ]); + + // Second pass: fix up any mangled source paths + srcMap.remapPaths([ + { from: "common/web/input-processor/build/keyman/", to: "" }, + { from: "common/web/keyboard-processor/build/keyman/", to: "" } + ]); } -let sourceJSON = JSON.parse(sourceContent) as {[key: string]: any}; -let destJSON = JSON.parse(destContent) as {[key: string]: any}; - -// We now have the root JSON contents. Time to go to work! First, the easy parts. -destJSON["file"] = sourceJSON["file"]; -destJSON["sourceRoot"] = sourceJSON["sourceRoot"] + sourceRootSuffix; - -// The hard part: mapping the source file arrays correctly. -// A raw copy of the arrays will not work properly. -let sourceSources = sourceJSON["sources"] as string[]; -let destSources = destJSON["sources"] as string[]; -let finalDestSources: string[] = []; - -/** - * Closure's minification always uses the TS paths as a suffix, prepending relative minification-path info to reuse them. - * So, if we can find the TS path complete within a path in the minified sourcemap, it's a match. - * - * It's key that we preserve the original ordering of the source files from Closure's output sourcemaps, as is done here. - * Otherwise, browsers will incorrectly match the inlined source to any given file, causing a fair bit of confusion. - * This is why we iterate over the destination's defined array; this way ensures identical ordering for the finalized version. - */ -for(let destPath of destSources) { - let matched = false; - - for(let sourcePath of sourceSources) { - if(destPath.indexOf(sourcePath) != -1) { - matched = true; - finalDestSources.push(sourcePath); - break; - } - } - - if(!matched) { - finalDestSources.push(destPath); - } +if(sourceRoot) { + srcMap.sourceRoot = srcMap.sourceRoot ?? "" + sourceRoot; } -destJSON["sources"] = finalDestSources; - -let destOutput = JSON.stringify(destJSON); -fs.writeFileSync(destFile, destOutput); \ No newline at end of file +srcMap.toFile(destFile); \ No newline at end of file diff --git a/web/src/tools/building/sourcemap-root/tsconfig.json b/web/src/tools/building/sourcemap-root/tsconfig.json index e8e4d5e4c6..6324bca910 100644 --- a/web/src/tools/building/sourcemap-root/tsconfig.json +++ b/web/src/tools/building/sourcemap-root/tsconfig.json @@ -1,7 +1,9 @@ { "compilerOptions": { - "allowJs": true, + "allowJs": false, "outDir": "../../../../build/tools/building/sourcemap-root", + "module": "es6", + "moduleResolution": "node", "types": ["node"], "lib": ["es6", "dom"] }