Consolidate Lit repositories: figma-to-lit, figma_lit_example, lit-3d-piano, lit-calculator, lit-code-editor, lit-draggable-dom, lit-file-based-routing, lit-force-graph, lit-html-editor, lit-html-table, lit-modules, lit-native, lit-node-editor, lit-sheet-music, lit-starter-ts, lit-vscode-extension, lit-wmr, vite-lit-capacitor, vite-lit-element-starter, vite-rxdb-lit
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
types
|
||||
*.local
|
||||
@@ -0,0 +1,269 @@
|
||||
{
|
||||
"name": "lit-file-router",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "17.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
|
||||
"integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==",
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.15.tgz",
|
||||
"integrity": "sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild-android-arm64": "0.13.15",
|
||||
"esbuild-darwin-64": "0.13.15",
|
||||
"esbuild-darwin-arm64": "0.13.15",
|
||||
"esbuild-freebsd-64": "0.13.15",
|
||||
"esbuild-freebsd-arm64": "0.13.15",
|
||||
"esbuild-linux-32": "0.13.15",
|
||||
"esbuild-linux-64": "0.13.15",
|
||||
"esbuild-linux-arm": "0.13.15",
|
||||
"esbuild-linux-arm64": "0.13.15",
|
||||
"esbuild-linux-mips64le": "0.13.15",
|
||||
"esbuild-linux-ppc64le": "0.13.15",
|
||||
"esbuild-netbsd-64": "0.13.15",
|
||||
"esbuild-openbsd-64": "0.13.15",
|
||||
"esbuild-sunos-64": "0.13.15",
|
||||
"esbuild-windows-32": "0.13.15",
|
||||
"esbuild-windows-64": "0.13.15",
|
||||
"esbuild-windows-arm64": "0.13.15"
|
||||
}
|
||||
},
|
||||
"esbuild-android-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz",
|
||||
"integrity": "sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz",
|
||||
"integrity": "sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-32": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz",
|
||||
"integrity": "sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz",
|
||||
"integrity": "sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz",
|
||||
"integrity": "sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-mips64le": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz",
|
||||
"integrity": "sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-ppc64le": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz",
|
||||
"integrity": "sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-netbsd-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz",
|
||||
"integrity": "sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-openbsd-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz",
|
||||
"integrity": "sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-sunos-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz",
|
||||
"integrity": "sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-32": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz",
|
||||
"integrity": "sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz",
|
||||
"integrity": "sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
|
||||
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.30",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
|
||||
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
|
||||
"integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"nanoid": "^3.1.30",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.21.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz",
|
||||
"integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-core-module": "^2.8.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.63.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.63.0.tgz",
|
||||
"integrity": "sha512-nps0idjmD+NXl6OREfyYXMn/dar3WGcyKn+KBzPdaLecub3x/LrId0wUcthcr8oZUAcZAR8NKcfGGFlNgGL1kQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz",
|
||||
"integrity": "sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
|
||||
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
|
||||
"dev": true
|
||||
},
|
||||
"vite": {
|
||||
"version": "2.7.10",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.7.10.tgz",
|
||||
"integrity": "sha512-KEY96ntXUid1/xJihJbgmLZx7QSC2D4Tui0FdS0Old5OokYzFclcofhtxtjDdGOk/fFpPbHv9yw88+rB93Tb8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild": "^0.13.12",
|
||||
"fsevents": "~2.3.2",
|
||||
"postcss": "^8.4.5",
|
||||
"resolve": "^1.20.0",
|
||||
"rollup": "^2.59.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "lit-file-router",
|
||||
"version": "0.0.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"types"
|
||||
],
|
||||
"scripts": {
|
||||
"preinstall": "npm run build",
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17.0.8",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
export function analyzePage(path: string, content: string): WebComponent[] {
|
||||
const components: WebComponent[] = [];
|
||||
// Check for export function loader( or export async function loader(
|
||||
let hasLoader = false;
|
||||
const lines = content.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (
|
||||
line.includes("export function loader(") ||
|
||||
line.includes("export async function loader(")
|
||||
) {
|
||||
hasLoader = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Look for @customElement decorator and get the value
|
||||
const regex = /@customElement\("([^"]+)"\)/g;
|
||||
const matches = content.match(regex);
|
||||
if (matches) {
|
||||
for (const match of matches) {
|
||||
const result = match.match(/@customElement\("([^"]+)"\)/);
|
||||
if (result) {
|
||||
const name = result[1];
|
||||
components.push({
|
||||
name,
|
||||
path,
|
||||
hasLoader,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// Look for customElements.define() and get the value
|
||||
const regex2 = /customElements\.define\("([^"]+)"/g;
|
||||
const matches2 = content.match(regex2);
|
||||
if (matches2) {
|
||||
for (const match of matches2) {
|
||||
const result = match.match(/customElements\.define\("([^"]+)"/);
|
||||
if (result) {
|
||||
const name = result[1];
|
||||
components.push({
|
||||
name,
|
||||
path,
|
||||
hasLoader,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
export interface WebComponent {
|
||||
name: string;
|
||||
path: string;
|
||||
alias?: string;
|
||||
hasLoader: boolean;
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
import { WebComponent } from "./analyze-page";
|
||||
import { StringBuilder } from "./string-builder";
|
||||
|
||||
export function generateApp(
|
||||
sb: StringBuilder,
|
||||
components: WebComponent[],
|
||||
options: { staticImports: boolean; cacheAll: boolean; showLoading: boolean }
|
||||
) {
|
||||
sb.writeln(`import { html, css, LitElement } from "lit";`);
|
||||
sb.writeln(
|
||||
`import { customElement, property, state } from "lit/decorators.js";`
|
||||
);
|
||||
sb.writeln();
|
||||
sb.writeAll([
|
||||
'@customElement("generated-app")',
|
||||
"export class GeneratedApp extends LitElement {",
|
||||
" static styles = css`",
|
||||
" main {",
|
||||
" width: 100%;",
|
||||
" height: 100%;",
|
||||
" }",
|
||||
...(options.showLoading
|
||||
? [
|
||||
" progress {",
|
||||
" position: absolute;",
|
||||
" bottom: 0;",
|
||||
" width: calc(100% - 1rem);",
|
||||
" z-index: 1;",
|
||||
" left: 0.5rem;",
|
||||
" right: 0.5rem;",
|
||||
" }",
|
||||
]
|
||||
: []),
|
||||
" `;",
|
||||
"",
|
||||
" @property() hash = 'true';",
|
||||
" @property() base = '/';",
|
||||
...(options.showLoading ? [" @state() loading = false;"] : []),
|
||||
" @property() route = this.getCurrentRoute();",
|
||||
" @state() child = document.createElement('main');",
|
||||
"",
|
||||
]);
|
||||
if (options.cacheAll) {
|
||||
sb.writeln(" dataCache = new Map<string, any>();");
|
||||
}
|
||||
sb.writeln(" components: Map<string, Route> = new Map([");
|
||||
for (const component of components) {
|
||||
let path = component.path.replace("./src/pages/", "/");
|
||||
path = path.replace(".ts", "");
|
||||
path = path.replace(".js", "");
|
||||
path = path.replace("/index", "/");
|
||||
// Check if path contains . and convert to /
|
||||
if (path.indexOf(".") > -1) {
|
||||
path = path.split(".").join("/");
|
||||
}
|
||||
if (path == "/root") path = "";
|
||||
// sb.writeln(` ["${path}", "${component.name}"],`);]
|
||||
sb.writeln(` ["${path}", {
|
||||
component: "${component.name}",`);
|
||||
const componentImportPath = component.path
|
||||
.replace("./src/", "./")
|
||||
.replace(".ts", ".js");
|
||||
if (component.hasLoader) {
|
||||
if (options.staticImports) {
|
||||
sb.writeln(` loadData: async () => {
|
||||
return ${component.alias}.loader;
|
||||
},`);
|
||||
} else {
|
||||
sb.writeln(` loadData: async () => {
|
||||
const {loader} = await import("${componentImportPath}");
|
||||
return loader;
|
||||
},`);
|
||||
}
|
||||
} else {
|
||||
sb.writeln(` loadData: async () => null,`);
|
||||
}
|
||||
if (options.staticImports) {
|
||||
sb.writeln(` loadImport: async () => ${component.alias},
|
||||
}],`);
|
||||
} else {
|
||||
sb.writeln(` loadImport: () => import("${componentImportPath}"),
|
||||
}],`);
|
||||
}
|
||||
}
|
||||
sb.writeAll([
|
||||
" ]);",
|
||||
"",
|
||||
" firstUpdated() {",
|
||||
' window.addEventListener("hashchange", () => {',
|
||||
" const oldRoute = this.route;",
|
||||
" this.route = this.getCurrentRoute();",
|
||||
" this.updateTree(oldRoute);",
|
||||
" });",
|
||||
" this.updateTree();",
|
||||
" }",
|
||||
"",
|
||||
" render() {",
|
||||
" return html` ${this.child} `;",
|
||||
" }",
|
||||
"",
|
||||
" refresh() {",
|
||||
" return this.updateTree();",
|
||||
" }",
|
||||
"",
|
||||
" private async updateTree(oldRoute?:string) {",
|
||||
" this.checkForIndex();",
|
||||
" if (oldRoute) {",
|
||||
" // TODO: Get delta between old and new route",
|
||||
" }",
|
||||
...(options.showLoading
|
||||
? [
|
||||
' const loadingElem = document.createElement("progress");',
|
||||
" this.child.appendChild(loadingElem);",
|
||||
]
|
||||
: []),
|
||||
" const tree = await this.renderTree();",
|
||||
" // Remove children",
|
||||
" while (this.child.firstChild) {",
|
||||
" this.child.removeChild(this.child.firstChild);",
|
||||
" }",
|
||||
" // Add new children",
|
||||
" if (tree) this.child.appendChild(tree);",
|
||||
" this.requestUpdate();",
|
||||
" }",
|
||||
"",
|
||||
" private async renderTree() {",
|
||||
" let _route = this.route;",
|
||||
" const args = this.getArgsForRoute(_route);",
|
||||
" const elements: Element[] = [];",
|
||||
' if (_route !== "/") {',
|
||||
" while (_route.length > 0) {",
|
||||
" const newChild = await this.getComponent(_route, args);",
|
||||
" if (!newChild && _route === this.route) {",
|
||||
' const noChild = await this.getComponent("/404", args);',
|
||||
" if (noChild) elements.push(noChild);",
|
||||
" break;",
|
||||
" }",
|
||||
" if (newChild) elements.push(newChild);",
|
||||
' const parts = _route.split("/");',
|
||||
" parts.pop();",
|
||||
' _route = parts.join("/");',
|
||||
' if (_route === "/") break;',
|
||||
" }",
|
||||
' } else if (_route === "/") {',
|
||||
' const indexChild = await this.getComponent("/", args);',
|
||||
" if (indexChild) elements.push(indexChild);",
|
||||
" } else {",
|
||||
' const noChild = await this.getComponent("/404", args);',
|
||||
" if (noChild) elements.push(noChild);",
|
||||
" }",
|
||||
' const rootChild = await this.getComponent("", args);',
|
||||
" if (rootChild) elements.push(rootChild);",
|
||||
" let idx = elements.length - 1;",
|
||||
" while (idx >= 1) {",
|
||||
" const parent = elements[idx];",
|
||||
" const child = elements[idx - 1];",
|
||||
" if (child && parent) {",
|
||||
" parent.appendChild(child);",
|
||||
" }",
|
||||
" idx--;",
|
||||
" }",
|
||||
" return elements.pop();",
|
||||
" }",
|
||||
"",
|
||||
" private async getComponent(",
|
||||
" path: string,",
|
||||
" args: RegExpMatchArray | null",
|
||||
" ) {",
|
||||
" const applyArgs = (value: string, apply: boolean, data?: any) => {",
|
||||
" const elem = document.createElement(value);",
|
||||
" if (apply && args?.groups) {",
|
||||
" for (const [key, value] of Object.entries(args.groups)) {",
|
||||
" elem.setAttribute(key, value);",
|
||||
" }",
|
||||
" }",
|
||||
" if (data) (elem as any).data = data;",
|
||||
" return elem;",
|
||||
" };",
|
||||
" for (const [key, value] of Array.from(this.components.entries())) {",
|
||||
" const hasArgs = path.match(fixRegex(key)) !== null;",
|
||||
" if (key === path || path.match(fixRegex(key)) !== null) {",
|
||||
...(options.cacheAll
|
||||
? [
|
||||
" const cacheKey = `${path}:${value.component}`;",
|
||||
" if (this.dataCache.has(cacheKey)) {",
|
||||
" const data = this.dataCache.get(cacheKey)!;",
|
||||
...(options.staticImports
|
||||
? []
|
||||
: [" await value.loadImport();"]),
|
||||
" return applyArgs(value.component, hasArgs, data);",
|
||||
" }",
|
||||
]
|
||||
: []),
|
||||
" const getLoader = await value.loadData();",
|
||||
" if (getLoader) {",
|
||||
" const componentData = await getLoader(this.route, args ? Object(args)['groups'] : {});",
|
||||
...(options.cacheAll
|
||||
? [" this.dataCache.set(cacheKey, componentData);"]
|
||||
: []),
|
||||
...(options.staticImports ? [] : [" await value.loadImport();"]),
|
||||
" return applyArgs(value.component, hasArgs, componentData);",
|
||||
" }",
|
||||
...(options.staticImports ? [] : [" await value.loadImport();"]),
|
||||
" return applyArgs(value.component, hasArgs);",
|
||||
" }",
|
||||
" }",
|
||||
" return null;",
|
||||
" }",
|
||||
"",
|
||||
" private getArgsForRoute(route: string): RegExpMatchArray | null {",
|
||||
" for (const key of Array.from(this.components.keys())) {",
|
||||
" const regMatch = route.match(fixRegex(key));",
|
||||
" if (regMatch !== null) return regMatch;",
|
||||
" }",
|
||||
" return null;",
|
||||
" }",
|
||||
"",
|
||||
" private checkForIndex() {",
|
||||
' if (this.route === "" || this.route === "/") location.hash = "#/";',
|
||||
' if (this.route.endsWith("/")) return;',
|
||||
" const indexArgs = this.getArgsForRoute(`${this.route}/`);",
|
||||
" if (indexArgs !== null) {",
|
||||
" location.hash = `#${this.route}/`;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" private getCurrentRoute() {",
|
||||
' let route = "/";',
|
||||
' if (this.hash === "true" && window.location.hash.length > 0) {',
|
||||
" route = window.location.hash.slice(1);",
|
||||
' } else if (this.hash === "false") {',
|
||||
' const baseUrl = this.getAttribute("base") ?? "";',
|
||||
" route = window.location.pathname.slice(baseUrl.length);",
|
||||
" }",
|
||||
" console.debug(`current route: ${route}`);",
|
||||
" return route;",
|
||||
" }",
|
||||
"}",
|
||||
"",
|
||||
"function fixRegex(route: string): RegExp {",
|
||||
' const variableRegex = "[a-zA-Z0-9_-]+";',
|
||||
" const nameWithParameters = route.replace(",
|
||||
" new RegExp(`:(${variableRegex})`),",
|
||||
" (match) => {",
|
||||
" const groupName = match.slice(1);",
|
||||
" return `(?<${groupName}>[a-zA-Z0-9_\\\\-.,:;+*^%$@!]+)`;",
|
||||
" }",
|
||||
" );",
|
||||
" return new RegExp(`^${nameWithParameters}$`);",
|
||||
"}",
|
||||
"",
|
||||
"interface Route {",
|
||||
" component: string;",
|
||||
" loadImport: () => Promise<any>;",
|
||||
" loadData: () => Promise<RouteLoader | null>;",
|
||||
"}",
|
||||
"",
|
||||
"type RouteLoader = (",
|
||||
" route: string,",
|
||||
" args: { [key: string]: any }",
|
||||
") => Promise<any>;",
|
||||
]);
|
||||
sb.writeln();
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import * as fs from "fs";
|
||||
import { analyzePage, WebComponent } from "./analyze-page.js";
|
||||
import { generateApp } from "./generate-app.js";
|
||||
import { StringBuilder } from "./string-builder.js";
|
||||
|
||||
let inputDir = "./src/pages";
|
||||
let outputFile = "./src/generated-app.ts";
|
||||
let staticImports = true;
|
||||
let cacheAll = false;
|
||||
let showLoading = false;
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length == 0) {
|
||||
analyzePages();
|
||||
} else {
|
||||
// Check for -dynamic-imports=false
|
||||
const noDynamicImports = args.indexOf("--dynamic-imports=false") !== -1;
|
||||
staticImports = noDynamicImports;
|
||||
// Check for --input-dir=<dir>
|
||||
const inputDirArg = args.find((arg) => arg.startsWith("--input-dir="));
|
||||
if (inputDirArg) {
|
||||
inputDir = inputDirArg.replace("--input-dir=", "");
|
||||
}
|
||||
// Check for --output-file=<file>
|
||||
const outputFileArg = args.find((arg) => arg.startsWith("--output-file="));
|
||||
if (outputFileArg) {
|
||||
outputFile = outputFileArg.replace("--output-file=", "");
|
||||
}
|
||||
// Check for --cache-all
|
||||
const cacheAllArg = args.find((arg) => arg.startsWith("--cache-all"));
|
||||
if (cacheAllArg) {
|
||||
cacheAll = true;
|
||||
}
|
||||
// Check for --show-loading=false
|
||||
const showLoadingArg = args.find((arg) =>
|
||||
arg.startsWith("--show-loading=true")
|
||||
);
|
||||
showLoading = showLoadingArg ? true : false;
|
||||
analyzePages();
|
||||
}
|
||||
|
||||
function readPagesDirectory(
|
||||
dir: string,
|
||||
pages: { path: string; content: string }[]
|
||||
) {
|
||||
const files = fs.readdirSync(dir);
|
||||
for (const file of files) {
|
||||
if (fs.statSync(`${dir}/${file}`).isDirectory()) {
|
||||
readPagesDirectory(`${dir}/${file}`, pages);
|
||||
} else {
|
||||
const path = `${dir}/${file}`;
|
||||
const content = fs.readFileSync(path, "utf8");
|
||||
pages.push({ path, content });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function analyzePages() {
|
||||
const sb = new StringBuilder();
|
||||
// sb.writeln("// @ts-nocheck");
|
||||
// sb.writeln();
|
||||
let i = 0;
|
||||
if (staticImports) {
|
||||
sb.writeln(`// Page Routes`);
|
||||
}
|
||||
const components: WebComponent[] = [];
|
||||
const pages: { path: string; content: string }[] = [];
|
||||
readPagesDirectory(inputDir, pages);
|
||||
for (const { path, content } of pages) {
|
||||
// Add import
|
||||
const results = analyzePage(path, content);
|
||||
if (results.length > 0) {
|
||||
const c = results[0];
|
||||
if (staticImports) {
|
||||
const filePath = path.replace("./src/", "./");
|
||||
const jsPath = filePath.replace(".ts", ".js");
|
||||
c.alias = `route${i}`;
|
||||
sb.writeln(`import * as ${c.alias} from "${jsPath}";`);
|
||||
// if (c.hasLoader) {
|
||||
// sb.writeln(`import {loader as ${c.alias}Loader} from "${jsPath}";`);
|
||||
// }
|
||||
}
|
||||
components.push(c);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
sb.writeln();
|
||||
generateApp(sb, components, { staticImports, cacheAll, showLoading });
|
||||
const output = sb.toString();
|
||||
fs.writeFileSync(outputFile, output);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
export class StringBuilder {
|
||||
private _lines: string[] = [];
|
||||
|
||||
write(line: string = ""): void {
|
||||
this._lines.push(line);
|
||||
}
|
||||
|
||||
writeln(line: string = ""): void {
|
||||
this._lines.push(line);
|
||||
this._lines.push("\n");
|
||||
}
|
||||
|
||||
writeAll(lines: string[]): void {
|
||||
this._lines.push(lines.join("\n"));
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this._lines.join("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"lib": ["es2017", "dom", "dom.iterable"],
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": false,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"useDefineForClassFields": false
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": []
|
||||
}
|
||||
Reference in New Issue
Block a user