diff --git a/CHANGELOG.md b/CHANGELOG.md
index a62cd4ea..f9c17529 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
English | [简体中文](./CHANGELOG_CN.md)
+## 3.12.1 (2022-02-25)
+
+- `Fix(Core)` Fix bug that `VConsole.instance` is empty when VConsole `import` as a new module.
+- `Chore(Core)` Fix type declaration errors caused by vendors.
+
+
## 3.12.0 (2022-02-17)
- `Feat(Core)` Add new static property `VConsole.instance` to get the singleton instance.
diff --git a/CHANGELOG_CN.md b/CHANGELOG_CN.md
index 6979cf06..ce50f159 100644
--- a/CHANGELOG_CN.md
+++ b/CHANGELOG_CN.md
@@ -1,5 +1,11 @@
[English](./CHANGELOG.md) | 简体中文
+## 3.12.1 (2022-02-25)
+
+- `Fix(Core)` 修复当 VConsole 作为新模块 `import` 时 `VConsole.instance` 为空的问题。
+- `Chore(Core)` 修复由外部依赖库引起的 TypeScript 类型声明错误问题。
+
+
## 3.12.0 (2022-02-17)
- `Feat(Core)` 新增静态属性 `VConsole.instance` 以获取实例化后的单例 vConsole 对象。
diff --git a/build/build.typings.js b/build/build.typings.js
new file mode 100644
index 00000000..69861e29
--- /dev/null
+++ b/build/build.typings.js
@@ -0,0 +1,21 @@
+const fs = require('fs');
+const { execSync } = require('child_process');
+const vendorConfig = require('./vendor.json');
+
+const main = () => {
+ console.group('\nEmitting type declarations...');
+ const distFile = './dist/vconsole.min.d.ts';
+ if (fs.existsSync(distFile)) {
+ fs.unlinkSync(distFile);
+ }
+ execSync('tsc --build ./tsconfig.type.json');
+ let distContent = fs.readFileSync(distFile, 'utf8');
+ for (const name of vendorConfig.name) {
+ distContent = distContent.replace(new RegExp(`['"]${name}['"]`, 'g'), `"vendor/${name}"`);
+ }
+ const vendorContent = '/// \n\n';
+ fs.writeFileSync(distFile, vendorContent + distContent, 'utf8');
+ console.groupEnd();
+};
+
+main();
\ No newline at end of file
diff --git a/build/vendor.d.ts b/build/vendor.d.ts
new file mode 100644
index 00000000..9b948616
--- /dev/null
+++ b/build/vendor.d.ts
@@ -0,0 +1,24 @@
+declare module 'vendor/core-js/stable/symbol' {
+}
+
+declare module 'vendor/mutation-observer' {
+ export class MutationObserver {
+ }
+}
+
+declare module 'vendor/svelte' {
+ export class SvelteComponent {
+ }
+}
+
+declare module 'vendor/svelte/store' {
+ export interface Subscriber {
+ }
+ export interface Unsubscriber {
+ }
+ export interface Updater {
+ }
+ export interface Writable {
+ }
+}
+
diff --git a/build/vendor.json b/build/vendor.json
new file mode 100644
index 00000000..96afe665
--- /dev/null
+++ b/build/vendor.json
@@ -0,0 +1,8 @@
+{
+ "name": [
+ "core-js/stable/symbol",
+ "mutation-observer",
+ "svelte/store",
+ "svelte"
+ ]
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 17eb2ece..7056e8cf 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,11 @@
{
"name": "vconsole",
- "version": "3.12.0",
+ "version": "3.12.1",
"description": "A lightweight, extendable front-end developer tool for mobile web page.",
"homepage": "https://github.com/Tencent/vConsole",
"files": [
"dist/*",
+ "build/vendor.d.ts",
"CHANGELOG*",
"README*"
],
@@ -12,7 +13,7 @@
"typings": "dist/vconsole.min.d.ts",
"scripts": {
"build": "webpack --mode=production --progress",
- "build:typings": "tsc --build tsconfig.type.json",
+ "build:typings": "node ./build/build.typings.js",
"build:dev": "webpack --mode=development --progress",
"watch": "webpack --mode=development --watch --progress",
"serve": "webpack serve --config webpack.serve.config --progress",
diff --git a/src/core/core.ts b/src/core/core.ts
index 3b1a7a52..9e18fcdb 100644
--- a/src/core/core.ts
+++ b/src/core/core.ts
@@ -53,9 +53,6 @@ export class VConsole {
public system: VConsoleLogExporter;
public network: VConsoleNetworkExporter;
- // Singleton instance
- public static instance: VConsole;
-
// Export static classes
public static VConsolePlugin = VConsolePlugin;
public static VConsoleLogPlugin = VConsoleLogPlugin;
@@ -71,7 +68,6 @@ export class VConsole {
return VConsole.instance;
}
- VConsole.instance = this;
this.isInited = false;
this.option = {
defaultPlugins: ['system', 'network', 'element', 'storage'],
@@ -132,6 +128,29 @@ export class VConsole {
}
}
+ /**
+ * Get singleton instance.
+ **/
+ public static get instance() {
+ return ($.one(VCONSOLE_ID))?.__VCONSOLE_INSTANCE as VConsole;
+ }
+
+ /**
+ * Set singleton instance.
+ **/
+ public static set instance(value: VConsole | undefined) {
+ if (value !== undefined && !(value instanceof VConsole)) {
+ console.debug('[vConsole] Cannot set `VConsole.instance` because the value is not the instance of VConsole.');
+ return;
+ }
+ const $elm = $.one(VCONSOLE_ID);
+ if ($elm) {
+ ($elm).__VCONSOLE_INSTANCE = value;
+ } else {
+ console.debug('[vConsole] Cannot set `VConsole.instance` because vConsole has not finished initializing yet.');
+ }
+ }
+
/**
* Add built-in plugins.
*/
@@ -199,6 +218,9 @@ export class VConsole {
const pluginId = e.detail.pluginId;
this.showPlugin(pluginId);
});
+
+ // bind vConsole instance
+ VConsole.instance = this;
}
// set options into component
@@ -497,6 +519,10 @@ export class VConsole {
if (!this.isInited) {
return;
}
+ // reverse isInited when destroyed
+ this.isInited = false;
+ VConsole.instance = undefined;
+
// remove plugins
const pluginIds = Object.keys(this.pluginList);
for (let i = pluginIds.length - 1; i >= 0; i--) {
@@ -504,10 +530,6 @@ export class VConsole {
}
// remove component
this.compInstance.$destroy();
-
- // reverse isInited when destroyed
- this.isInited = false;
- VConsole.instance = undefined;
}
} // END class
diff --git a/src/lib/mito.ts b/src/lib/mito.ts
deleted file mode 100644
index 2db4f418..00000000
--- a/src/lib/mito.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * Mito.js
- * A simple template engine
- *
- * @author Maiz
- */
-
-export default class Mito {
- /**
- * Render `tpl` with `data` into a HTML string.
- */
- public render(tpl: string, data: any, toString: T): string;
- /**
- * Render `tpl` with `data` into a HTML element.
- */
- public render(tpl: string, data: any, toString?: T): Element;
- public render(tpl: string, data: any, toString?: T) {
- const pattern = /\{\{([^\}]+)\}\}/g;
- let code = '';
- let codeWrap = '';
- let pointer = 0;
- let match: RegExpExecArray;
- const RenderFunction = {
- // Escape HTML to XSS-safe text
- text: (text: string | number) => {
- if (typeof text !== 'string' && typeof text !== 'number') { return text; }
- return String(text).replace(/[<>&" ]/g, (c) => {
- return { '<': '<', '>': '>', '&': '&', '"': '"', ' ': ' ' }[c];
- });
- },
- // Change invisible characters to visible characters
- visibleText: (text: string) => {
- if (typeof text !== 'string') { return text; }
- return String(text).replace(/[\n\t]/g, (c) => {
- return { '\n': '\\n', '\t': '\\t' }[c];
- });
- },
- };
- const addCode = (line: string, isJS: boolean) => {
- if (line === '') { return; }
- // console.log(line)
- if (isJS) {
- if ( line.match(/^ ?else/g) ) {
- // else --> } else {
- code += '} ' + line + ' {\n';
- } else if ( line.match(/\/(if|for|switch)/g) ) {
- // /if --> }
- code += '}\n';
- } else if ( line.match(/^ ?if|for|switch/g) ) {
- // if (age) --> if (this.age) {
- code += line + ' {\n';
- } else if ( line.match(/^ ?(break|continue) ?$/g) ) {
- // break --> break;
- code += line + ';\n';
- } else if ( line.match(/^ ?(case|default)/g) ) {
- // case (1) --> case (1):
- code += line + ':\n';
- } else {
- // name --> name
- code += 'arr.push(String('+ line +'));\n';
- }
- } else {
- // plain text
- code += 'arr.push("' + line.replace(/"/g, '\\"' )+ '");\n';
- }
- };
- // init global param
- (window).__mito_data = data;
- (window).__mito_code = "";
- (window).__mito_result = "";
- // remove spaces after switch
- tpl = tpl.replace(/(\{\{ ?switch(.+?)\}\})[\r\n\t ]+\{\{/g, '$1{{');
- // line breaks
- tpl = tpl.replace(/^[\r\n]/, '').replace(/\n/g, '\\\n').replace(/\r/g, '\\\r');
- // init code
- codeWrap = '(function(){\n';
- code = 'var arr = [];\n';
- // renderFunctions
- for (let fn in RenderFunction) {
- code += `var ${fn} = ${RenderFunction[fn].toString()};\n`;
- }
- while (match = pattern.exec(tpl)) {
- addCode( tpl.slice(pointer, match.index), false );
- addCode( match[1], true );
- pointer = match.index + match[0].length;
- }
- addCode( tpl.substr(pointer, tpl.length - pointer), false );
- code += '__mito_result = arr.join("");';
- code = 'with (__mito_data) {\n' + code + '\n}';
- codeWrap += code;
- codeWrap += '})();';
- // console.log("code:\n"+codeWrap);
- // run code, do NOT use `eval` or `new Function` to avoid `unsafe-eval` CSP rule
- const scriptList = document.getElementsByTagName('script');
- let nonce = '';
- // find the first script with nonce
- for (let i = 0; i < scriptList.length; i++) {
- if (scriptList[i].nonce) {
- nonce = scriptList[i].nonce
- break
- }
- }
-
- const script = document.createElement('SCRIPT');
- script.innerHTML = codeWrap;
- script.setAttribute('nonce', nonce);
- document.documentElement.appendChild(script);
- const domString = (window).__mito_result;
- document.documentElement.removeChild(script);
- if (!toString) {
- const e = document.createElement('DIV');
- e.innerHTML = domString;
- return e.children[0];
- }
- return domString;
- }
-}
diff --git a/tsconfig.json b/tsconfig.json
index 3fd7d99c..f831bdfd 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -16,5 +16,5 @@
},
},
"include": ["src/**/*"],
- "exclude": ["node_modules/*"],
+ "exclude": ["build/vendor.d.ts", "node_modules/*"],
}
\ No newline at end of file
diff --git a/tsconfig.type.json b/tsconfig.type.json
index 40bbddfe..ddb39251 100644
--- a/tsconfig.type.json
+++ b/tsconfig.type.json
@@ -4,7 +4,7 @@
"declaration": true,
// "declarationDir": "./dist/typings",
"outFile": "dist/vconsole.min.d.ts",
- "outDir": "./dist/typings",
+ "outDir": "./dist",
"baseUrl": "./src",
"rootDir": "./src",
"moduleResolution": "node",
diff --git a/webpack.config.js b/webpack.config.js
index 5998325c..3422f54f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -131,9 +131,7 @@ module.exports = (env, argv) => {
apply: (compiler) => {
compiler.hooks.done.tap('DeclarationEmitter', () => {
if (isDev) return; // only emit declarations in prod mode
- console.group('Emitting type declarations...');
execSync('npm run build:typings');
- console.groupEnd();
});
},
},