支持 template 模板 list 模式

This commit is contained in:
muwoo 2021-12-17 17:47:51 +08:00
parent afca4f2b5a
commit 8bcc5d409c
30 changed files with 13784 additions and 28 deletions

View File

@ -1,6 +1,6 @@
{
"name": "rubick",
"version": "2.0.1-beta.1",
"version": "2.0.1-beta.2",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",

View File

@ -0,0 +1 @@
*{margin:0;padding:0}.options{position:absolute;left:0;width:100%;z-index:99;max-height:100vh;overflow:auto}.options::-webkit-scrollbar{width:0}.op-item{padding:0 10px;height:60px;max-height:500px;overflow:auto;background:#fafafa;display:flex;align-items:center;font-size:14px;text-align:left}.icon{width:30px;height:30px;border-radius:100%;margin-right:10px}.desc,.title{width:500px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.desc{color:#999}.op-item.active{background:#dee2e8}

BIN
public/tpl/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

1
public/tpl/index.html Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>tpl</title><link href="css/app.f5fd5a5f.css" rel="preload" as="style"><link href="js/app.845a0078.js" rel="preload" as="script"><link href="js/chunk-vendors.d5af439e.js" rel="preload" as="script"><link href="css/app.f5fd5a5f.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but tpl doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.d5af439e.js"></script><script src="js/app.845a0078.js"></script></body></html>

View File

@ -0,0 +1,2 @@
(function(e){function t(t){for(var r,u,a=t[0],i=t[1],l=t[2],d=0,p=[];d<a.length;d++)u=a[d],Object.prototype.hasOwnProperty.call(c,u)&&c[u]&&p.push(c[u][0]),c[u]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(p.length)p.shift()();return o.push.apply(o,l||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,a=1;a<n.length;a++){var i=n[a];0!==c[i]&&(r=!1)}r&&(o.splice(t--,1),e=u(u.s=n[0]))}return e}var r={},c={app:0},o=[];function u(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,u),n.l=!0,n.exports}u.m=e,u.c=r,u.d=function(e,t,n){u.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},u.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,t){if(1&t&&(e=u(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(u.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)u.d(n,r,function(t){return e[t]}.bind(null,r));return n},u.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return u.d(t,"a",t),t},u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.p="";var a=window["webpackJsonp"]=window["webpackJsonp"]||[],i=a.push.bind(a);a.push=t,a=a.slice();for(var l=0;l<a.length;l++)t(a[l]);var s=i;o.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("cd49")},2874:function(e,t,n){},"2f93":function(e,t,n){"use strict";n("4016")},4016:function(e,t,n){},5490:function(e,t,n){"use strict";n("2874")},cd49:function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("7a23"),c=n("6c02"),o={setup:function(e){var t=Object(c["d"])();return window.rubick.onPluginEnter((function(e){var n=e.code,r=window.exports[n];t.push({name:r.mode,params:{code:n}})})),function(e,t){var n=Object(r["v"])("router-view");return Object(r["q"])(),Object(r["d"])(n)}}};n("5490");const u=o;var a=u,i=(n("ac1f"),n("841c"),n("a4d3"),n("e01a"),{class:"list-container"}),l={class:"options"},s=["onClick"],d=["src"],p={class:"content"},f={class:"title"},v={class:"desc"},b=Object(r["g"])({setup:function(e){var t=window.require("electron"),n=t.ipcRenderer,o=Object(c["c"])(),u=60,a=10,b=60,O=o.params.code,j=window.exports[O];window.rubick.setExpendHeight(b);var w=Object(r["t"])([]);j.args.enter&&j.args.enter({code:O,type:"",payload:[]},(function(e){e.value=e}));var h=Object(r["t"])(0);n.on("changeCurrent",(function(e,t){h.value+t>w.value.length-1||w.value+t<0||(h.value=h.value+t)})),window.rubick.setSubInput((function(e){var t=e.text;j.args.search&&j.args.search({code:O,type:"",payload:[]},t,(function(e){w.value=e||[];var t=w.value.length>a?a*u:u*w.value.length;window.rubick.setExpendHeight(b+t)}))}),"搜索");var g=function(e){j.args.select&&j.args.select({code:O,type:"",payload:[]},e)},y=function(e){if("Enter"===e.code)return g(w.value[h.value]);var t=0;"ArrowDown"===e.code&&(t=1),"ArrowUp"===e.code&&(t=-1),w.value.length&&(h.value+t>w.value.length-1||h.value+t<0||(h.value=h.value+t))};return window.addEventListener("keydown",y),Object(r["n"])((function(){window.removeEventListener("keydown",y)})),function(e,t){return Object(r["q"])(),Object(r["e"])("div",i,[Object(r["B"])(Object(r["f"])("div",l,[(Object(r["q"])(!0),Object(r["e"])(r["a"],null,Object(r["u"])(w.value,(function(e,t){return Object(r["q"])(),Object(r["e"])("div",{key:t,class:Object(r["l"])(h.value===t?"active op-item":"op-item"),onClick:function(t){return g(e)}},[Object(r["f"])("img",{class:"icon",src:e.icon},null,8,d),Object(r["f"])("div",p,[Object(r["f"])("div",f,Object(r["x"])(e.title),1),Object(r["f"])("div",v,Object(r["x"])(decodeURIComponent(e.description)),1)])],10,s)})),128))],512),[[r["z"],!!(w.value||[]).length]])])}}});n("2f93");const O=b;var j=O,w={class:"home"};function h(e,t){return Object(r["q"])(),Object(r["e"])("div",w)}var g=n("6b0d"),y=n.n(g);const m={},x=y()(m,[["render",h]]);var k=x,P=[{path:"/list",name:"list",component:j},{path:"/doc",name:"doc",component:k}],q=Object(c["a"])({history:Object(c["b"])(),routes:P}),E=q,S=n("5502"),_=Object(S["a"])({state:{},mutations:{},actions:{},modules:{}});Object(r["c"])(a).use(_).use(E).mount("#app")}});
//# sourceMappingURL=app.845a0078.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,4 +5,83 @@ const appPath = app.getPath("cache");
const PLUGIN_INSTALL_DIR = path.join(appPath, "./rubick-plugins");
export { PLUGIN_INSTALL_DIR };
const DECODE_KEY = {
Backspace: "Backspace",
Tab: "Tab",
Enter: "Enter",
MediaPlayPause: "MediaPlayPause",
Escape: "Escape",
Space: "Space",
PageUp: "PageUp",
PageDown: "PageDown",
End: "End",
Home: "Home",
ArrowLeft: "Left",
ArrowUp: "Up",
ArrowRight: "Right",
ArrowDown: "Down",
PrintScreen: "PrintScreen",
Insert: "Insert",
Delete: "Delete",
Digit0: "0",
Digit1: "1",
Digit2: "2",
Digit3: "3",
Digit4: "4",
Digit5: "5",
Digit6: "6",
Digit7: "7",
Digit8: "8",
Digit9: "9",
KeyA: "A",
KeyB: "B",
KeyC: "C",
KeyD: "D",
KeyE: "E",
KeyF: "F",
KeyG: "G",
KeyH: "H",
KeyI: "I",
KeyJ: "J",
KeyK: "K",
KeyL: "L",
KeyM: "M",
KeyN: "N",
KeyO: "O",
KeyP: "P",
KeyQ: "Q",
KeyR: "R",
KeyS: "S",
KeyT: "T",
KeyU: "U",
KeyV: "V",
KeyW: "W",
KeyX: "X",
KeyY: "Y",
KeyZ: "Z",
F1: "F1",
F2: "F2",
F3: "F3",
F4: "F4",
F5: "F5",
F6: "F6",
F7: "F7",
F8: "F8",
F9: "F9",
F10: "F10",
F11: "F11",
F12: "F12",
Semicolon: ";",
Equal: "=",
Comma: ",",
Minus: "-",
Period: ".",
Slash: "/",
Backquote: "`",
BracketLeft: "[",
Backslash: "\\",
BracketRight: "]",
Quote: "'",
};
export { PLUGIN_INSTALL_DIR, DECODE_KEY };

