Merge docs PR, fix all lint/typecheck errors, update changelog
- Merge add-vitepress-docs: docs site with 6 locales, SEO, user guide - Remove VitePress cache files that slipped into git - Fix all 11 oxlint warnings: replace non-null assertions in use-collab.ts with local const captures inside closures - Update changelog with docs and lint fix entries
This commit is contained in:
parent
cbff284e78
commit
6eb206a451
|
|
@ -11,6 +11,7 @@
|
||||||
- Double-click to rename layers — inline rename in layer panel, shared `useInlineRename` composable
|
- Double-click to rename layers — inline rename in layer panel, shared `useInlineRename` composable
|
||||||
- New AI/MCP tools: `analyze_colors`, `analyze_typography`, `analyze_spacing`, `analyze_clusters`, `diff_create`, `diff_show`, `get_components`, `get_current_page`, `arrange`, `node_to_component`
|
- New AI/MCP tools: `analyze_colors`, `analyze_typography`, `analyze_spacing`, `analyze_clusters`, `diff_create`, `diff_show`, `get_components`, `get_current_page`, `arrange`, `node_to_component`
|
||||||
- CLI-to-app RPC bridge — all CLI commands work against the running app when no file is specified. Start the app, then run `bun open-pencil tree` to inspect the live document
|
- CLI-to-app RPC bridge — all CLI commands work against the running app when no file is specified. Start the app, then run `bun open-pencil tree` to inspect the live document
|
||||||
|
- VitePress docs site — user guide, reference, architecture, and development docs at openpencil.dev with 6 locales (en, de, fr, es, it, pl), SEO (OG tags, hreflang, JSON-LD, sitemap), and dark theme
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
- Fix drawer animation jump on close — single spring transition instead of two-phase
|
- Fix drawer animation jump on close — single spring transition instead of two-phase
|
||||||
- Fix `ALL_TOOLS` registry missing newer tools (`analyzeColors`, `diffCreate`, `exportImage`, `arrangeNodes`)
|
- Fix `ALL_TOOLS` registry missing newer tools (`analyzeColors`, `diffCreate`, `exportImage`, `arrangeNodes`)
|
||||||
- Fix `renderJSX` typo in tool definitions (`renderJsx` → `renderJSX`)
|
- Fix `renderJSX` typo in tool definitions (`renderJsx` → `renderJSX`)
|
||||||
|
- Fix all oxlint warnings and tsgo errors — replace `!` non-null assertions in `use-collab.ts` with local const captures
|
||||||
- Fix broken test imports — stale `../../src/engine/` paths updated to `@open-pencil/core`
|
- Fix broken test imports — stale `../../src/engine/` paths updated to `@open-pencil/core`
|
||||||
- Fix flaky E2E tests: layers panel navigates to `/demo`, zoom-to-fit test zooms in first, snapshot rendering stabilized with `workers: 1` and `colorScheme: dark`
|
- Fix flaky E2E tests: layers panel navigates to `/demo`, zoom-to-fit test zooms in first, snapshot rendering stabilized with `workers: 1` and `colorScheme: dark`
|
||||||
|
|
||||||
|
|
|
||||||
275
docs/.vitepress/cache/deps/@theme_index.js
vendored
275
docs/.vitepress/cache/deps/@theme_index.js
vendored
|
|
@ -1,275 +0,0 @@
|
||||||
import {
|
|
||||||
useMediaQuery
|
|
||||||
} from "./chunk-GHHMWP3C.js";
|
|
||||||
import {
|
|
||||||
computed,
|
|
||||||
ref,
|
|
||||||
shallowRef,
|
|
||||||
watch
|
|
||||||
} from "./chunk-H6MPEGKE.js";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/index.js
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/fonts.css";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/vars.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/base.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/icons.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/utils.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css";
|
|
||||||
import "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css";
|
|
||||||
import VPBadge from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
|
|
||||||
import Layout from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/Layout.vue";
|
|
||||||
import { default as default2 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
|
|
||||||
import { default as default3 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPButton.vue";
|
|
||||||
import { default as default4 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue";
|
|
||||||
import { default as default5 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPFeatures.vue";
|
|
||||||
import { default as default6 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPHomeContent.vue";
|
|
||||||
import { default as default7 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue";
|
|
||||||
import { default as default8 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue";
|
|
||||||
import { default as default9 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue";
|
|
||||||
import { default as default10 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPImage.vue";
|
|
||||||
import { default as default11 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPLink.vue";
|
|
||||||
import { default as default12 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPNavBarSearch.vue";
|
|
||||||
import { default as default13 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPSocialLink.vue";
|
|
||||||
import { default as default14 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPSocialLinks.vue";
|
|
||||||
import { default as default15 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPSponsors.vue";
|
|
||||||
import { default as default16 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue";
|
|
||||||
import { default as default17 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue";
|
|
||||||
import { default as default18 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue";
|
|
||||||
import { default as default19 } from "/mnt/f/projects/openspec/dannote/open-pencil/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
|
|
||||||
import { onContentUpdated } from "vitepress";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
|
|
||||||
import { getScrollOffset } from "vitepress";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/support/utils.js
|
|
||||||
import { withBase } from "vitepress";
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/data.js
|
|
||||||
import { useData as useData$ } from "vitepress";
|
|
||||||
var useData = useData$;
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/support/utils.js
|
|
||||||
function ensureStartingSlash(path) {
|
|
||||||
return path.startsWith("/") ? path : `/${path}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/support/sidebar.js
|
|
||||||
function getSidebar(_sidebar, path) {
|
|
||||||
if (Array.isArray(_sidebar))
|
|
||||||
return addBase(_sidebar);
|
|
||||||
if (_sidebar == null)
|
|
||||||
return [];
|
|
||||||
path = ensureStartingSlash(path);
|
|
||||||
const dir = Object.keys(_sidebar).sort((a, b) => {
|
|
||||||
return b.split("/").length - a.split("/").length;
|
|
||||||
}).find((dir2) => {
|
|
||||||
return path.startsWith(ensureStartingSlash(dir2));
|
|
||||||
});
|
|
||||||
const sidebar = dir ? _sidebar[dir] : [];
|
|
||||||
return Array.isArray(sidebar) ? addBase(sidebar) : addBase(sidebar.items, sidebar.base);
|
|
||||||
}
|
|
||||||
function getSidebarGroups(sidebar) {
|
|
||||||
const groups = [];
|
|
||||||
let lastGroupIndex = 0;
|
|
||||||
for (const index in sidebar) {
|
|
||||||
const item = sidebar[index];
|
|
||||||
if (item.items) {
|
|
||||||
lastGroupIndex = groups.push(item);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!groups[lastGroupIndex]) {
|
|
||||||
groups.push({ items: [] });
|
|
||||||
}
|
|
||||||
groups[lastGroupIndex].items.push(item);
|
|
||||||
}
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
function addBase(items, _base) {
|
|
||||||
return [...items].map((_item) => {
|
|
||||||
const item = { ..._item };
|
|
||||||
const base = item.base || _base;
|
|
||||||
if (base && item.link)
|
|
||||||
item.link = base + item.link;
|
|
||||||
if (item.items)
|
|
||||||
item.items = addBase(item.items, base);
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/sidebar.js
|
|
||||||
function useSidebar() {
|
|
||||||
const { frontmatter, page, theme: theme2 } = useData();
|
|
||||||
const is960 = useMediaQuery("(min-width: 960px)");
|
|
||||||
const isOpen = ref(false);
|
|
||||||
const _sidebar = computed(() => {
|
|
||||||
const sidebarConfig = theme2.value.sidebar;
|
|
||||||
const relativePath = page.value.relativePath;
|
|
||||||
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [];
|
|
||||||
});
|
|
||||||
const sidebar = ref(_sidebar.value);
|
|
||||||
watch(_sidebar, (next, prev) => {
|
|
||||||
if (JSON.stringify(next) !== JSON.stringify(prev))
|
|
||||||
sidebar.value = _sidebar.value;
|
|
||||||
});
|
|
||||||
const hasSidebar = computed(() => {
|
|
||||||
return frontmatter.value.sidebar !== false && sidebar.value.length > 0 && frontmatter.value.layout !== "home";
|
|
||||||
});
|
|
||||||
const leftAside = computed(() => {
|
|
||||||
if (hasAside)
|
|
||||||
return frontmatter.value.aside == null ? theme2.value.aside === "left" : frontmatter.value.aside === "left";
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
const hasAside = computed(() => {
|
|
||||||
if (frontmatter.value.layout === "home")
|
|
||||||
return false;
|
|
||||||
if (frontmatter.value.aside != null)
|
|
||||||
return !!frontmatter.value.aside;
|
|
||||||
return theme2.value.aside !== false;
|
|
||||||
});
|
|
||||||
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value);
|
|
||||||
const sidebarGroups = computed(() => {
|
|
||||||
return hasSidebar.value ? getSidebarGroups(sidebar.value) : [];
|
|
||||||
});
|
|
||||||
function open() {
|
|
||||||
isOpen.value = true;
|
|
||||||
}
|
|
||||||
function close() {
|
|
||||||
isOpen.value = false;
|
|
||||||
}
|
|
||||||
function toggle() {
|
|
||||||
isOpen.value ? close() : open();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
isOpen,
|
|
||||||
sidebar,
|
|
||||||
sidebarGroups,
|
|
||||||
hasSidebar,
|
|
||||||
hasAside,
|
|
||||||
leftAside,
|
|
||||||
isSidebarEnabled,
|
|
||||||
open,
|
|
||||||
close,
|
|
||||||
toggle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
|
|
||||||
var ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/;
|
|
||||||
var resolvedHeaders = [];
|
|
||||||
function getHeaders(range) {
|
|
||||||
const headers = [
|
|
||||||
...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")
|
|
||||||
].filter((el) => el.id && el.hasChildNodes()).map((el) => {
|
|
||||||
const level = Number(el.tagName[1]);
|
|
||||||
return {
|
|
||||||
element: el,
|
|
||||||
title: serializeHeader(el),
|
|
||||||
link: "#" + el.id,
|
|
||||||
level
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return resolveHeaders(headers, range);
|
|
||||||
}
|
|
||||||
function serializeHeader(h) {
|
|
||||||
let ret = "";
|
|
||||||
for (const node of h.childNodes) {
|
|
||||||
if (node.nodeType === 1) {
|
|
||||||
if (ignoreRE.test(node.className))
|
|
||||||
continue;
|
|
||||||
ret += node.textContent;
|
|
||||||
} else if (node.nodeType === 3) {
|
|
||||||
ret += node.textContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret.trim();
|
|
||||||
}
|
|
||||||
function resolveHeaders(headers, range) {
|
|
||||||
if (range === false) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const levelsRange = (typeof range === "object" && !Array.isArray(range) ? range.level : range) || 2;
|
|
||||||
const [high, low] = typeof levelsRange === "number" ? [levelsRange, levelsRange] : levelsRange === "deep" ? [2, 6] : levelsRange;
|
|
||||||
return buildTree(headers, high, low);
|
|
||||||
}
|
|
||||||
function buildTree(data, min, max) {
|
|
||||||
resolvedHeaders.length = 0;
|
|
||||||
const result = [];
|
|
||||||
const stack = [];
|
|
||||||
data.forEach((item) => {
|
|
||||||
const node = { ...item, children: [] };
|
|
||||||
let parent = stack[stack.length - 1];
|
|
||||||
while (parent && parent.level >= node.level) {
|
|
||||||
stack.pop();
|
|
||||||
parent = stack[stack.length - 1];
|
|
||||||
}
|
|
||||||
if (node.element.classList.contains("ignore-header") || parent && "shouldIgnore" in parent) {
|
|
||||||
stack.push({ level: node.level, shouldIgnore: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (node.level > max || node.level < min)
|
|
||||||
return;
|
|
||||||
resolvedHeaders.push({ element: node.element, link: node.link });
|
|
||||||
if (parent)
|
|
||||||
parent.children.push(node);
|
|
||||||
else
|
|
||||||
result.push(node);
|
|
||||||
stack.push(node);
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
|
|
||||||
function useLocalNav() {
|
|
||||||
const { theme: theme2, frontmatter } = useData();
|
|
||||||
const headers = shallowRef([]);
|
|
||||||
const hasLocalNav = computed(() => {
|
|
||||||
return headers.value.length > 0;
|
|
||||||
});
|
|
||||||
onContentUpdated(() => {
|
|
||||||
headers.value = getHeaders(frontmatter.value.outline ?? theme2.value.outline);
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
headers,
|
|
||||||
hasLocalNav
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
|
|
||||||
var theme = {
|
|
||||||
Layout,
|
|
||||||
enhanceApp: ({ app }) => {
|
|
||||||
app.component("Badge", VPBadge);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var without_fonts_default = theme;
|
|
||||||
export {
|
|
||||||
default2 as VPBadge,
|
|
||||||
default3 as VPButton,
|
|
||||||
default4 as VPDocAsideSponsors,
|
|
||||||
default5 as VPFeatures,
|
|
||||||
default6 as VPHomeContent,
|
|
||||||
default7 as VPHomeFeatures,
|
|
||||||
default8 as VPHomeHero,
|
|
||||||
default9 as VPHomeSponsors,
|
|
||||||
default10 as VPImage,
|
|
||||||
default11 as VPLink,
|
|
||||||
default12 as VPNavBarSearch,
|
|
||||||
default13 as VPSocialLink,
|
|
||||||
default14 as VPSocialLinks,
|
|
||||||
default15 as VPSponsors,
|
|
||||||
default16 as VPTeamMembers,
|
|
||||||
default17 as VPTeamPage,
|
|
||||||
default18 as VPTeamPageSection,
|
|
||||||
default19 as VPTeamPageTitle,
|
|
||||||
without_fonts_default as default,
|
|
||||||
useLocalNav,
|
|
||||||
useSidebar
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=@theme_index.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
58
docs/.vitepress/cache/deps/_metadata.json
vendored
58
docs/.vitepress/cache/deps/_metadata.json
vendored
|
|
@ -1,58 +0,0 @@
|
||||||
{
|
|
||||||
"hash": "56ac3d9b",
|
|
||||||
"configHash": "2e20719c",
|
|
||||||
"lockfileHash": "e3b0c442",
|
|
||||||
"browserHash": "83e68847",
|
|
||||||
"optimized": {
|
|
||||||
"vue": {
|
|
||||||
"src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
|
|
||||||
"file": "vue.js",
|
|
||||||
"fileHash": "144f3c50",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > @vue/devtools-api": {
|
|
||||||
"src": "../../../../node_modules/@vue/devtools-api/dist/index.js",
|
|
||||||
"file": "vitepress___@vue_devtools-api.js",
|
|
||||||
"fileHash": "a9dff81d",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > @vueuse/core": {
|
|
||||||
"src": "../../../../node_modules/vitepress/node_modules/@vueuse/core/index.mjs",
|
|
||||||
"file": "vitepress___@vueuse_core.js",
|
|
||||||
"fileHash": "c5cd5c33",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > @vueuse/integrations/useFocusTrap": {
|
|
||||||
"src": "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs",
|
|
||||||
"file": "vitepress___@vueuse_integrations_useFocusTrap.js",
|
|
||||||
"fileHash": "09bdc683",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > mark.js/src/vanilla.js": {
|
|
||||||
"src": "../../../../node_modules/mark.js/src/vanilla.js",
|
|
||||||
"file": "vitepress___mark__js_src_vanilla__js.js",
|
|
||||||
"fileHash": "59d6f4ed",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"vitepress > minisearch": {
|
|
||||||
"src": "../../../../node_modules/minisearch/dist/es/index.js",
|
|
||||||
"file": "vitepress___minisearch.js",
|
|
||||||
"fileHash": "bd3393ea",
|
|
||||||
"needsInterop": false
|
|
||||||
},
|
|
||||||
"@theme/index": {
|
|
||||||
"src": "../../../../node_modules/vitepress/dist/client/theme-default/index.js",
|
|
||||||
"file": "@theme_index.js",
|
|
||||||
"fileHash": "e473d499",
|
|
||||||
"needsInterop": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chunks": {
|
|
||||||
"chunk-GHHMWP3C": {
|
|
||||||
"file": "chunk-GHHMWP3C.js"
|
|
||||||
},
|
|
||||||
"chunk-H6MPEGKE": {
|
|
||||||
"file": "chunk-H6MPEGKE.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9719
docs/.vitepress/cache/deps/chunk-GHHMWP3C.js
vendored
9719
docs/.vitepress/cache/deps/chunk-GHHMWP3C.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
12877
docs/.vitepress/cache/deps/chunk-H6MPEGKE.js
vendored
12877
docs/.vitepress/cache/deps/chunk-H6MPEGKE.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
3
docs/.vitepress/cache/deps/package.json
vendored
3
docs/.vitepress/cache/deps/package.json
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"type": "module"
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1,583 +0,0 @@
|
||||||
import {
|
|
||||||
DefaultMagicKeysAliasMap,
|
|
||||||
StorageSerializers,
|
|
||||||
TransitionPresets,
|
|
||||||
assert,
|
|
||||||
breakpointsAntDesign,
|
|
||||||
breakpointsBootstrapV5,
|
|
||||||
breakpointsElement,
|
|
||||||
breakpointsMasterCss,
|
|
||||||
breakpointsPrimeFlex,
|
|
||||||
breakpointsQuasar,
|
|
||||||
breakpointsSematic,
|
|
||||||
breakpointsTailwind,
|
|
||||||
breakpointsVuetify,
|
|
||||||
breakpointsVuetifyV2,
|
|
||||||
breakpointsVuetifyV3,
|
|
||||||
bypassFilter,
|
|
||||||
camelize,
|
|
||||||
clamp,
|
|
||||||
cloneFnJSON,
|
|
||||||
computedAsync,
|
|
||||||
computedEager,
|
|
||||||
computedInject,
|
|
||||||
computedWithControl,
|
|
||||||
containsProp,
|
|
||||||
controlledRef,
|
|
||||||
createEventHook,
|
|
||||||
createFetch,
|
|
||||||
createFilterWrapper,
|
|
||||||
createGlobalState,
|
|
||||||
createInjectionState,
|
|
||||||
createRef,
|
|
||||||
createReusableTemplate,
|
|
||||||
createSharedComposable,
|
|
||||||
createSingletonPromise,
|
|
||||||
createTemplatePromise,
|
|
||||||
createUnrefFn,
|
|
||||||
customStorageEventName,
|
|
||||||
debounceFilter,
|
|
||||||
defaultDocument,
|
|
||||||
defaultLocation,
|
|
||||||
defaultNavigator,
|
|
||||||
defaultWindow,
|
|
||||||
executeTransition,
|
|
||||||
extendRef,
|
|
||||||
formatDate,
|
|
||||||
formatTimeAgo,
|
|
||||||
get,
|
|
||||||
getLifeCycleTarget,
|
|
||||||
getSSRHandler,
|
|
||||||
hasOwn,
|
|
||||||
hyphenate,
|
|
||||||
identity,
|
|
||||||
increaseWithUnit,
|
|
||||||
injectLocal,
|
|
||||||
invoke,
|
|
||||||
isClient,
|
|
||||||
isDef,
|
|
||||||
isDefined,
|
|
||||||
isIOS,
|
|
||||||
isObject,
|
|
||||||
isWorker,
|
|
||||||
makeDestructurable,
|
|
||||||
mapGamepadToXbox360Controller,
|
|
||||||
noop,
|
|
||||||
normalizeDate,
|
|
||||||
notNullish,
|
|
||||||
now,
|
|
||||||
objectEntries,
|
|
||||||
objectOmit,
|
|
||||||
objectPick,
|
|
||||||
onClickOutside,
|
|
||||||
onElementRemoval,
|
|
||||||
onKeyDown,
|
|
||||||
onKeyPressed,
|
|
||||||
onKeyStroke,
|
|
||||||
onKeyUp,
|
|
||||||
onLongPress,
|
|
||||||
onStartTyping,
|
|
||||||
pausableFilter,
|
|
||||||
promiseTimeout,
|
|
||||||
provideLocal,
|
|
||||||
provideSSRWidth,
|
|
||||||
pxValue,
|
|
||||||
rand,
|
|
||||||
reactify,
|
|
||||||
reactifyObject,
|
|
||||||
reactiveComputed,
|
|
||||||
reactiveOmit,
|
|
||||||
reactivePick,
|
|
||||||
refAutoReset,
|
|
||||||
refDebounced,
|
|
||||||
refDefault,
|
|
||||||
refThrottled,
|
|
||||||
refWithControl,
|
|
||||||
resolveRef,
|
|
||||||
resolveUnref,
|
|
||||||
set,
|
|
||||||
setSSRHandler,
|
|
||||||
syncRef,
|
|
||||||
syncRefs,
|
|
||||||
templateRef,
|
|
||||||
throttleFilter,
|
|
||||||
timestamp,
|
|
||||||
toArray,
|
|
||||||
toReactive,
|
|
||||||
toRef,
|
|
||||||
toRefs,
|
|
||||||
toValue,
|
|
||||||
tryOnBeforeMount,
|
|
||||||
tryOnBeforeUnmount,
|
|
||||||
tryOnMounted,
|
|
||||||
tryOnScopeDispose,
|
|
||||||
tryOnUnmounted,
|
|
||||||
unrefElement,
|
|
||||||
until,
|
|
||||||
useActiveElement,
|
|
||||||
useAnimate,
|
|
||||||
useArrayDifference,
|
|
||||||
useArrayEvery,
|
|
||||||
useArrayFilter,
|
|
||||||
useArrayFind,
|
|
||||||
useArrayFindIndex,
|
|
||||||
useArrayFindLast,
|
|
||||||
useArrayIncludes,
|
|
||||||
useArrayJoin,
|
|
||||||
useArrayMap,
|
|
||||||
useArrayReduce,
|
|
||||||
useArraySome,
|
|
||||||
useArrayUnique,
|
|
||||||
useAsyncQueue,
|
|
||||||
useAsyncState,
|
|
||||||
useBase64,
|
|
||||||
useBattery,
|
|
||||||
useBluetooth,
|
|
||||||
useBreakpoints,
|
|
||||||
useBroadcastChannel,
|
|
||||||
useBrowserLocation,
|
|
||||||
useCached,
|
|
||||||
useClipboard,
|
|
||||||
useClipboardItems,
|
|
||||||
useCloned,
|
|
||||||
useColorMode,
|
|
||||||
useConfirmDialog,
|
|
||||||
useCountdown,
|
|
||||||
useCounter,
|
|
||||||
useCssVar,
|
|
||||||
useCurrentElement,
|
|
||||||
useCycleList,
|
|
||||||
useDark,
|
|
||||||
useDateFormat,
|
|
||||||
useDebounceFn,
|
|
||||||
useDebouncedRefHistory,
|
|
||||||
useDeviceMotion,
|
|
||||||
useDeviceOrientation,
|
|
||||||
useDevicePixelRatio,
|
|
||||||
useDevicesList,
|
|
||||||
useDisplayMedia,
|
|
||||||
useDocumentVisibility,
|
|
||||||
useDraggable,
|
|
||||||
useDropZone,
|
|
||||||
useElementBounding,
|
|
||||||
useElementByPoint,
|
|
||||||
useElementHover,
|
|
||||||
useElementSize,
|
|
||||||
useElementVisibility,
|
|
||||||
useEventBus,
|
|
||||||
useEventListener,
|
|
||||||
useEventSource,
|
|
||||||
useEyeDropper,
|
|
||||||
useFavicon,
|
|
||||||
useFetch,
|
|
||||||
useFileDialog,
|
|
||||||
useFileSystemAccess,
|
|
||||||
useFocus,
|
|
||||||
useFocusWithin,
|
|
||||||
useFps,
|
|
||||||
useFullscreen,
|
|
||||||
useGamepad,
|
|
||||||
useGeolocation,
|
|
||||||
useIdle,
|
|
||||||
useImage,
|
|
||||||
useInfiniteScroll,
|
|
||||||
useIntersectionObserver,
|
|
||||||
useInterval,
|
|
||||||
useIntervalFn,
|
|
||||||
useKeyModifier,
|
|
||||||
useLastChanged,
|
|
||||||
useLocalStorage,
|
|
||||||
useMagicKeys,
|
|
||||||
useManualRefHistory,
|
|
||||||
useMediaControls,
|
|
||||||
useMediaQuery,
|
|
||||||
useMemoize,
|
|
||||||
useMemory,
|
|
||||||
useMounted,
|
|
||||||
useMouse,
|
|
||||||
useMouseInElement,
|
|
||||||
useMousePressed,
|
|
||||||
useMutationObserver,
|
|
||||||
useNavigatorLanguage,
|
|
||||||
useNetwork,
|
|
||||||
useNow,
|
|
||||||
useObjectUrl,
|
|
||||||
useOffsetPagination,
|
|
||||||
useOnline,
|
|
||||||
usePageLeave,
|
|
||||||
useParallax,
|
|
||||||
useParentElement,
|
|
||||||
usePerformanceObserver,
|
|
||||||
usePermission,
|
|
||||||
usePointer,
|
|
||||||
usePointerLock,
|
|
||||||
usePointerSwipe,
|
|
||||||
usePreferredColorScheme,
|
|
||||||
usePreferredContrast,
|
|
||||||
usePreferredDark,
|
|
||||||
usePreferredLanguages,
|
|
||||||
usePreferredReducedMotion,
|
|
||||||
usePreferredReducedTransparency,
|
|
||||||
usePrevious,
|
|
||||||
useRafFn,
|
|
||||||
useRefHistory,
|
|
||||||
useResizeObserver,
|
|
||||||
useSSRWidth,
|
|
||||||
useScreenOrientation,
|
|
||||||
useScreenSafeArea,
|
|
||||||
useScriptTag,
|
|
||||||
useScroll,
|
|
||||||
useScrollLock,
|
|
||||||
useSessionStorage,
|
|
||||||
useShare,
|
|
||||||
useSorted,
|
|
||||||
useSpeechRecognition,
|
|
||||||
useSpeechSynthesis,
|
|
||||||
useStepper,
|
|
||||||
useStorage,
|
|
||||||
useStorageAsync,
|
|
||||||
useStyleTag,
|
|
||||||
useSupported,
|
|
||||||
useSwipe,
|
|
||||||
useTemplateRefsList,
|
|
||||||
useTextDirection,
|
|
||||||
useTextSelection,
|
|
||||||
useTextareaAutosize,
|
|
||||||
useThrottleFn,
|
|
||||||
useThrottledRefHistory,
|
|
||||||
useTimeAgo,
|
|
||||||
useTimeout,
|
|
||||||
useTimeoutFn,
|
|
||||||
useTimeoutPoll,
|
|
||||||
useTimestamp,
|
|
||||||
useTitle,
|
|
||||||
useToNumber,
|
|
||||||
useToString,
|
|
||||||
useToggle,
|
|
||||||
useTransition,
|
|
||||||
useUrlSearchParams,
|
|
||||||
useUserMedia,
|
|
||||||
useVModel,
|
|
||||||
useVModels,
|
|
||||||
useVibrate,
|
|
||||||
useVirtualList,
|
|
||||||
useWakeLock,
|
|
||||||
useWebNotification,
|
|
||||||
useWebSocket,
|
|
||||||
useWebWorker,
|
|
||||||
useWebWorkerFn,
|
|
||||||
useWindowFocus,
|
|
||||||
useWindowScroll,
|
|
||||||
useWindowSize,
|
|
||||||
watchArray,
|
|
||||||
watchAtMost,
|
|
||||||
watchDebounced,
|
|
||||||
watchDeep,
|
|
||||||
watchIgnorable,
|
|
||||||
watchImmediate,
|
|
||||||
watchOnce,
|
|
||||||
watchPausable,
|
|
||||||
watchThrottled,
|
|
||||||
watchTriggerable,
|
|
||||||
watchWithFilter,
|
|
||||||
whenever
|
|
||||||
} from "./chunk-GHHMWP3C.js";
|
|
||||||
import "./chunk-H6MPEGKE.js";
|
|
||||||
export {
|
|
||||||
DefaultMagicKeysAliasMap,
|
|
||||||
StorageSerializers,
|
|
||||||
TransitionPresets,
|
|
||||||
assert,
|
|
||||||
computedAsync as asyncComputed,
|
|
||||||
refAutoReset as autoResetRef,
|
|
||||||
breakpointsAntDesign,
|
|
||||||
breakpointsBootstrapV5,
|
|
||||||
breakpointsElement,
|
|
||||||
breakpointsMasterCss,
|
|
||||||
breakpointsPrimeFlex,
|
|
||||||
breakpointsQuasar,
|
|
||||||
breakpointsSematic,
|
|
||||||
breakpointsTailwind,
|
|
||||||
breakpointsVuetify,
|
|
||||||
breakpointsVuetifyV2,
|
|
||||||
breakpointsVuetifyV3,
|
|
||||||
bypassFilter,
|
|
||||||
camelize,
|
|
||||||
clamp,
|
|
||||||
cloneFnJSON,
|
|
||||||
computedAsync,
|
|
||||||
computedEager,
|
|
||||||
computedInject,
|
|
||||||
computedWithControl,
|
|
||||||
containsProp,
|
|
||||||
computedWithControl as controlledComputed,
|
|
||||||
controlledRef,
|
|
||||||
createEventHook,
|
|
||||||
createFetch,
|
|
||||||
createFilterWrapper,
|
|
||||||
createGlobalState,
|
|
||||||
createInjectionState,
|
|
||||||
reactify as createReactiveFn,
|
|
||||||
createRef,
|
|
||||||
createReusableTemplate,
|
|
||||||
createSharedComposable,
|
|
||||||
createSingletonPromise,
|
|
||||||
createTemplatePromise,
|
|
||||||
createUnrefFn,
|
|
||||||
customStorageEventName,
|
|
||||||
debounceFilter,
|
|
||||||
refDebounced as debouncedRef,
|
|
||||||
watchDebounced as debouncedWatch,
|
|
||||||
defaultDocument,
|
|
||||||
defaultLocation,
|
|
||||||
defaultNavigator,
|
|
||||||
defaultWindow,
|
|
||||||
computedEager as eagerComputed,
|
|
||||||
executeTransition,
|
|
||||||
extendRef,
|
|
||||||
formatDate,
|
|
||||||
formatTimeAgo,
|
|
||||||
get,
|
|
||||||
getLifeCycleTarget,
|
|
||||||
getSSRHandler,
|
|
||||||
hasOwn,
|
|
||||||
hyphenate,
|
|
||||||
identity,
|
|
||||||
watchIgnorable as ignorableWatch,
|
|
||||||
increaseWithUnit,
|
|
||||||
injectLocal,
|
|
||||||
invoke,
|
|
||||||
isClient,
|
|
||||||
isDef,
|
|
||||||
isDefined,
|
|
||||||
isIOS,
|
|
||||||
isObject,
|
|
||||||
isWorker,
|
|
||||||
makeDestructurable,
|
|
||||||
mapGamepadToXbox360Controller,
|
|
||||||
noop,
|
|
||||||
normalizeDate,
|
|
||||||
notNullish,
|
|
||||||
now,
|
|
||||||
objectEntries,
|
|
||||||
objectOmit,
|
|
||||||
objectPick,
|
|
||||||
onClickOutside,
|
|
||||||
onElementRemoval,
|
|
||||||
onKeyDown,
|
|
||||||
onKeyPressed,
|
|
||||||
onKeyStroke,
|
|
||||||
onKeyUp,
|
|
||||||
onLongPress,
|
|
||||||
onStartTyping,
|
|
||||||
pausableFilter,
|
|
||||||
watchPausable as pausableWatch,
|
|
||||||
promiseTimeout,
|
|
||||||
provideLocal,
|
|
||||||
provideSSRWidth,
|
|
||||||
pxValue,
|
|
||||||
rand,
|
|
||||||
reactify,
|
|
||||||
reactifyObject,
|
|
||||||
reactiveComputed,
|
|
||||||
reactiveOmit,
|
|
||||||
reactivePick,
|
|
||||||
refAutoReset,
|
|
||||||
refDebounced,
|
|
||||||
refDefault,
|
|
||||||
refThrottled,
|
|
||||||
refWithControl,
|
|
||||||
resolveRef,
|
|
||||||
resolveUnref,
|
|
||||||
set,
|
|
||||||
setSSRHandler,
|
|
||||||
syncRef,
|
|
||||||
syncRefs,
|
|
||||||
templateRef,
|
|
||||||
throttleFilter,
|
|
||||||
refThrottled as throttledRef,
|
|
||||||
watchThrottled as throttledWatch,
|
|
||||||
timestamp,
|
|
||||||
toArray,
|
|
||||||
toReactive,
|
|
||||||
toRef,
|
|
||||||
toRefs,
|
|
||||||
toValue,
|
|
||||||
tryOnBeforeMount,
|
|
||||||
tryOnBeforeUnmount,
|
|
||||||
tryOnMounted,
|
|
||||||
tryOnScopeDispose,
|
|
||||||
tryOnUnmounted,
|
|
||||||
unrefElement,
|
|
||||||
until,
|
|
||||||
useActiveElement,
|
|
||||||
useAnimate,
|
|
||||||
useArrayDifference,
|
|
||||||
useArrayEvery,
|
|
||||||
useArrayFilter,
|
|
||||||
useArrayFind,
|
|
||||||
useArrayFindIndex,
|
|
||||||
useArrayFindLast,
|
|
||||||
useArrayIncludes,
|
|
||||||
useArrayJoin,
|
|
||||||
useArrayMap,
|
|
||||||
useArrayReduce,
|
|
||||||
useArraySome,
|
|
||||||
useArrayUnique,
|
|
||||||
useAsyncQueue,
|
|
||||||
useAsyncState,
|
|
||||||
useBase64,
|
|
||||||
useBattery,
|
|
||||||
useBluetooth,
|
|
||||||
useBreakpoints,
|
|
||||||
useBroadcastChannel,
|
|
||||||
useBrowserLocation,
|
|
||||||
useCached,
|
|
||||||
useClipboard,
|
|
||||||
useClipboardItems,
|
|
||||||
useCloned,
|
|
||||||
useColorMode,
|
|
||||||
useConfirmDialog,
|
|
||||||
useCountdown,
|
|
||||||
useCounter,
|
|
||||||
useCssVar,
|
|
||||||
useCurrentElement,
|
|
||||||
useCycleList,
|
|
||||||
useDark,
|
|
||||||
useDateFormat,
|
|
||||||
refDebounced as useDebounce,
|
|
||||||
useDebounceFn,
|
|
||||||
useDebouncedRefHistory,
|
|
||||||
useDeviceMotion,
|
|
||||||
useDeviceOrientation,
|
|
||||||
useDevicePixelRatio,
|
|
||||||
useDevicesList,
|
|
||||||
useDisplayMedia,
|
|
||||||
useDocumentVisibility,
|
|
||||||
useDraggable,
|
|
||||||
useDropZone,
|
|
||||||
useElementBounding,
|
|
||||||
useElementByPoint,
|
|
||||||
useElementHover,
|
|
||||||
useElementSize,
|
|
||||||
useElementVisibility,
|
|
||||||
useEventBus,
|
|
||||||
useEventListener,
|
|
||||||
useEventSource,
|
|
||||||
useEyeDropper,
|
|
||||||
useFavicon,
|
|
||||||
useFetch,
|
|
||||||
useFileDialog,
|
|
||||||
useFileSystemAccess,
|
|
||||||
useFocus,
|
|
||||||
useFocusWithin,
|
|
||||||
useFps,
|
|
||||||
useFullscreen,
|
|
||||||
useGamepad,
|
|
||||||
useGeolocation,
|
|
||||||
useIdle,
|
|
||||||
useImage,
|
|
||||||
useInfiniteScroll,
|
|
||||||
useIntersectionObserver,
|
|
||||||
useInterval,
|
|
||||||
useIntervalFn,
|
|
||||||
useKeyModifier,
|
|
||||||
useLastChanged,
|
|
||||||
useLocalStorage,
|
|
||||||
useMagicKeys,
|
|
||||||
useManualRefHistory,
|
|
||||||
useMediaControls,
|
|
||||||
useMediaQuery,
|
|
||||||
useMemoize,
|
|
||||||
useMemory,
|
|
||||||
useMounted,
|
|
||||||
useMouse,
|
|
||||||
useMouseInElement,
|
|
||||||
useMousePressed,
|
|
||||||
useMutationObserver,
|
|
||||||
useNavigatorLanguage,
|
|
||||||
useNetwork,
|
|
||||||
useNow,
|
|
||||||
useObjectUrl,
|
|
||||||
useOffsetPagination,
|
|
||||||
useOnline,
|
|
||||||
usePageLeave,
|
|
||||||
useParallax,
|
|
||||||
useParentElement,
|
|
||||||
usePerformanceObserver,
|
|
||||||
usePermission,
|
|
||||||
usePointer,
|
|
||||||
usePointerLock,
|
|
||||||
usePointerSwipe,
|
|
||||||
usePreferredColorScheme,
|
|
||||||
usePreferredContrast,
|
|
||||||
usePreferredDark,
|
|
||||||
usePreferredLanguages,
|
|
||||||
usePreferredReducedMotion,
|
|
||||||
usePreferredReducedTransparency,
|
|
||||||
usePrevious,
|
|
||||||
useRafFn,
|
|
||||||
useRefHistory,
|
|
||||||
useResizeObserver,
|
|
||||||
useSSRWidth,
|
|
||||||
useScreenOrientation,
|
|
||||||
useScreenSafeArea,
|
|
||||||
useScriptTag,
|
|
||||||
useScroll,
|
|
||||||
useScrollLock,
|
|
||||||
useSessionStorage,
|
|
||||||
useShare,
|
|
||||||
useSorted,
|
|
||||||
useSpeechRecognition,
|
|
||||||
useSpeechSynthesis,
|
|
||||||
useStepper,
|
|
||||||
useStorage,
|
|
||||||
useStorageAsync,
|
|
||||||
useStyleTag,
|
|
||||||
useSupported,
|
|
||||||
useSwipe,
|
|
||||||
useTemplateRefsList,
|
|
||||||
useTextDirection,
|
|
||||||
useTextSelection,
|
|
||||||
useTextareaAutosize,
|
|
||||||
refThrottled as useThrottle,
|
|
||||||
useThrottleFn,
|
|
||||||
useThrottledRefHistory,
|
|
||||||
useTimeAgo,
|
|
||||||
useTimeout,
|
|
||||||
useTimeoutFn,
|
|
||||||
useTimeoutPoll,
|
|
||||||
useTimestamp,
|
|
||||||
useTitle,
|
|
||||||
useToNumber,
|
|
||||||
useToString,
|
|
||||||
useToggle,
|
|
||||||
useTransition,
|
|
||||||
useUrlSearchParams,
|
|
||||||
useUserMedia,
|
|
||||||
useVModel,
|
|
||||||
useVModels,
|
|
||||||
useVibrate,
|
|
||||||
useVirtualList,
|
|
||||||
useWakeLock,
|
|
||||||
useWebNotification,
|
|
||||||
useWebSocket,
|
|
||||||
useWebWorker,
|
|
||||||
useWebWorkerFn,
|
|
||||||
useWindowFocus,
|
|
||||||
useWindowScroll,
|
|
||||||
useWindowSize,
|
|
||||||
watchArray,
|
|
||||||
watchAtMost,
|
|
||||||
watchDebounced,
|
|
||||||
watchDeep,
|
|
||||||
watchIgnorable,
|
|
||||||
watchImmediate,
|
|
||||||
watchOnce,
|
|
||||||
watchPausable,
|
|
||||||
watchThrottled,
|
|
||||||
watchTriggerable,
|
|
||||||
watchWithFilter,
|
|
||||||
whenever
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=vitepress___@vueuse_core.js.map
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"sources": [],
|
|
||||||
"sourcesContent": [],
|
|
||||||
"mappings": "",
|
|
||||||
"names": []
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
1813
docs/.vitepress/cache/deps/vitepress___minisearch.js
vendored
1813
docs/.vitepress/cache/deps/vitepress___minisearch.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
347
docs/.vitepress/cache/deps/vue.js
vendored
347
docs/.vitepress/cache/deps/vue.js
vendored
|
|
@ -1,347 +0,0 @@
|
||||||
import {
|
|
||||||
BaseTransition,
|
|
||||||
BaseTransitionPropsValidators,
|
|
||||||
Comment,
|
|
||||||
DeprecationTypes,
|
|
||||||
EffectScope,
|
|
||||||
ErrorCodes,
|
|
||||||
ErrorTypeStrings,
|
|
||||||
Fragment,
|
|
||||||
KeepAlive,
|
|
||||||
ReactiveEffect,
|
|
||||||
Static,
|
|
||||||
Suspense,
|
|
||||||
Teleport,
|
|
||||||
Text,
|
|
||||||
TrackOpTypes,
|
|
||||||
Transition,
|
|
||||||
TransitionGroup,
|
|
||||||
TriggerOpTypes,
|
|
||||||
VueElement,
|
|
||||||
assertNumber,
|
|
||||||
callWithAsyncErrorHandling,
|
|
||||||
callWithErrorHandling,
|
|
||||||
camelize,
|
|
||||||
capitalize,
|
|
||||||
cloneVNode,
|
|
||||||
compatUtils,
|
|
||||||
compile,
|
|
||||||
computed,
|
|
||||||
createApp,
|
|
||||||
createBaseVNode,
|
|
||||||
createBlock,
|
|
||||||
createCommentVNode,
|
|
||||||
createElementBlock,
|
|
||||||
createHydrationRenderer,
|
|
||||||
createPropsRestProxy,
|
|
||||||
createRenderer,
|
|
||||||
createSSRApp,
|
|
||||||
createSlots,
|
|
||||||
createStaticVNode,
|
|
||||||
createTextVNode,
|
|
||||||
createVNode,
|
|
||||||
customRef,
|
|
||||||
defineAsyncComponent,
|
|
||||||
defineComponent,
|
|
||||||
defineCustomElement,
|
|
||||||
defineEmits,
|
|
||||||
defineExpose,
|
|
||||||
defineModel,
|
|
||||||
defineOptions,
|
|
||||||
defineProps,
|
|
||||||
defineSSRCustomElement,
|
|
||||||
defineSlots,
|
|
||||||
devtools,
|
|
||||||
effect,
|
|
||||||
effectScope,
|
|
||||||
getCurrentInstance,
|
|
||||||
getCurrentScope,
|
|
||||||
getCurrentWatcher,
|
|
||||||
getTransitionRawChildren,
|
|
||||||
guardReactiveProps,
|
|
||||||
h,
|
|
||||||
handleError,
|
|
||||||
hasInjectionContext,
|
|
||||||
hydrate,
|
|
||||||
hydrateOnIdle,
|
|
||||||
hydrateOnInteraction,
|
|
||||||
hydrateOnMediaQuery,
|
|
||||||
hydrateOnVisible,
|
|
||||||
initCustomFormatter,
|
|
||||||
initDirectivesForSSR,
|
|
||||||
inject,
|
|
||||||
isMemoSame,
|
|
||||||
isProxy,
|
|
||||||
isReactive,
|
|
||||||
isReadonly,
|
|
||||||
isRef,
|
|
||||||
isRuntimeOnly,
|
|
||||||
isShallow,
|
|
||||||
isVNode,
|
|
||||||
markRaw,
|
|
||||||
mergeDefaults,
|
|
||||||
mergeModels,
|
|
||||||
mergeProps,
|
|
||||||
nextTick,
|
|
||||||
nodeOps,
|
|
||||||
normalizeClass,
|
|
||||||
normalizeProps,
|
|
||||||
normalizeStyle,
|
|
||||||
onActivated,
|
|
||||||
onBeforeMount,
|
|
||||||
onBeforeUnmount,
|
|
||||||
onBeforeUpdate,
|
|
||||||
onDeactivated,
|
|
||||||
onErrorCaptured,
|
|
||||||
onMounted,
|
|
||||||
onRenderTracked,
|
|
||||||
onRenderTriggered,
|
|
||||||
onScopeDispose,
|
|
||||||
onServerPrefetch,
|
|
||||||
onUnmounted,
|
|
||||||
onUpdated,
|
|
||||||
onWatcherCleanup,
|
|
||||||
openBlock,
|
|
||||||
patchProp,
|
|
||||||
popScopeId,
|
|
||||||
provide,
|
|
||||||
proxyRefs,
|
|
||||||
pushScopeId,
|
|
||||||
queuePostFlushCb,
|
|
||||||
reactive,
|
|
||||||
readonly,
|
|
||||||
ref,
|
|
||||||
registerRuntimeCompiler,
|
|
||||||
render,
|
|
||||||
renderList,
|
|
||||||
renderSlot,
|
|
||||||
resolveComponent,
|
|
||||||
resolveDirective,
|
|
||||||
resolveDynamicComponent,
|
|
||||||
resolveFilter,
|
|
||||||
resolveTransitionHooks,
|
|
||||||
setBlockTracking,
|
|
||||||
setDevtoolsHook,
|
|
||||||
setTransitionHooks,
|
|
||||||
shallowReactive,
|
|
||||||
shallowReadonly,
|
|
||||||
shallowRef,
|
|
||||||
ssrContextKey,
|
|
||||||
ssrUtils,
|
|
||||||
stop,
|
|
||||||
toDisplayString,
|
|
||||||
toHandlerKey,
|
|
||||||
toHandlers,
|
|
||||||
toRaw,
|
|
||||||
toRef,
|
|
||||||
toRefs,
|
|
||||||
toValue,
|
|
||||||
transformVNodeArgs,
|
|
||||||
triggerRef,
|
|
||||||
unref,
|
|
||||||
useAttrs,
|
|
||||||
useCssModule,
|
|
||||||
useCssVars,
|
|
||||||
useHost,
|
|
||||||
useId,
|
|
||||||
useModel,
|
|
||||||
useSSRContext,
|
|
||||||
useShadowRoot,
|
|
||||||
useSlots,
|
|
||||||
useTemplateRef,
|
|
||||||
useTransitionState,
|
|
||||||
vModelCheckbox,
|
|
||||||
vModelDynamic,
|
|
||||||
vModelRadio,
|
|
||||||
vModelSelect,
|
|
||||||
vModelText,
|
|
||||||
vShow,
|
|
||||||
version,
|
|
||||||
warn,
|
|
||||||
watch,
|
|
||||||
watchEffect,
|
|
||||||
watchPostEffect,
|
|
||||||
watchSyncEffect,
|
|
||||||
withAsyncContext,
|
|
||||||
withCtx,
|
|
||||||
withDefaults,
|
|
||||||
withDirectives,
|
|
||||||
withKeys,
|
|
||||||
withMemo,
|
|
||||||
withModifiers,
|
|
||||||
withScopeId
|
|
||||||
} from "./chunk-H6MPEGKE.js";
|
|
||||||
export {
|
|
||||||
BaseTransition,
|
|
||||||
BaseTransitionPropsValidators,
|
|
||||||
Comment,
|
|
||||||
DeprecationTypes,
|
|
||||||
EffectScope,
|
|
||||||
ErrorCodes,
|
|
||||||
ErrorTypeStrings,
|
|
||||||
Fragment,
|
|
||||||
KeepAlive,
|
|
||||||
ReactiveEffect,
|
|
||||||
Static,
|
|
||||||
Suspense,
|
|
||||||
Teleport,
|
|
||||||
Text,
|
|
||||||
TrackOpTypes,
|
|
||||||
Transition,
|
|
||||||
TransitionGroup,
|
|
||||||
TriggerOpTypes,
|
|
||||||
VueElement,
|
|
||||||
assertNumber,
|
|
||||||
callWithAsyncErrorHandling,
|
|
||||||
callWithErrorHandling,
|
|
||||||
camelize,
|
|
||||||
capitalize,
|
|
||||||
cloneVNode,
|
|
||||||
compatUtils,
|
|
||||||
compile,
|
|
||||||
computed,
|
|
||||||
createApp,
|
|
||||||
createBlock,
|
|
||||||
createCommentVNode,
|
|
||||||
createElementBlock,
|
|
||||||
createBaseVNode as createElementVNode,
|
|
||||||
createHydrationRenderer,
|
|
||||||
createPropsRestProxy,
|
|
||||||
createRenderer,
|
|
||||||
createSSRApp,
|
|
||||||
createSlots,
|
|
||||||
createStaticVNode,
|
|
||||||
createTextVNode,
|
|
||||||
createVNode,
|
|
||||||
customRef,
|
|
||||||
defineAsyncComponent,
|
|
||||||
defineComponent,
|
|
||||||
defineCustomElement,
|
|
||||||
defineEmits,
|
|
||||||
defineExpose,
|
|
||||||
defineModel,
|
|
||||||
defineOptions,
|
|
||||||
defineProps,
|
|
||||||
defineSSRCustomElement,
|
|
||||||
defineSlots,
|
|
||||||
devtools,
|
|
||||||
effect,
|
|
||||||
effectScope,
|
|
||||||
getCurrentInstance,
|
|
||||||
getCurrentScope,
|
|
||||||
getCurrentWatcher,
|
|
||||||
getTransitionRawChildren,
|
|
||||||
guardReactiveProps,
|
|
||||||
h,
|
|
||||||
handleError,
|
|
||||||
hasInjectionContext,
|
|
||||||
hydrate,
|
|
||||||
hydrateOnIdle,
|
|
||||||
hydrateOnInteraction,
|
|
||||||
hydrateOnMediaQuery,
|
|
||||||
hydrateOnVisible,
|
|
||||||
initCustomFormatter,
|
|
||||||
initDirectivesForSSR,
|
|
||||||
inject,
|
|
||||||
isMemoSame,
|
|
||||||
isProxy,
|
|
||||||
isReactive,
|
|
||||||
isReadonly,
|
|
||||||
isRef,
|
|
||||||
isRuntimeOnly,
|
|
||||||
isShallow,
|
|
||||||
isVNode,
|
|
||||||
markRaw,
|
|
||||||
mergeDefaults,
|
|
||||||
mergeModels,
|
|
||||||
mergeProps,
|
|
||||||
nextTick,
|
|
||||||
nodeOps,
|
|
||||||
normalizeClass,
|
|
||||||
normalizeProps,
|
|
||||||
normalizeStyle,
|
|
||||||
onActivated,
|
|
||||||
onBeforeMount,
|
|
||||||
onBeforeUnmount,
|
|
||||||
onBeforeUpdate,
|
|
||||||
onDeactivated,
|
|
||||||
onErrorCaptured,
|
|
||||||
onMounted,
|
|
||||||
onRenderTracked,
|
|
||||||
onRenderTriggered,
|
|
||||||
onScopeDispose,
|
|
||||||
onServerPrefetch,
|
|
||||||
onUnmounted,
|
|
||||||
onUpdated,
|
|
||||||
onWatcherCleanup,
|
|
||||||
openBlock,
|
|
||||||
patchProp,
|
|
||||||
popScopeId,
|
|
||||||
provide,
|
|
||||||
proxyRefs,
|
|
||||||
pushScopeId,
|
|
||||||
queuePostFlushCb,
|
|
||||||
reactive,
|
|
||||||
readonly,
|
|
||||||
ref,
|
|
||||||
registerRuntimeCompiler,
|
|
||||||
render,
|
|
||||||
renderList,
|
|
||||||
renderSlot,
|
|
||||||
resolveComponent,
|
|
||||||
resolveDirective,
|
|
||||||
resolveDynamicComponent,
|
|
||||||
resolveFilter,
|
|
||||||
resolveTransitionHooks,
|
|
||||||
setBlockTracking,
|
|
||||||
setDevtoolsHook,
|
|
||||||
setTransitionHooks,
|
|
||||||
shallowReactive,
|
|
||||||
shallowReadonly,
|
|
||||||
shallowRef,
|
|
||||||
ssrContextKey,
|
|
||||||
ssrUtils,
|
|
||||||
stop,
|
|
||||||
toDisplayString,
|
|
||||||
toHandlerKey,
|
|
||||||
toHandlers,
|
|
||||||
toRaw,
|
|
||||||
toRef,
|
|
||||||
toRefs,
|
|
||||||
toValue,
|
|
||||||
transformVNodeArgs,
|
|
||||||
triggerRef,
|
|
||||||
unref,
|
|
||||||
useAttrs,
|
|
||||||
useCssModule,
|
|
||||||
useCssVars,
|
|
||||||
useHost,
|
|
||||||
useId,
|
|
||||||
useModel,
|
|
||||||
useSSRContext,
|
|
||||||
useShadowRoot,
|
|
||||||
useSlots,
|
|
||||||
useTemplateRef,
|
|
||||||
useTransitionState,
|
|
||||||
vModelCheckbox,
|
|
||||||
vModelDynamic,
|
|
||||||
vModelRadio,
|
|
||||||
vModelSelect,
|
|
||||||
vModelText,
|
|
||||||
vShow,
|
|
||||||
version,
|
|
||||||
warn,
|
|
||||||
watch,
|
|
||||||
watchEffect,
|
|
||||||
watchPostEffect,
|
|
||||||
watchSyncEffect,
|
|
||||||
withAsyncContext,
|
|
||||||
withCtx,
|
|
||||||
withDefaults,
|
|
||||||
withDirectives,
|
|
||||||
withKeys,
|
|
||||||
withMemo,
|
|
||||||
withModifiers,
|
|
||||||
withScopeId
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=vue.js.map
|
|
||||||
7
docs/.vitepress/cache/deps/vue.js.map
vendored
7
docs/.vitepress/cache/deps/vue.js.map
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"sources": [],
|
|
||||||
"sourcesContent": [],
|
|
||||||
"mappings": "",
|
|
||||||
"names": []
|
|
||||||
}
|
|
||||||
54
plan-refactor.md
Normal file
54
plan-refactor.md
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Refactor Plan — Architecture Cleanup
|
||||||
|
|
||||||
|
## Status: DONE ✓
|
||||||
|
|
||||||
|
## 1. tools/schema.ts cleanup [P0] ✓
|
||||||
|
- Deleted all duplicate tool definitions from schema.ts: 1831 → 65 lines
|
||||||
|
- Fixed tools/index.ts to export ALL_TOOLS from registry
|
||||||
|
- Fixed renderJsx → renderJSX typo in create.ts and structure.ts
|
||||||
|
|
||||||
|
## 2. geometry.ts extraction [P0] ✓
|
||||||
|
- Created packages/core/src/geometry.ts with degToRad, radToDeg, rotatePoint, rotatedCorners, rotatedBBox
|
||||||
|
- Exported from core index.ts
|
||||||
|
- Consumer refactoring (snap.ts, kiwi-serialize.ts, use-canvas-input.ts) deferred — functions available for new code
|
||||||
|
|
||||||
|
## 3. renderer/ directory split [P1] ✓
|
||||||
|
- Split 3206-line renderer.ts into renderer/ directory (10 files)
|
||||||
|
- renderer.ts (1144) — class with delegations, constructor, render(), loadFonts(), surface mgmt
|
||||||
|
- overlays.ts (760) — selection, hover, snap, marquee, flashes, pen, remote cursors, text edit overlay
|
||||||
|
- scene.ts (490) — node rendering pipeline, effects, text
|
||||||
|
- rulers.ts (235) — ruler drawing and badges
|
||||||
|
- fills.ts (233) — fill application, gradients, images, arcs
|
||||||
|
- strokes.ts (221) — stroke drawing with alignment
|
||||||
|
- labels.ts (212) — section titles and component labels
|
||||||
|
- shapes.ts (193) — path/shape creation and geometry caching
|
||||||
|
- effects.ts (64) — image/mask filter caching
|
||||||
|
|
||||||
|
## 4. isMixed() helper [P1] ✓
|
||||||
|
- Added isArrayMixed() to use-multi-props.ts
|
||||||
|
- Deduplicated FillSection, StrokeSection, EffectsSection (each lost 4 lines of boilerplate)
|
||||||
|
|
||||||
|
## 5. Test imports cleanup ✓
|
||||||
|
- All tests now use `@open-pencil/core` instead of relative paths into packages/core/src/
|
||||||
|
- Merged duplicate import statements across all test files
|
||||||
|
- Fixed 3 broken test imports (stale paths to src/engine/ and src/kiwi/)
|
||||||
|
- Exported profiler internals and style-run helpers from core index.ts
|
||||||
|
|
||||||
|
## 6. Test coverage [P0-P1] ✓
|
||||||
|
New test files (98 new tests, 683 total → all green):
|
||||||
|
- color.test.ts — parseColor, colorToHex, colorToCSS (14 tests)
|
||||||
|
- undo.test.ts — UndoManager apply/push/undo/redo/batch/clear (12 tests)
|
||||||
|
- snap.test.ts — computeSnap, computeSelectionBounds (9 tests)
|
||||||
|
- vector.test.ts — vectorNetworkBlob round-trip, computeVectorBounds (10 tests)
|
||||||
|
- style-runs.test.ts — toggleBold/Italic/Decoration, adjustRuns, applyStyle (18 tests)
|
||||||
|
- text-editor.test.ts — insert/delete/cursor/selection/word ops (25 tests)
|
||||||
|
|
||||||
|
## 7. Bug fixes (found during audit) ✓
|
||||||
|
- renderJsx → renderJSX typo in tools/create.ts and tools/structure.ts
|
||||||
|
- 3 broken test file imports (stale paths after monorepo reorganization)
|
||||||
|
|
||||||
|
## Future work (not in this batch)
|
||||||
|
- Refactor consumers to use geometry.ts (snap.ts, kiwi-serialize.ts, use-canvas-input.ts)
|
||||||
|
- Split editor.ts store into sub-composables (~2184 lines, 91 functions)
|
||||||
|
- Split use-canvas-input.ts drag handlers (~1298 lines)
|
||||||
|
- Unify decompress utilities (kiwi-serialize.ts vs kiwi/codec.ts)
|
||||||
|
|
@ -140,35 +140,34 @@ export function useCollab(store: EditorStore) {
|
||||||
sendYjsUpdate?.(update)
|
sendYjsUpdate?.(update)
|
||||||
})
|
})
|
||||||
|
|
||||||
awareness.on(
|
const localAwareness = awareness
|
||||||
|
const localYdoc = ydoc
|
||||||
|
|
||||||
|
localAwareness.on(
|
||||||
'update',
|
'update',
|
||||||
({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => {
|
({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => {
|
||||||
const changedClients = [...added, ...updated, ...removed]
|
const changedClients = [...added, ...updated, ...removed]
|
||||||
const encodedUpdate = awarenessProtocol.encodeAwarenessUpdate(awareness!, changedClients)
|
const encodedUpdate = awarenessProtocol.encodeAwarenessUpdate(localAwareness, changedClients)
|
||||||
sendAwareness?.(encodedUpdate)
|
sendAwareness?.(encodedUpdate)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
room.onPeerJoin((peerId) => {
|
room.onPeerJoin((peerId) => {
|
||||||
state.value.connected = true
|
state.value.connected = true
|
||||||
const sv = Y.encodeStateVector(ydoc!)
|
const sv = Y.encodeStateVector(localYdoc)
|
||||||
sendSyncStep1?.(sv, peerId)
|
sendSyncStep1?.(sv, peerId)
|
||||||
|
|
||||||
if (awareness) {
|
const encodedUpdate = awarenessProtocol.encodeAwarenessUpdate(localAwareness, [
|
||||||
const encodedUpdate = awarenessProtocol.encodeAwarenessUpdate(awareness, [
|
localAwareness.clientID
|
||||||
awareness.clientID
|
|
||||||
])
|
])
|
||||||
sendAwareness?.(encodedUpdate, peerId)
|
sendAwareness?.(encodedUpdate, peerId)
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
room.onPeerLeave(() => {
|
room.onPeerLeave(() => {
|
||||||
if (awareness) {
|
const remoteClients = [...localAwareness.getStates().keys()].filter(
|
||||||
const remoteClients = [...awareness.getStates().keys()].filter(
|
(id) => id !== localAwareness.clientID
|
||||||
(id) => id !== awareness!.clientID
|
|
||||||
)
|
)
|
||||||
awarenessProtocol.removeAwarenessStates(awareness, remoteClients, 'peer-left')
|
awarenessProtocol.removeAwarenessStates(localAwareness, remoteClients, 'peer-left')
|
||||||
}
|
|
||||||
updatePeersList()
|
updatePeersList()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -229,12 +228,13 @@ export function useCollab(store: EditorStore) {
|
||||||
const node = store.graph.getNode(nodeId)
|
const node = store.graph.getNode(nodeId)
|
||||||
if (!node) return
|
if (!node) return
|
||||||
|
|
||||||
|
const localYnodes = ynodes
|
||||||
suppressYjsEvents = true
|
suppressYjsEvents = true
|
||||||
ydoc.transact(() => {
|
ydoc.transact(() => {
|
||||||
let ynode = ynodes!.get(nodeId)
|
let ynode = localYnodes.get(nodeId)
|
||||||
if (!ynode) {
|
if (!ynode) {
|
||||||
ynode = new Y.Map()
|
ynode = new Y.Map()
|
||||||
ynodes!.set(nodeId, ynode)
|
localYnodes.set(nodeId, ynode)
|
||||||
}
|
}
|
||||||
syncNodePropsToYMap(node, ynode)
|
syncNodePropsToYMap(node, ynode)
|
||||||
})
|
})
|
||||||
|
|
@ -253,13 +253,14 @@ export function useCollab(store: EditorStore) {
|
||||||
|
|
||||||
function syncAllNodesToYjs() {
|
function syncAllNodesToYjs() {
|
||||||
if (!ydoc || !ynodes) return
|
if (!ydoc || !ynodes) return
|
||||||
|
const localYnodes = ynodes
|
||||||
suppressYjsEvents = true
|
suppressYjsEvents = true
|
||||||
ydoc.transact(() => {
|
ydoc.transact(() => {
|
||||||
for (const node of store.graph.getAllNodes()) {
|
for (const node of store.graph.getAllNodes()) {
|
||||||
let ynode = ynodes!.get(node.id)
|
let ynode = localYnodes.get(node.id)
|
||||||
if (!ynode) {
|
if (!ynode) {
|
||||||
ynode = new Y.Map()
|
ynode = new Y.Map()
|
||||||
ynodes!.set(node.id, ynode)
|
localYnodes.set(node.id, ynode)
|
||||||
}
|
}
|
||||||
syncNodePropsToYMap(node, ynode)
|
syncNodePropsToYMap(node, ynode)
|
||||||
}
|
}
|
||||||
|
|
@ -268,20 +269,22 @@ export function useCollab(store: EditorStore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyYjsToGraph(events: Y.YEvent<Y.Map<unknown>>[]) {
|
function applyYjsToGraph(events: Y.YEvent<Y.Map<unknown>>[]) {
|
||||||
|
if (!ynodes) return
|
||||||
|
const localYnodes = ynodes
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
if (event.target === ynodes) {
|
if (event.target === localYnodes) {
|
||||||
for (const [key, change] of event.changes.keys) {
|
for (const [key, change] of event.changes.keys) {
|
||||||
if (change.action === 'add') {
|
if (change.action === 'add') {
|
||||||
const ynode = ynodes!.get(key)
|
const ynode = localYnodes.get(key)
|
||||||
if (ynode) applyYnodeToGraph(key, ynode)
|
if (ynode) applyYnodeToGraph(key, ynode)
|
||||||
} else if (change.action === 'delete') {
|
} else if (change.action === 'delete') {
|
||||||
store.graph.deleteNode(key)
|
store.graph.deleteNode(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (event.target.parent === ynodes) {
|
} else if (event.target.parent === localYnodes) {
|
||||||
const nodeId = findNodeIdForYMap(event.target as Y.Map<unknown>)
|
const nodeId = findNodeIdForYMap(event.target as Y.Map<unknown>)
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
const ynode = ynodes!.get(nodeId)
|
const ynode = localYnodes.get(nodeId)
|
||||||
if (ynode) applyYnodeToGraph(nodeId, ynode)
|
if (ynode) applyYnodeToGraph(nodeId, ynode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -367,13 +370,16 @@ export function useCollab(store: EditorStore) {
|
||||||
state.value.peers = peers
|
state.value.peers = peers
|
||||||
store.state.remoteCursors = peers
|
store.state.remoteCursors = peers
|
||||||
.filter((p) => p.cursor && p.cursor.pageId === currentPageId)
|
.filter((p) => p.cursor && p.cursor.pageId === currentPageId)
|
||||||
.map((p) => ({
|
.map((p) => {
|
||||||
|
const cursor = p.cursor as NonNullable<RemotePeer['cursor']>
|
||||||
|
return {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
color: p.color,
|
color: p.color,
|
||||||
x: p.cursor!.x,
|
x: cursor.x,
|
||||||
y: p.cursor!.y,
|
y: cursor.y,
|
||||||
selection: p.selection
|
selection: p.selection
|
||||||
}))
|
}
|
||||||
|
})
|
||||||
store.requestRender()
|
store.requestRender()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue