Added tr caching to webpack

canary
WolverinDEV 2020-03-31 15:19:53 +02:00
parent 2d5006bf64
commit d5ed46150e
18 changed files with 160 additions and 137 deletions

6
package-lock.json generated
View File

@ -9240,6 +9240,12 @@
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
"dev": true "dev": true
}, },
"wabt": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/wabt/-/wabt-1.0.13.tgz",
"integrity": "sha512-nkWPyUjYt+SqPox2mjJF5jrpWv30awdXKdG0OmryzfhtahHBrPz/BGSbakPgcJU2SFjC1s7Mb8MadRhQ6lmqUg==",
"dev": true
},
"watchpack": { "watchpack": {
"version": "1.6.1", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz",

View File

@ -26,8 +26,8 @@
"author": "TeaSpeak (WolverinDEV)", "author": "TeaSpeak (WolverinDEV)",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/fs-extra": "^8.0.1",
"@types/emscripten": "^1.38.0", "@types/emscripten": "^1.38.0",
"@types/fs-extra": "^8.0.1",
"@types/jquery": "^3.3.34", "@types/jquery": "^3.3.34",
"@types/lodash": "^4.14.149", "@types/lodash": "^4.14.149",
"@types/moment": "^2.13.0", "@types/moment": "^2.13.0",
@ -36,12 +36,15 @@
"@types/sha256": "^0.2.0", "@types/sha256": "^0.2.0",
"@types/websocket": "0.0.40", "@types/websocket": "0.0.40",
"chunk-manifest-webpack-plugin": "^1.1.2", "chunk-manifest-webpack-plugin": "^1.1.2",
"circular-dependency-plugin": "^5.2.0",
"clean-css": "^4.2.1", "clean-css": "^4.2.1",
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.2",
"csso-cli": "^2.0.2", "csso-cli": "^2.0.2",
"exports-loader": "^0.7.0", "exports-loader": "^0.7.0",
"fs-extra": "latest", "fs-extra": "latest",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"html-loader": "^1.0.0",
"html-webpack-plugin": "^4.0.3", "html-webpack-plugin": "^4.0.3",
"mime-types": "^2.1.24", "mime-types": "^2.1.24",
"mini-css-extract-plugin": "^0.9.0", "mini-css-extract-plugin": "^0.9.0",
@ -49,20 +52,19 @@
"node-sass": "^4.13.1", "node-sass": "^4.13.1",
"raw-loader": "^4.0.0", "raw-loader": "^4.0.0",
"sass": "1.22.10", "sass": "1.22.10",
"sass-loader": "^8.0.2",
"sha256": "^0.2.0", "sha256": "^0.2.0",
"style-loader": "^1.1.3",
"terser": "^4.2.1", "terser": "^4.2.1",
"ts-loader": "^6.2.2", "ts-loader": "^6.2.2",
"ttypescript": "^1.5.10", "ttypescript": "^1.5.10",
"typescript": "3.6.5", "typescript": "3.6.5",
"wabt": "^1.0.13",
"webpack": "^4.42.1", "webpack": "^4.42.1",
"webpack-bundle-analyzer": "^3.6.1", "webpack-bundle-analyzer": "^3.6.1",
"webpack-cli": "^3.3.11", "webpack-cli": "^3.3.11",
"worker-plugin": "^4.0.2", "worker-plugin": "^4.0.2",
"circular-dependency-plugin": "^5.2.0", "terser-webpack-plugin": "latest"
"css-loader": "^3.4.2",
"html-loader": "^1.0.0",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -477,7 +477,7 @@ export class ConnectionHandler {
this._certificate_modal = createErrorModal( this._certificate_modal = createErrorModal(
tr("Could not connect"), tr("Could not connect"),
formatMessage(tr(error_message_format), this.generate_ssl_certificate_accept()) formatMessage(/* @tr-ignore */ tr(error_message_format), this.generate_ssl_certificate_accept())
); );
this._certificate_modal.close_listener.push(() => this._certificate_modal = undefined); this._certificate_modal.close_listener.push(() => this._certificate_modal = undefined);
this._certificate_modal.open(); this._certificate_modal.open();

View File

@ -70,7 +70,7 @@ export function tr(message: string, key?: string) {
} }
export function tra(message: string, ...args: any[]) { export function tra(message: string, ...args: any[]) {
message = tr(message); message = /* @tr-ignore */ tr(message);
return formatMessage(message, ...args); return formatMessage(message, ...args);
} }

View File

@ -113,7 +113,7 @@ function setup_jsrender() : boolean {
}); });
js_render.views.tags("tr", (...args) => { js_render.views.tags("tr", (...args) => {
return tr(args[0]); return /* @tr-ignore */ tr(args[0]);
}); });
$(".jsrender-template").each((idx, _entry) => { $(".jsrender-template").each((idx, _entry) => {
@ -481,7 +481,7 @@ const task_connect_handler: loader.Task = {
"You could now close this page."; "You could now close this page.";
createInfoModal( createInfoModal(
tr("Connecting successfully within other instance"), tr("Connecting successfully within other instance"),
formatMessage(tr(message), connect_data.address), formatMessage(/* @tr-ignore */ tr(message), connect_data.address),
{ {
closeable: false, closeable: false,
footer: undefined footer: undefined
@ -548,7 +548,7 @@ const task_certificate_callback: loader.Task = {
"This page will close in {0} seconds."; "This page will close in {0} seconds.";
createInfoModal( createInfoModal(
tr("Certificate acccepted successfully"), tr("Certificate acccepted successfully"),
formatMessage(tr(message), seconds_tag), formatMessage(/* @tr-ignore */ tr(message), seconds_tag),
{ {
closeable: false, closeable: false,
footer: undefined footer: undefined

View File

@ -10,7 +10,6 @@ import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase"; import {AbstractServerConnection} from "tc-shared/connection/ConnectionBase";
import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler"; import {HandshakeIdentityHandler} from "tc-shared/connection/HandshakeHandler";
console.error(AbstractHandshakeIdentityHandler);
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler { class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
readonly identity: NameIdentity; readonly identity: NameIdentity;
handler: HandshakeCommandHandler<NameHandshakeHandler>; handler: HandshakeCommandHandler<NameHandshakeHandler>;

View File

@ -163,7 +163,7 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<emodal.new
container.addClass("help-shown"); container.addClass("help-shown");
const text = tr( const text = tr( /* @tr-ignore */
"After you've successfully set upped your microphone,\n" + "After you've successfully set upped your microphone,\n" +
"lets setup some profiles and identities!\n" + "lets setup some profiles and identities!\n" +
"\n" + "\n" +
@ -202,7 +202,7 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<emodal.new
update_position(); update_position();
container_help_text.off('resize').on('resize', update_position); container_help_text.off('resize').on('resize', update_position);
const text = tr( const text = tr( /* @tr-ignore */
"You could have as many connect profiles as you want.\n" + "You could have as many connect profiles as you want.\n" +
"All created profiles will be listed here.\n" + "All created profiles will be listed here.\n" +
"\n" + "\n" +
@ -234,7 +234,7 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<emodal.new
bottom: "1em" bottom: "1em"
}); });
}; };
set_help_text(tr( set_help_text(tr( /* @tr-ignore */
"In the upper left, you'll find the profile settings for the selected profile.\n" + "In the upper left, you'll find the profile settings for the selected profile.\n" +
"You could give each profile an individual name. You could also specify the default connect nickname here.\n" + "You could give each profile an individual name. You could also specify the default connect nickname here.\n" +
"\n" + "\n" +
@ -267,7 +267,7 @@ function initializeStepIdentity(tag: JQuery, event_registry: Registry<emodal.new
bottom: "1em" bottom: "1em"
}); });
}; };
set_help_text(tr( set_help_text(tr( /* @tr-ignore */
"When selecting an identify type, some corresponding will pop up in the highlighted area.\n" + "When selecting an identify type, some corresponding will pop up in the highlighted area.\n" +
"\n" + "\n" +
"But don't worry, we've already generated\n" + "But don't worry, we've already generated\n" +
@ -321,7 +321,7 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<emodal.n
is_first_show = false; is_first_show = false;
container.addClass("help-shown"); container.addClass("help-shown");
const text = tr( const text = tr( /* @tr-ignore */
"Firstly we need to setup a microphone.\n" + "Firstly we need to setup a microphone.\n" +
"Let me guide you thru the basic UI elements.\n" + "Let me guide you thru the basic UI elements.\n" +
"\n" + "\n" +
@ -356,7 +356,7 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<emodal.n
update_position(); update_position();
container_help_text.off('resize').on('resize', update_position); container_help_text.off('resize').on('resize', update_position);
const text = tr( const text = tr( /* @tr-ignore */
"All your available microphones are listed within this box.\n" + "All your available microphones are listed within this box.\n" +
"\n" + "\n" +
"The currently selected microphone\n" + "The currently selected microphone\n" +
@ -393,7 +393,7 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<emodal.n
$.spawn("ol").append( $.spawn("ol").append(
$.spawn("li").addClass("vad-type").append( $.spawn("li").addClass("vad-type").append(
$.spawn("a").addClass("title").text(tr("Push to Talk")), $.spawn("a").addClass("title").text(tr("Push to Talk")),
$.spawn("a").addClass("description").html(tr( $.spawn("a").addClass("description").html(tr( /* @tr-ignore */
"To transmit audio data you'll have to<br>" + "To transmit audio data you'll have to<br>" +
"press a key. The key could be selected " + "press a key. The key could be selected " +
"via the button right to the radio button." "via the button right to the radio button."
@ -401,7 +401,7 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<emodal.n
), ),
$.spawn("li").addClass("vad-type").append( $.spawn("li").addClass("vad-type").append(
$.spawn("a").addClass("title").text(tr("Voice activity detection")), $.spawn("a").addClass("title").text(tr("Voice activity detection")),
$.spawn("a").addClass("description").html(tr( $.spawn("a").addClass("description").html(tr( /* @tr-ignore */
"In this mode, TeaSpeak will continuously analyze your microphone input. " + "In this mode, TeaSpeak will continuously analyze your microphone input. " +
"If the audio level is grater than a certain threshold, " + "If the audio level is grater than a certain threshold, " +
"the audio will be transmitted. " + "the audio will be transmitted. " +
@ -410,7 +410,7 @@ function initializeStepMicrophone(tag: JQuery, event_registry: Registry<emodal.n
), ),
$.spawn("li").addClass("vad-type").append( $.spawn("li").addClass("vad-type").append(
$.spawn("a").addClass("title").html(tr("Always active")), $.spawn("a").addClass("title").html(tr("Always active")),
$.spawn("a").addClass("description").text(tr( $.spawn("a").addClass("description").text(tr( /* @tr-ignore */
"Continuously transmit any audio data.\n" "Continuously transmit any audio data.\n"
)) ))
) )

View File

@ -23,6 +23,7 @@ import {
senseless_client_permissions, senseless_server_group_permissions senseless_client_permissions, senseless_server_group_permissions
} from "tc-shared/ui/modal/permission/SenselessPermissions"; } from "tc-shared/ui/modal/permission/SenselessPermissions";
import {AbstractPermissionEditor, PermissionEditorMode} from "tc-shared/ui/modal/permission/AbstractPermissionEditor"; import {AbstractPermissionEditor, PermissionEditorMode} from "tc-shared/ui/modal/permission/AbstractPermissionEditor";
import {tra} from "tc-shared/i18n/localize";
declare global { declare global {
interface JQuery<TElement = HTMLElement> { interface JQuery<TElement = HTMLElement> {
@ -1358,7 +1359,7 @@ function apply_server_groups(connection: ConnectionHandler, editor: AbstractPerm
console.log(tr("Failed to add client %o to server group %o: %o"), dbid, current_group.id, error); console.log(tr("Failed to add client %o to server group %o: %o"), dbid, current_group.id, error);
if(error instanceof CommandResult) if(error instanceof CommandResult)
error = error.extra_message || error.message; error = error.extra_message || error.message;
createErrorModal(tr("Failed to add client"), tr("Failed to add client to server group\n" + error)).open(); createErrorModal(tr("Failed to add client"), tra("Failed to add client to server group{:br:}", error)).open();
}); });
}).open(); }).open();
}); });

View File

@ -49,7 +49,6 @@ function compile(fileNames: string[], options: ts.CompilerOptions): void {
} }
const config = ts.parseCommandLine(process.argv.slice(2), file => readFileSync(file).toString()); const config = ts.parseCommandLine(process.argv.slice(2), file => readFileSync(file).toString());
console.dir(config);
if(config.errors && config.errors.length > 0) { if(config.errors && config.errors.length > 0) {
for(const error of config.errors) for(const error of config.errors)
console.log(error.messageText); console.log(error.messageText);

View File

@ -1,4 +1,3 @@
export interface TranslationEntry { export interface TranslationEntry {
filename: string; filename: string;
line: number; line: number;

View File

@ -8,8 +8,6 @@ import {isArray} from "util";
import * as mkdirp from "mkdirp"; import * as mkdirp from "mkdirp";
import {TranslationEntry} from "./generator"; import {TranslationEntry} from "./generator";
console.log("TR GEN!");
/* /*
const files = ["/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/build/trgen/test/test_01.ts"]; const files = ["/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/build/trgen/test/test_01.ts"];
files.forEach(file => { files.forEach(file => {

View File

@ -11,10 +11,14 @@ export function generate(file: ts.SourceFile, config: Configuration) : Translati
return result; return result;
} }
function report(node: ts.Node, message: string) { const source_location = (node: ts.Node) => {
const sf = node.getSourceFile(); const sf = node.getSourceFile();
let { line, character } = sf ? sf.getLineAndCharacterOfPosition(node.getStart()) : {line: -1, character: -1}; let { line, character } = sf ? sf.getLineAndCharacterOfPosition(node.getStart()) : {line: -1, character: -1};
console.log(`${(sf || {fileName: "unknown"}).fileName} (${line + 1},${character + 1}): ${message}`); return `${(sf || {fileName: "unknown"}).fileName} (${line + 1},${character + 1})`;
};
function report(node: ts.Node, message: string) {
console.log(`${source_location(node)}: ${message}`);
} }
function _generate(config: Configuration, node: ts.Node, result: TranslationEntry[]) { function _generate(config: Configuration, node: ts.Node, result: TranslationEntry[]) {
@ -27,7 +31,6 @@ function _generate(config: Configuration, node: ts.Node, result: TranslationEntr
if(call_name != "tr") break call_analize; if(call_name != "tr") break call_analize;
console.dir(call_name); console.dir(call_name);
console.log("Parameters: %o", call.arguments.length); console.log("Parameters: %o", call.arguments.length);
if(call.arguments.length > 1) { if(call.arguments.length > 1) {
report(call, "Invalid argument count"); report(call, "Invalid argument count");
@ -159,7 +162,7 @@ function create_unique_check(source_file: ts.SourceFile, variable: ts.Expression
return [...nodes, ts.createLabel(unique_check_label_name, ts.createBlock(blocked_nodes))]; return [...nodes, ts.createLabel(unique_check_label_name, ts.createBlock(blocked_nodes))];
} }
export function transform(config: Configuration, context: ts.TransformationContext, node: ts.SourceFile) : TransformResult { export function transform(config: Configuration, context: ts.TransformationContext, source_file: ts.SourceFile) : TransformResult {
const cache: VolatileTransformConfig = {} as any; const cache: VolatileTransformConfig = {} as any;
cache.translations = []; cache.translations = [];
@ -215,56 +218,59 @@ export function transform(config: Configuration, context: ts.TransformationConte
function visit(node: ts.Node): ts.Node { function visit(node: ts.Node): ts.Node {
node = ts.visitEachChild(node, visit, context); node = ts.visitEachChild(node, visit, context);
return replace_processor(config, cache, node); return replace_processor(config, cache, node, source_file);
} }
node = ts.visitNode(node, visit); source_file = ts.visitNode(source_file, visit);
extra_nodes.push(...create_unique_check(node, cache.nodes.translation_map_init, generated_names)); extra_nodes.push(...create_unique_check(source_file, cache.nodes.translation_map_init, generated_names));
node = ts.updateSourceFileNode(node, [...(extra_nodes as any[]), ...node.statements], node.isDeclarationFile, node.referencedFiles, node.typeReferenceDirectives, node.hasNoDefaultLib, node.referencedFiles); source_file = ts.updateSourceFileNode(source_file, [...(extra_nodes as any[]), ...source_file.statements], source_file.isDeclarationFile, source_file.referencedFiles, source_file.typeReferenceDirectives, source_file.hasNoDefaultLib, source_file.referencedFiles);
const result: TransformResult = {} as any; const result: TransformResult = {} as any;
result.node = node; result.node = source_file;
result.translations = cache.translations; result.translations = cache.translations;
return result; return result;
} }
export function replace_processor(config: Configuration, cache: VolatileTransformConfig, node: ts.Node) : ts.Node { export function replace_processor(config: Configuration, cache: VolatileTransformConfig, node: ts.Node, source_file: ts.SourceFile) : ts.Node {
if(config.verbose) if(config.verbose)
console.log("Process %s", SyntaxKind[node.kind]); console.log("Process %s", SyntaxKind[node.kind]);
if(ts.isCallExpression(node)) { if(ts.isCallExpression(node)) {
const call = <ts.CallExpression>node; const call = <ts.CallExpression>node;
const call_name = call.expression["escapedText"] as string; const call_name = call.expression["escapedText"] as string;
if(call_name != "tr") return node; if(call_name != "tr") return node;
if(!node.getSourceFile()) return node;
if(config.verbose) { if(config.verbose) {
console.dir(call_name); console.dir(call_name);
console.log("Parameters: %o", call.arguments.length); console.log("Parameters: %o", call.arguments.length);
} }
if(call.arguments.length > 1) {
report(call, "Invalid argument count"); if(call.arguments.length > 1)
throw new Error(source_location(call) + ": tr(...) has been called with an invalid arguments (" + (call.arguments.length === 0 ? "too few" : "too many") + ")");
const fullText = call.getFullText(source_file);
if(fullText && fullText.indexOf("@tr-ignore") !== -1)
return node; return node;
}
const object = <ts.StringLiteral>call.arguments[0]; const object = <ts.StringLiteral>call.arguments[0];
if(object.kind != SyntaxKind.StringLiteral) { if(object.kind != SyntaxKind.StringLiteral) {
report(call, "Invalid argument: " + SyntaxKind[object.kind]); if(call.getSourceFile())
return node; throw new Error(source_location(call) + ": Ignoring tr call because given argument isn't of type string literal. (" + SyntaxKind[object.kind] + ")");
report(call, "Ignoring tr call because given argument isn't of type string literal. (" + SyntaxKind[object.kind] + ")");
} }
if(config.verbose) if(config.verbose)
console.log("Message: %o", object.text || object.getText()); console.log("Message: %o", object.text || object.getText(source_file));
const variable_name = ts.createIdentifier(cache.name_generator(config, node, object.text || object.getText())); const variable_name = ts.createIdentifier(cache.name_generator(config, node, object.text || object.getText(source_file)));
const variable_init = ts.createPropertyAccess(cache.nodes.translation_map_init, variable_name); const variable_init = ts.createPropertyAccess(cache.nodes.translation_map_init, variable_name);
const variable = ts.createPropertyAccess(cache.nodes.translation_map, variable_name); const variable = ts.createPropertyAccess(cache.nodes.translation_map, variable_name);
const new_variable = ts.createAssignment(variable, call); const new_variable = ts.createAssignment(variable, call);
const source_file = node.getSourceFile(); let { line, character } = source_file.getLineAndCharacterOfPosition(node.getStart());
let { line, character } = source_file ? source_file.getLineAndCharacterOfPosition(node.getStart()) : {line: -1, character: -1};
cache.translations.push({ cache.translations.push({
message: object.text || object.getText(), message: object.text || object.getText(source_file),
line: line, line: line,
character: character, character: character,
filename: (source_file || {fileName: "unknown"}).fileName filename: (source_file || {fileName: "unknown"}).fileName

View File

@ -0,0 +1,67 @@
import * as ts from "typescript";
import * as ts_generator from "./ts_generator";
import * as path from "path";
import * as mkdirp from "mkdirp";
import {writeFileSync} from "fs";
import {TranslationEntry} from "./generator";
export interface Config {
target_file?: string;
verbose?: boolean;
}
let process_config: Config;
export default function(program: ts.Program, config?: Config) : (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile {
process_config = config as any || {};
const base_path = path.dirname(program.getCompilerOptions().project || program.getCurrentDirectory());
if(process_config.verbose) {
console.log("TRGen transformer called");
console.log("Base path: %s", base_path);
}
process.on('exit', function () {
if(!process_config.target_file) return;
const target = path.isAbsolute(process_config.target_file) ? process_config.target_file : path.join(base_path, process_config.target_file);
if(process_config.target_file) {
if(process_config.verbose)
console.log("Writing translation file to " + target);
mkdirp.sync(path.dirname(target));
writeFileSync(target, JSON.stringify(translations, null, 2));
}
});
return ctx => transformer(ctx) as any;
}
const translations: TranslationEntry[] = [];
const transformer = (context: ts.TransformationContext) =>
(rootNode: ts.Node) => {
const handler = (rootNode: ts.Node) => {
if(rootNode.kind == ts.SyntaxKind.Bundle) {
const bundle = rootNode as ts.Bundle;
const result = [];
for(const file of bundle.sourceFiles)
result.push(handler(file));
return ts.updateBundle(bundle, result as any, bundle.prepends as any);
} else if(rootNode.kind == ts.SyntaxKind.SourceFile) {
const file = rootNode as ts.SourceFile;
console.log("Processing " + file.fileName);
const result = ts_generator.transform({
use_window: false,
replace_cache: true
}, context, file);
translations.push(...result.translations);
return result.node;
} else {
console.warn("Invalid transform input: %s", ts.SyntaxKind[rootNode.kind]);
}
};
return handler(rootNode);
};

View File

@ -1,67 +1,9 @@
import * as ts from "typescript"; import transform, {Config} from "./ts_transformer";
import * as ts_generator from "./ts_generator";
import * as path from "path";
import * as mkdirp from "mkdirp";
import {PluginConfig} from "ttypescript/lib/PluginCreator"; import {PluginConfig} from "ttypescript/lib/PluginCreator";
import {writeFileSync} from "fs"; import * as ts from "typescript";
import {TranslationEntry} from "./generator";
interface Config {
target_file?: string;
verbose?: boolean;
}
//(program: ts.Program, config?: PluginConfig) => ts.TransformerFactory
let process_config: Config;
export default function(program: ts.Program, config?: PluginConfig) : (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile { export default function(program: ts.Program, config?: PluginConfig) : (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile {
process_config = config as any || {}; const process_config: Config = config as any || {};
const base_path = path.dirname(program.getCompilerOptions().project || program.getCurrentDirectory()); return transform(program, process_config);
if(process_config.verbose) { }
console.log("TRGen transformer called");
console.log("Base path: %s", base_path);
}
process.on('exit', function () {
const target = path.isAbsolute(process_config.target_file) ? process_config.target_file : path.join(base_path, process_config.target_file);
if(process_config.target_file) {
if(process_config.verbose)
console.log("Writing translation file to " + target);
mkdirp.sync(path.dirname(target));
writeFileSync(target, JSON.stringify(translations, null, 2));
}
});
return ctx => transformer(ctx) as any;
}
const translations: TranslationEntry[] = [];
const transformer = (context: ts.TransformationContext) =>
(rootNode: ts.Node) => {
const handler = (rootNode: ts.Node) => {
if(rootNode.kind == ts.SyntaxKind.Bundle) {
const bundle = rootNode as ts.Bundle;
const result = [];
for(const file of bundle.sourceFiles)
result.push(handler(file));
return ts.updateBundle(bundle, result as any, bundle.prepends as any);
} else if(rootNode.kind == ts.SyntaxKind.SourceFile) {
const file = rootNode as ts.SourceFile;
console.log("Processing " + file.fileName);
const result = ts_generator.transform({
use_window: false,
replace_cache: true
}, context, file);
translations.push(...result.translations);
return result.node;
} else {
console.warn("Invalid transform input: %s", ts.SyntaxKind[rootNode.kind]);
}
};
return handler(rootNode);
};

View File

@ -1,2 +0,0 @@
**/*.js
**/*.js.map

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Translation Manager</title>
</head>
<body>
<div>This needs some improvements</div>
</body>
</html>

View File

@ -1,19 +1,23 @@
import * as ts from "typescript";
import trtransformer, {Config} from "./tools/trgen/ts_transformer";
const path = require('path'); const path = require('path');
const webpack = require("webpack"); const webpack = require("webpack");
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const ManifestGenerator = require("./webpack/ManifestPlugin"); const ManifestGenerator = require("./webpack/ManifestPlugin");
const WorkerPlugin = require('worker-plugin'); const WorkerPlugin = require('worker-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const isDevelopment = process.env.NODE_ENV === 'development'; let isDevelopment = process.env.NODE_ENV === 'development';
isDevelopment = true;
module.exports = { module.exports = {
entry: { entry: {
//"shared-app": "./shared/js/main.ts"
"shared-app": "./web/js/index.ts" "shared-app": "./web/js/index.ts"
}, },
devtool: 'inline-source-map', devtool: isDevelopment ? "inline-source-map" : undefined,
mode: "development", mode: isDevelopment ? "development" : "production",
plugins: [ plugins: [
new CleanWebpackPlugin(), new CleanWebpackPlugin(),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
@ -34,8 +38,8 @@ module.exports = {
}) })
*/ */
new webpack.optimize.AggressiveSplittingPlugin({ new webpack.optimize.AggressiveSplittingPlugin({
minSize: 1024 * 128, minSize: 1024 * 8,
maxSize: 1024 * 1024 maxSize: 1024 * 128
}) })
], ],
module: { module: {
@ -43,8 +47,7 @@ module.exports = {
{ {
test: /\.s[ac]ss$/, test: /\.s[ac]ss$/,
loader: [ loader: [
//isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader, isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
'style-loader',
{ {
loader: 'css-loader', loader: 'css-loader',
options: { options: {
@ -68,8 +71,21 @@ module.exports = {
{ {
loader: 'ts-loader', loader: 'ts-loader',
options: { options: {
transpileOnly: true transpileOnly: true,
getCustomTransformers: (prog: ts.Program) => {
return {
before: [trtransformer(prog, {})]
};
}
} }
/*
{
"transform": "../../tools/trgen/ttsc_transformer.js",
"type": "program",
"target_file": "../generated/messages_script.json",
"verbose": true
}
*/
} }
] ]
}, },
@ -100,6 +116,8 @@ module.exports = {
publicPath: "js/" publicPath: "js/"
}, },
optimization: { optimization: {
splitChunks: { } splitChunks: { },
minimize: !isDevelopment,
minimizer: [new TerserPlugin()]
} }
}; };

View File

@ -2,7 +2,7 @@ import * as webpack from "webpack";
import {RawSourceMap} from "source-map"; import {RawSourceMap} from "source-map";
import LoaderContext = webpack.loader.LoaderContext; import LoaderContext = webpack.loader.LoaderContext;
const wabt = require("wabt"); const wabt = require("wabt")();
const filename = "module.wast"; const filename = "module.wast";
@ -10,9 +10,7 @@ export default function loader(this: LoaderContext, source: string | Buffer, sou
this.cacheable(); this.cacheable();
const module = wabt.parseWat(filename, source); const module = wabt.parseWat(filename, source);
const { buffer } = module.toBinary({ write_debug_names: true, relocatable: true, canonicalize_lebs: true, log: true }); const { buffer } = module.toBinary({ write_debug_names: false });
this.emitFile("test.wasm", buffer, null); this.callback(null, `module.exports = new Uint8Array([${buffer.join(",")}]);`);
const result = `module.exports = new Uint8Array([${buffer.join(",")}]);`;
this.callback(null, result);
} }