View File

@ -3,6 +3,21 @@ import path from "path";
import commonConst from "../../common/utils/commonConst";
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/main";
const getPreloadPath = (plugin, pluginIndexPath) => {
const { name, preload, tplPath, indexPath } = plugin;
if (commonConst.dev()) {
if (name === "rubick-system-feature") {
return path.resolve(__static, `../feature/public/preload.js`);
}
if (tplPath) {
return path.resolve(indexPath.replace("file:", ""), `./`, preload);
}
return path.resolve(pluginIndexPath.replace("file:", ""), `../`, preload);
}
return path.resolve(pluginIndexPath.replace("file:", ""), `../`, preload);
};
export default () => {
let view;
@ -13,19 +28,12 @@ export default () => {
};
const createView = (plugin, window: BrowserWindow) => {
let pluginIndexPath = plugin.indexPath;
let pluginIndexPath = plugin.tplPath || plugin.indexPath;
if (!pluginIndexPath) {
const pluginPath = path.resolve(baseDir, "node_modules", plugin.name);
pluginIndexPath = `file://${path.join(pluginPath, "./", plugin.main)}`;
}
const preload =
commonConst.dev() && plugin.name === "rubick-system-feature"
? path.resolve(__static, `../feature/public/preload.js`)
: path.resolve(
pluginIndexPath.replace("file:", ""),
`../`,
plugin.preload
);
const preload = getPreloadPath(plugin, pluginIndexPath);
const ses = session.fromPartition("<" + plugin.name + ">");
ses.setPreloads([`${__static}/preload.js`]);
@ -44,10 +52,10 @@ export default () => {
});
window.setBrowserView(view);
view.webContents.loadURL(pluginIndexPath);
window.once("ready-to-show", () => {
view.webContents.once("dom-ready", () => {
window.setSize(800, 660);
view.setBounds({ x: 0, y: 60, width: 800, height: 600 });
view.setAutoResize({ width: true });
window.setSize(800, 660);
commonConst.dev() && view.webContents.openDevTools();
executeHooks("PluginEnter", plugin.ext);
executeHooks("PluginReady", plugin.ext);

View File

@ -8,10 +8,10 @@ import {
clipboard,
} from "electron";
import { runner } from "../browsers";
import path from "path";
import fs from "fs";
import { LocalDb } from "@/core";
import plist from "plist";
import { DECODE_KEY } from "@/common/constans/main";
const runnerInstance = runner();
const dbInstance = new LocalDb(app.getPath("userData"));
@ -156,6 +156,22 @@ const API: any = {
);
return true;
},
sendPluginSomeKeyDownEvent({ data: { modifiers, keyCode } }) {
const code = DECODE_KEY[keyCode];
if (!code || !runnerInstance.getView()) return;
if (modifiers.length > 0) {
runnerInstance.getView().webContents.sendInputEvent({
type: "keyDown",
modifiers,
keyCode: code,
});
} else {
runnerInstance.getView().webContents.sendInputEvent({
type: "keyDown",
keyCode: code,
});
}
},
};
export default (mainWindow: BrowserWindow) => {

View File

@ -5,17 +5,12 @@
id="search"
class="main-input"
@input="(e) => changeValue(e)"
@keydown.down="() => emit('changeCurrent', 1)"
@keydown.up="() => emit('changeCurrent', -1)"
@keydown.down="(e) => keydownEvent(e, 1)"
@keydown.up="(e) => keydownEvent(e, -1)"
@keydown="e => checkNeedInit(e)"
:value="searchValue"
:placeholder="placeholder || 'Hi, Rubick2'"
@keypress.enter="
(e) => targetSearch({ value: e.target.value, type: 'enter' })
"
@keypress.space="
(e) => targetSearch({ value: e.target.value, type: 'space' })
"
@keypress.enter="(e) => keydownEvent(e)"
>
<template #suffix>
<div class="suffix-tool" >
@ -64,6 +59,7 @@ const props = defineProps({
const changeValue = (e) => {
if (props.currentPlugin.name === "rubick-system-feature") return;
targetSearch({ value: e.target.value });
emit("onSearch", e);
};
@ -75,6 +71,27 @@ const emit = defineEmits([
"choosePlugin",
]);
const keydownEvent = (e, index) => {
const { ctrlKey, shiftKey, altKey, metaKey } = e;
const modifiers = [];
ctrlKey && modifiers.push("control");
shiftKey && modifiers.push("shift");
altKey && modifiers.push("alt");
metaKey && modifiers.push("meta");
ipcRenderer.send("msg-trigger", {
type: "sendPluginSomeKeyDownEvent",
data: {
keyCode: e.code,
modifiers,
},
});
if(index) {
emit("changeCurrent", index);
} else {
!props.currentPlugin.name && emit("choosePlugin");
}
};
const checkNeedInit = (e) => {
if (e.target.value === "" && e.keyCode === 8) {
closeTag();
@ -87,8 +104,6 @@ const targetSearch = ({ value, type }) => {
type: "sendSubInputChangeEvent",
data: { text: value },
});
} else {
emit("choosePlugin");
}
};

View File

@ -67,7 +67,7 @@ const createPluginManager = (): any => {
return {
...pluginInfo,
indexPath: commonConst.dev()
? "http://localhost:8080/#/"
? "http://localhost:8081/#/"
: `file://${path.join(pluginPath, "../", pluginInfo.main)}`,
};
};

View File

@ -3,6 +3,7 @@ import throttle from "lodash.throttle";
import { remote } from "electron";
import path from "path";
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
import commonConst from "@/common/utils/commonConst";
function searchKeyValues(lists, value) {
return lists.filter((item) => {
@ -44,16 +45,23 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
"node_modules",
plugin.name
);
openPlugin({
const pluginDist = {
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main
plugin.main || ""
)}`,
cmd,
feature: fe,
});
};
// 模板文件
if (!plugin.main) {
pluginDist.tplPath = commonConst.dev()
? "http://localhost:8082/#/"
: `file://${__static}/tpl/index.html`;
}
openPlugin(pluginDist);
},
})),
];

23
tpl/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

24
tpl/README.md Normal file
View File

@ -0,0 +1,24 @@
# tpl
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

3
tpl/babel.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
};

13227
tpl/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

56
tpl/package.json Normal file
View File

@ -0,0 +1,56 @@
{
"name": "tpl",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"prettier": "^2.2.1",
"typescript": "~4.1.5"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/typescript/recommended",
"@vue/prettier",
"@vue/prettier/@typescript-eslint"
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

BIN
tpl/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

17
tpl/public/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

25
tpl/src/App.vue Normal file
View File

@ -0,0 +1,25 @@
<template>
<router-view />
</template>
<script setup>
import { useRouter } from "vue-router";
const router = useRouter();
window.rubick.onPluginEnter(({ code }) => {
const current = window.exports[code];
router.push({
name: current.mode,
params: {
code,
},
});
});
</script>
<style>
* {
margin: 0;
padding: 0;
}
</style>

6
tpl/src/main.ts Normal file
View File

@ -0,0 +1,6 @@
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
createApp(App).use(store).use(router).mount("#app");

23
tpl/src/router/index.ts Normal file
View File

@ -0,0 +1,23 @@
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import List from "../views/List.vue";
import Doc from "../views/Doc.vue";
const routes: Array<RouteRecordRaw> = [
{
path: "/list",
name: "list",
component: List,
},
{
path: "/doc",
name: "doc",
component: Doc,
},
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;

10
tpl/src/shims-vue.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
interface Window {
rubick: any;
}

8
tpl/src/store/index.ts Normal file
View File

@ -0,0 +1,8 @@
import { createStore } from "vuex";
export default createStore({
state: {},
mutations: {},
actions: {},
modules: {},
});

7
tpl/src/views/Doc.vue Normal file
View File

@ -0,0 +1,7 @@
<template>
<div class="home">
</div>
</template>
<script lang="ts">
</script>

135
tpl/src/views/List.vue Normal file
View File

@ -0,0 +1,135 @@
<template>
<div class="list-container">
<div class="options" v-show="!!(lists || []).length">
<div
:key="index"
:class="currentSelect === index ? 'active op-item' : 'op-item'"
v-for="(item, index) in lists"
@click="select(item)"
>
<img class="icon" :src="item.icon" />
<div class="content">
<div class="title">{{ item.title }}</div>
<div class="desc">{{ decodeURIComponent(item.description) }}</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
import { ref, onBeforeUnmount } from "vue";
const { ipcRenderer } = window.require("electron");
const route = useRoute();
const itemHeight = 60;
const itemMaxNum = 10;
const defaultHeight = 60;
const code = route.params.code;
const current = window.exports[code];
window.rubick.setExpendHeight(defaultHeight);
const lists = ref([]);
current.args.enter &&
current.args.enter({ code: code, type: "", payload: [] }, (lists) => {
lists.value = lists;
});
const currentSelect = ref(0);
ipcRenderer.on(`changeCurrent`, (e, result) => {
if (
currentSelect.value + result > lists.value.length - 1 ||
lists.value + result < 0
) {
return;
}
currentSelect.value = currentSelect.value + result;
});
window.rubick.setSubInput(({ text }) => {
current.args.search &&
current.args.search({ code, type: "", payload: [] }, text, (result) => {
lists.value = result || [];
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
window.rubick.setExpendHeight(defaultHeight + height);
});
}, "搜索");
const select = (item) => {
current.args.select && current.args.select({code, type: '', payload: [] }, item);
};
const onKeydownAction = (e) => {
if (e.code === "Enter") {
return select(lists.value[currentSelect.value]);
}
let index = 0;
if (e.code === "ArrowDown") {
index = 1;
}
if (e.code === "ArrowUp") {
index = -1;
}
if (!lists.value.length) return;
if (
currentSelect.value + index > lists.value.length - 1 ||
currentSelect.value + index < 0
)
return;
currentSelect.value = currentSelect.value + index;
};
window.addEventListener("keydown", onKeydownAction);
onBeforeUnmount(() => {
window.removeEventListener("keydown", onKeydownAction);
});
</script>
<style>
.options {
position: absolute;
left: 0;
width: 100%;
z-index: 99;
max-height: calc(100vh);
overflow: auto;
}
.options::-webkit-scrollbar {
width: 0;
}
.op-item {
padding: 0 10px;
height: 60px;
max-height: 500px;
overflow: auto;
background: #fafafa;
display: flex;
align-items: center;
font-size: 14px;
text-align: left;
}
.icon {
width: 30px;
height: 30px;
border-radius: 100%;
margin-right: 10px;
}
.title {
width: 500px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.desc {
color: #999;
width: 500px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.op-item.active {
background: #dee2e8;
}
</style>

39
tpl/tsconfig.json Normal file
View File

@ -0,0 +1,39 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

13
tpl/vue.config.js Normal file
View File

@ -0,0 +1,13 @@
const path = require("path");
module.exports = {
css: { // 配置css模块
loaderOptions: { // 向预处理器 Loader 传递配置选项
less: { // 配置less其他样式解析用法一致
javascriptEnabled: true // 设置为true
}
}
},
outputDir: path.join(__dirname, "../public/tpl"),
publicPath: process.env.NODE_ENV === "production" ? "" : "/",
};