From f9fa5bb2bff49aa386fb77182cccc2983f1ceef2 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 1 Aug 2020 14:54:44 +0200 Subject: [PATCH] Updated the translation generate algorithm --- ChangeLog.md | 3 + shared/js/ui/frames/control-bar/index.tsx | 30 ++-- shared/js/ui/frames/side/ConversationUI.tsx | 2 +- .../js/ui/modal/ModalGroupPermissionCopy.tsx | 8 +- .../permission/ModalPermissionEditor.tsx | 4 +- .../ui/modal/permission/PermissionEditor.tsx | 6 +- shared/js/ui/modal/settings/Keymap.tsx | 14 +- shared/js/ui/modal/settings/Notifications.tsx | 2 +- shared/js/ui/react-elements/i18n/index.tsx | 2 +- shared/js/ui/view.tsx | 1 + tools/trgen/compiler.ts | 1 - tools/trgen/generator.ts | 2 + tools/trgen/index.ts | 14 +- tools/trgen/test/test_03.tsx | 7 + tools/trgen/ts_generator.ts | 155 ++++++++++++++---- tools/trgen/ts_transformer.ts | 1 - tools/trgen/tsconfig.json | 3 +- tools/trgen/ttsc_transformer.ts | 9 - webpack-client.config.ts | 7 +- webpack.config.ts | 16 +- 20 files changed, 185 insertions(+), 102 deletions(-) create mode 100644 tools/trgen/test/test_03.tsx delete mode 100644 tools/trgen/ttsc_transformer.ts diff --git a/ChangeLog.md b/ChangeLog.md index 16041d3c..ad8d8714 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,7 @@ # Changelog: +* **01.08.20** + - Cleaning up the channel trees selection on reset + * **25.07.20** - Fixed bug where icons could not be loaded due to cros policy diff --git a/shared/js/ui/frames/control-bar/index.tsx b/shared/js/ui/frames/control-bar/index.tsx index e8501fc7..3b797b2f 100644 --- a/shared/js/ui/frames/control-bar/index.tsx +++ b/shared/js/ui/frames/control-bar/index.tsx @@ -44,23 +44,23 @@ class ConnectButton extends ReactComponentBase<{ multiSession: boolean; event_re if(this.props.multiSession) { if(!this.state.connected) { subentries.push( - } + Connect to a server} onClick={ () => global_client_actions.fire("action_open_window_connect", {new_tab: false }) } /> ); } else { subentries.push( - } + Disconnect from current server} onClick={ () => this.props.event_registry.fire("action_disconnect", { globally: false }) }/> ); } if(this.state.connectedAnywhere) { subentries.push( - } + Disconnect from all servers} onClick={ () => this.props.event_registry.fire("action_disconnect", { globally: true }) }/> ); } subentries.push( - } + Connect to a server in another tab} onClick={ () => global_client_actions.fire("action_open_window_connect", { new_tab: true }) } /> ); } @@ -106,9 +106,9 @@ class BookmarkButton extends ReactComponentBase<{ event_registry: Registry); return ( @@ -188,25 +188,25 @@ class AwayButton extends ReactComponentBase<{ event_registry: Registry} + dropdowns.push(Go online} onClick={() => this.props.event_registry.fire("action_disable_away", { globally: false })} />); } else { - dropdowns.push(} + dropdowns.push(Set away on this server} onClick={() => this.props.event_registry.fire("action_set_away", { globally: false, prompt_reason: false })} />); } - dropdowns.push(} + dropdowns.push(Set away message on this server} onClick={() => this.props.event_registry.fire("action_set_away", { globally: false, prompt_reason: true })} />); dropdowns.push(
); if(this.state.awayAnywhere) { - dropdowns.push(} + dropdowns.push(Go online for all servers} onClick={() => this.props.event_registry.fire("action_disable_away", { globally: true })} />); } if(!this.state.awayAll) { - dropdowns.push(} + dropdowns.push(Set away on all servers} onClick={() => this.props.event_registry.fire("action_set_away", { globally: true, prompt_reason: false })} />); } - dropdowns.push(} + dropdowns.push(Set away message for all servers} onClick={() => this.props.event_registry.fire("action_set_away", { globally: true, prompt_reason: true })} />); /* switchable because we're switching it manually */ @@ -323,16 +323,16 @@ class QueryButton extends ReactComponentBase<{ event_registry: Registry} + toggle = Hide server queries} onClick={() => this.props.event_registry.fire("action_toggle_query", { shown: false })}/>; else - toggle = } + toggle = Show server queries} onClick={() => this.props.event_registry.fire("action_toggle_query", { shown: true })}/>; return ( ) diff --git a/shared/js/ui/frames/side/ConversationUI.tsx b/shared/js/ui/frames/side/ConversationUI.tsx index 28018c8b..eb2a6f97 100644 --- a/shared/js/ui/frames/side/ConversationUI.tsx +++ b/shared/js/ui/frames/side/ConversationUI.tsx @@ -481,7 +481,7 @@ class ConversationMessages extends React.PureComponent You don't have permissions to participate in this conversation!
- {this.state.failedPermission}
+ >{this.state.failedPermission} ); break; diff --git a/shared/js/ui/modal/ModalGroupPermissionCopy.tsx b/shared/js/ui/modal/ModalGroupPermissionCopy.tsx index 4b34a871..f7c25ed4 100644 --- a/shared/js/ui/modal/ModalGroupPermissionCopy.tsx +++ b/shared/js/ui/modal/ModalGroupPermissionCopy.tsx @@ -44,7 +44,7 @@ export interface GroupPermissionCopyModalEvents { notify_destroy: {} } -const GroupSelector = (props: { events: Registry, defaultGroup: number, updateEvent: "action_set_source" | "action_set_target", label: string, className: string}) => { +const GroupSelector = (props: { events: Registry, defaultGroup: number, updateEvent: "action_set_source" | "action_set_target", label: React.ReactElement, className: string}) => { const [ selectedGroup, setSelectedGroup ] = useState(undefined); const [ permissions, setPermissions ] = useState<"loading" | { createTemplate, createQuery }>("loading"); const [ exitingGroups, setExitingGroups ] = useState<"loading" | GroupInfo[]>("loading"); @@ -72,7 +72,7 @@ const GroupSelector = (props: { events: Registry return ( {props.label}} + label={props.label} className={props.className} disabled={isLoading} value={isLoading || selectedGroup === undefined ? "-1" : selectedGroup.toString()} @@ -146,8 +146,8 @@ class ModalGroupPermissionCopy extends Modal { renderBody() { return
- - + Source group} className={cssStyle.sourceGroup} /> + Target group} className={cssStyle.targetGroup} />
diff --git a/shared/js/ui/modal/permission/ModalPermissionEditor.tsx b/shared/js/ui/modal/permission/ModalPermissionEditor.tsx index 1d214ba1..d516eefc 100644 --- a/shared/js/ui/modal/permission/ModalPermissionEditor.tsx +++ b/shared/js/ui/modal/permission/ModalPermissionEditor.tsx @@ -238,7 +238,7 @@ const ActiveTabInfo = (props: { events: Registry }) => { return @@ -251,7 +251,7 @@ const TabSelectorEntry = (props: { events: Registry, entr return
!active && props.events.fire("action_activate_tab", { tab: props.entry })}> - {PermissionTabName[props.entry].translated} + {PermissionTabName[props.entry].translated}
; }; diff --git a/shared/js/ui/modal/permission/PermissionEditor.tsx b/shared/js/ui/modal/permission/PermissionEditor.tsx index fbf60612..c344be61 100644 --- a/shared/js/ui/modal/permission/PermissionEditor.tsx +++ b/shared/js/ui/modal/permission/PermissionEditor.tsx @@ -204,7 +204,7 @@ const ClientListButton = (props: { events: Registry }) = className={cssStyle.clients + " " + (visible ? "" : cssStyle.hidden)} color={"green"} onClick={() => props.events.fire("action_toggle_client_list", { visible: !toggled })}> - {toggled ? "Hide clients in group" : "Show clients in group"} + {toggled ? Hide clients in group : Show clients in group} }; @@ -643,7 +643,9 @@ const PermissionGroupRow = (props: { events: Registry, g >
props.events.fire("action_toggle_group", { collapsed: !collapsed, groupId: props.group.groupId })} /> -
{props.group.groupName}
+
+ {props.group.groupName} +
diff --git a/shared/js/ui/modal/settings/Keymap.tsx b/shared/js/ui/modal/settings/Keymap.tsx index 0917e39f..5a8b8773 100644 --- a/shared/js/ui/modal/settings/Keymap.tsx +++ b/shared/js/ui/modal/settings/Keymap.tsx @@ -77,15 +77,15 @@ class KeyActionEntry extends ReactComponentBase
; + rightItem =
loading...
; } else if(this.state.state === "applying") { - rightItem =
; + rightItem =
applying...
; } else if(this.state.state === "loaded") { rightItem = null; if(this.state.assignedKey) rightItem =
{ppt.key_description(this.state.assignedKey)}
; } else { - rightItem =
; + rightItem =
{this.state.error || "unknown error"}
; } return (
this.onContextMenu(e)} > - + {this.props.description} {rightItem}
); @@ -204,7 +204,7 @@ class KeyActionGroup extends ReactComponentBase this.toggleCollapsed()}> ); result.push(...Object.keys(KeyTypes).filter(e => KeyTypes[e].category === this.props.id).map(e => ( @@ -264,7 +264,7 @@ class ButtonBar extends ReactComponentBase<{ event_registry: Registry
); @@ -304,7 +304,7 @@ export const KeyMapSettings = () => { return (<>
- + Keymap
diff --git a/shared/js/ui/modal/settings/Notifications.tsx b/shared/js/ui/modal/settings/Notifications.tsx index 1bc5b30b..b18c86fc 100644 --- a/shared/js/ui/modal/settings/Notifications.tsx +++ b/shared/js/ui/modal/settings/Notifications.tsx @@ -300,7 +300,7 @@ export const NotificationSettings = () => { return (<>
diff --git a/shared/js/ui/react-elements/i18n/index.tsx b/shared/js/ui/react-elements/i18n/index.tsx index 4e7f620a..074ef8f3 100644 --- a/shared/js/ui/react-elements/i18n/index.tsx +++ b/shared/js/ui/react-elements/i18n/index.tsx @@ -3,7 +3,7 @@ import {parseMessageWithArguments} from "tc-shared/ui/frames/chat"; import {cloneElement} from "react"; let instances = []; -export class Translatable extends React.Component<{ message: string, children?: never } | { children: string }, { translated: string }> { +export class Translatable extends React.Component<{ children: string, __cacheKey?: string, trIgnore?: boolean }, { translated: string }> { constructor(props) { super(props); diff --git a/shared/js/ui/view.tsx b/shared/js/ui/view.tsx index e1669a2a..fe88577c 100644 --- a/shared/js/ui/view.tsx +++ b/shared/js/ui/view.tsx @@ -842,6 +842,7 @@ export class ChannelTree { reset() { batch_updates(BatchUpdateType.CHANNEL_TREE); + this.selection.clear_selection(); try { this.selection.reset(); diff --git a/tools/trgen/compiler.ts b/tools/trgen/compiler.ts index ef2f438f..ae2c5cfa 100644 --- a/tools/trgen/compiler.ts +++ b/tools/trgen/compiler.ts @@ -17,7 +17,6 @@ const transformer = (context: ts.TransformationContext) => (r function compile(fileNames: string[], options: ts.CompilerOptions): void { const program: ts.Program = ts.createProgram(fileNames, options); - //(context: TransformationContext) => Transformer; let emitResult = program.emit(undefined, undefined, undefined, undefined, { before: [ transformer ] }); diff --git a/tools/trgen/generator.ts b/tools/trgen/generator.ts index 71cab0b7..fe401c70 100644 --- a/tools/trgen/generator.ts +++ b/tools/trgen/generator.ts @@ -4,4 +4,6 @@ export interface TranslationEntry { character: number; message: string; + + type: "call" | "jsx-translatable" | "js-template"; } \ No newline at end of file diff --git a/tools/trgen/index.ts b/tools/trgen/index.ts index db395c99..7ec42a7a 100644 --- a/tools/trgen/index.ts +++ b/tools/trgen/index.ts @@ -99,6 +99,7 @@ const translations: TranslationEntry[] = []; config.source_files.forEach(file => { if(config.verbose) console.log("iterating over %s (%s)", file, path.resolve(path.normalize(config.base_bath + file))); + glob.sync(config.base_bath + file).forEach(_file => { _file = path.normalize(_file); for(const n_file of negate_files) { @@ -109,28 +110,17 @@ config.source_files.forEach(file => { } const file_type = path.extname(_file); - if(file_type == ".ts") { + if(file_type == ".ts" || file_type == ".tsx") { let source = ts.createSourceFile( _file, readFileSync(_file).toString(), ts.ScriptTarget.ES2016, true ); - console.log(print(source)); - console.log("Compile " + _file); const messages = ts_generator.generate(source, {}); translations.push(...messages); - - /* - messages.forEach(message => { - console.log(message); - }); - - console.log("PRINT!"); - console.log(print(source)); - */ } else if(file_type == ".html") { const messages = jsrender_generator.generate({}, { content: readFileSync(_file).toString(), diff --git a/tools/trgen/test/test_03.tsx b/tools/trgen/test/test_03.tsx new file mode 100644 index 00000000..506661a1 --- /dev/null +++ b/tools/trgen/test/test_03.tsx @@ -0,0 +1,7 @@ +import {Translatable} from "../../../shared/js/ui/react-elements/i18n"; +import * as React from "react"; + +function test() { + const element_0 = Hello World; + const element_1 = {"Hello World"}; +} \ No newline at end of file diff --git a/tools/trgen/ts_generator.ts b/tools/trgen/ts_generator.ts index c65f6d79..e6e89bf0 100644 --- a/tools/trgen/ts_generator.ts +++ b/tools/trgen/ts_generator.ts @@ -1,6 +1,6 @@ import * as ts from "typescript"; -import * as sha256 from "sha256"; import {SyntaxKind} from "typescript"; +import * as sha256 from "sha256"; import {TranslationEntry} from "./generator"; export function generate(file: ts.SourceFile, config: Configuration) : TranslationEntry[] { @@ -26,23 +26,24 @@ function _generate(config: Configuration, node: ts.Node, result: TranslationEntr call_analize: if(ts.isCallExpression(node)) { - const call = node; + const call = node as ts.CallExpression; const call_name = call.expression["escapedText"] as string; - if(call_name != "tr") break call_analize; + + if(call_name != "tr") { + break call_analize; + } console.dir(call_name); console.log("Parameters: %o", call.arguments.length); if(call.arguments.length > 1) { report(call, "Invalid argument count"); - node.forEachChild(n => _generate(config, n, result)); - return; + break call_analize; } const object = call.arguments[0]; if(object.kind != SyntaxKind.StringLiteral) { report(call, "Invalid argument: " + SyntaxKind[object.kind]); - node.forEachChild(n => _generate(config, n, result)); - return; + break call_analize; } console.log("Message: %o", object.text); @@ -58,13 +59,43 @@ function _generate(config: Configuration, node: ts.Node, result: TranslationEntr filename: node.getSourceFile().fileName, line: line, character: character, - message: object.text + message: object.text, + type: "call" + }); + } else if(node.kind === SyntaxKind.JsxElement) { + const element = node as ts.JsxElement; + const tag = element.openingElement.tagName as ts.Identifier; + + if(tag.kind !== SyntaxKind.Identifier) + break call_analize; + + if(tag.escapedText !== "Translatable") + break call_analize; + + if(element.children.length !== 1) { + report(element, "Invalid child count: " + element.children.length); + break call_analize; + } + + const text = element.children[0] as ts.JsxText; + if(text.kind != SyntaxKind.JsxText) { + report(element, "Invalid child type " + SyntaxKind[text.kind]); + break call_analize; + } + + const { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()); + result.push({ + filename: node.getSourceFile().fileName, + line: line, + character: character, + message: text.text, + type: "jsx-translatable" }); } node.forEachChild(n => _generate(config, n, result)); } -function create_unique_check(config: Configuration, source_file: ts.SourceFile, variable: ts.Expression, variables: { name: string, node: ts.Node }[]) : ts.Node[] { +function generateUniqueCheck(config: Configuration, source_file: ts.SourceFile, variable: ts.Expression, variables: { name: string, node: ts.Node }[]) : ts.Node[] { const nodes: ts.Node[] = [], blocked_nodes: ts.Statement[] = []; const node_path = (node: ts.Node) => { @@ -162,6 +193,7 @@ function create_unique_check(config: Configuration, source_file: ts.SourceFile, return [...nodes, ts.createLabel(unique_check_label_name, ts.createBlock(blocked_nodes))]; } +let globalIdIndex = 0, globalIdTimestamp = Date.now(); export function transform(config: Configuration, context: ts.TransformationContext, source_file: ts.SourceFile) : TransformResult { const cache: VolatileTransformConfig = {} as any; cache.translations = []; @@ -207,32 +239,25 @@ export function transform(config: Configuration, context: ts.TransformationConte } } - const used_names = [config.variables.declarations, config.variables.declare_files]; const generated_names: { name: string, node: ts.Node }[] = []; let generator_base = 0; + + const generate_unique_name = config => { + if(config.module) { + return "_" + generator_base++; + } else { + return "_" + globalIdTimestamp + "-" + ++globalIdIndex; + } + }; + cache.name_generator = (config, node, message) => { - const characters = "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - let name; - do { - name = ""; - - if(config.module) { - name = "_" + generator_base++; - } else { - /* Global namespace. We've to generate a random name so no duplicates happen */ - while(name.length < 8) { - const char = characters[Math.floor(Math.random() * characters.length)]; - name = name + char; - if(name[0] >= '0' && name[0] <= '9') - name = name.substr(1) || ""; - } - } - } while(used_names.findIndex(e => e === name) !== -1); - + const name = generate_unique_name(config); generated_names.push({name: name, node: node}); return name; }; + cache.tsx_name_generator = generate_unique_name; + function visit(node: ts.Node): ts.Node { node = ts.visitEachChild(node, visit, context); return replace_processor(config, cache, node, source_file); @@ -240,7 +265,7 @@ export function transform(config: Configuration, context: ts.TransformationConte source_file = ts.visitNode(source_file, visit); if(!config.module) { /* we don't need a unique check because we're just in our scope */ - extra_nodes.push(...create_unique_check(config, source_file, cache.nodes.translation_map, generated_names)); + extra_nodes.push(...generateUniqueCheck(config, source_file, cache.nodes.translation_map, generated_names)); } 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); @@ -254,6 +279,7 @@ export function transform(config: Configuration, context: ts.TransformationConte export function replace_processor(config: Configuration, cache: VolatileTransformConfig, node: ts.Node, source_file: ts.SourceFile) : ts.Node { if(config.verbose) console.log("Process %s", SyntaxKind[node.kind]); + if(ts.isCallExpression(node)) { const call = node; const call_name = call.expression["escapedText"] as string; @@ -293,11 +319,79 @@ export function replace_processor(config: Configuration, cache: VolatileTransfor message: object.text || object.getText(source_file), line: line, character: character, - filename: (source_file || {fileName: "unknown"}).fileName + filename: (source_file || {fileName: "unknown"}).fileName, + type: "call" }); return ts.createBinary(variable_init, ts.SyntaxKind.BarBarToken, new_variable); + } else if(node.kind === SyntaxKind.JsxElement) { + const element = node as ts.JsxElement; + const tag = element.openingElement.tagName as ts.Identifier; + + if(tag.kind !== SyntaxKind.Identifier) + return node; + + /* TODO: VariadicTranslatable */ + if(tag.escapedText === "Translatable") { + const properties = {} as any; + + element.openingElement.attributes.properties.forEach((e: ts.JsxAttribute) => { + if(e.kind !== SyntaxKind.JsxAttribute) + throw new Error(source_location(e) + ": Invalid jsx attribute kind " + SyntaxKind[e.kind]); + + if(e.name.kind !== SyntaxKind.Identifier) + throw new Error(source_location(e) + ": Key isn't an identifier"); + + properties[e.name.escapedText as string] = e.initializer; + }); + + if('trIgnore' in properties && properties.trIgnore.kind === SyntaxKind.JsxExpression) { + const ignoreAttribute = properties.trIgnore as ts.JsxExpression; + if(ignoreAttribute.expression.kind === SyntaxKind.TrueKeyword) + return node; + else if(ignoreAttribute.expression.kind !== SyntaxKind.FalseKeyword) + throw new Error(source_location(ignoreAttribute) + ": Invalid attribute value of type " + SyntaxKind[ignoreAttribute.expression.kind]); + } + + if(element.children.length !== 1) + throw new Error(source_location(element) + ": Element has been called with an invalid arguments (" + (element.children.length === 0 ? "too few" : "too many") + ")"); + + const text = element.children[0] as ts.JsxText; + if(text.kind != SyntaxKind.JsxText) + throw new Error(source_location(element) + ": Element has invalid children. Expected JsxText but got " + SyntaxKind[text.kind]); + + let { line, character } = source_file.getLineAndCharacterOfPosition(node.getStart()); + cache.translations.push({ + message: text.text, + line: line, + character: character, + filename: (source_file || {fileName: "unknown"}).fileName, + type: "jsx-translatable" + }); + + /* + console.error( ts.updateJsxAttributes(element.openingElement.attributes, [ + ...element.openingElement.attributes.properties, + ts.createJsxAttribute(ts.createIdentifier("__cacheKey"), ts.createStringLiteral(cache.tsx_name_generator(config))) + ])); + */ + return ts.updateJsxElement( + element, + ts.updateJsxOpeningElement( + element.openingElement, + element.openingElement.tagName, + element.openingElement.typeArguments, + ts.updateJsxAttributes(element.openingElement.attributes, [ + ...element.openingElement.attributes.properties, + ts.createJsxAttribute(ts.createIdentifier("__cacheKey"), ts.createStringLiteral(cache.tsx_name_generator(config))) + ]) + ), + element.children, + element.closingElement + ); + } } + return node; } export interface Configuration { @@ -326,5 +420,6 @@ interface VolatileTransformConfig { }; name_generator: (config: Configuration, node: ts.Node, message: string) => string; + tsx_name_generator: (config: Configuration) => string; translations: TranslationEntry[]; } \ No newline at end of file diff --git a/tools/trgen/ts_transformer.ts b/tools/trgen/ts_transformer.ts index 8b2fed37..711c669c 100644 --- a/tools/trgen/ts_transformer.ts +++ b/tools/trgen/ts_transformer.ts @@ -49,7 +49,6 @@ const transformer = (context: ts.TransformationContext) => 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; diff --git a/tools/trgen/tsconfig.json b/tools/trgen/tsconfig.json index 369ed267..0229e46b 100644 --- a/tools/trgen/tsconfig.json +++ b/tools/trgen/tsconfig.json @@ -13,7 +13,6 @@ "index.ts", "compiler.ts", "jsrender_generator.ts", - "ts_generator.ts", - //"ttsc_transformer.ts" + "ts_generator.ts" ] } \ No newline at end of file diff --git a/tools/trgen/ttsc_transformer.ts b/tools/trgen/ttsc_transformer.ts deleted file mode 100644 index 4885dd05..00000000 --- a/tools/trgen/ttsc_transformer.ts +++ /dev/null @@ -1,9 +0,0 @@ -import transform, {Config} from "./ts_transformer"; -import {PluginConfig} from "ttypescript/lib/PluginCreator"; -import * as ts from "typescript"; - -export default function(program: ts.Program, config?: PluginConfig) : (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile { - const process_config: Config = config as any || {}; - - return transform(program, process_config); -} \ No newline at end of file diff --git a/webpack-client.config.ts b/webpack-client.config.ts index fd47a568..83463bcc 100644 --- a/webpack-client.config.ts +++ b/webpack-client.config.ts @@ -12,10 +12,13 @@ export = () => config_base.config("client").then(config => { "tc-backend": path.resolve(__dirname, "shared/backend.d"), }); - config.externals.push((context, request: string, callback) => { + if(!Array.isArray(config.externals)) + throw "invalid config"; + + config.externals.push((context, request, callback) => { if (request.startsWith("tc-backend/")) return callback(null, `window["backend-loader"].require("${request}")`); - callback(); + callback(undefined, undefined); }); config.externals.push({ "jquery": "window.$" }); diff --git a/webpack.config.ts b/webpack.config.ts index 27ce4147..9f23ea71 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -55,7 +55,7 @@ const isLoaderFile = (file: string) => { return false; }; -export const config = async (target: "web" | "client") => { return { +export const config = async (target: "web" | "client"): Promise => { return { entry: { "loader": "./loader/app/index.ts", "modal-external": "./shared/js/ui/react-elements/external-modal/PopoutEntrypoint.ts", @@ -75,15 +75,7 @@ export const config = async (target: "web" | "client") => { return { base: __dirname }), new WorkerPlugin(), - //new BundleAnalyzerPlugin() - /* - new CircularDependencyPlugin({ - //exclude: /a\.js|node_modules/, - failOnError: true, - allowAsyncCycles: false, - cwd: process.cwd(), - }) - */ + //new BundleAnalyzerPlugin(), isDevelopment ? undefined : new webpack.optimize.AggressiveSplittingPlugin({ minSize: 1024 * 8, maxSize: 1024 * 128 @@ -138,7 +130,7 @@ export const config = async (target: "web" | "client") => { return { options: { context: __dirname, colors: true, - getCustomTransformers(prog: ts.Program) { + getCustomTransformers: (prog: ts.Program) => { return { before: [trtransformer(prog, { optimized: false, @@ -197,7 +189,7 @@ export const config = async (target: "web" | "client") => { return { }, externals: [ {"tc-loader": "window loader"} - ] as any[], + ], output: { filename: isDevelopment ? "[name].[contenthash].js" : "[contenthash].js", chunkFilename: isDevelopment ? "[name].[contenthash].js" : "[contenthash].js",