├── .vscode
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── api.ts
├── assets
├── icons
│ ├── folder-minus.svg
│ ├── folder-plus.svg
│ ├── navigation-2.svg
│ ├── refresh-cw.svg
│ └── x-circle.svg
├── sortable-tree
│ ├── sortable-tree.css
│ └── sortable-tree.js
├── treeview.css
└── treeview.js
├── config.ts
├── deno.json
├── deno.lock
├── filters
├── filterByFunction.ts
├── filterByRegex.ts
└── filterByTags.ts
├── screenshot-action-button.png
├── screenshot-dark.png
├── screenshot.png
├── treeview.plug.js
├── treeview.plug.yaml
└── treeview.ts
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "deno.enable": true,
3 | "editor.formatOnSave": true,
4 | "deno.importMap": "import_map.json",
5 | "deno.config": "deno.json",
6 | "[json]": {
7 | "editor.defaultFormatter": "denoland.vscode-deno"
8 | },
9 | "[jsonc]": {
10 | "editor.defaultFormatter": "denoland.vscode-deno"
11 | },
12 | "[markdown]": {
13 | "editor.formatOnSave": false
14 | },
15 | "[typescript]": {
16 | "editor.defaultFormatter": "denoland.vscode-deno"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | * Nothing since 0.15
11 |
12 | ## [0.15] - 2025-03-26
13 |
14 | ### Changed
15 |
16 | * Upgrade plug to modern standards to work with both SilverBullet 0.10.x and v2. (by [@zefhemel](https://github.com/joekrill/silverbullet-treeview/pull/29))
17 |
18 | ## [0.14] - 2024-07-29
19 |
20 | ### Changed
21 |
22 | * Removed temporary workaround for injecting the current theme in the tree view panel (no longer needed)
23 |
24 | ## [0.13] - 2024-07-23
25 |
26 | ### Fixed
27 |
28 | * Fix incorrect negation logic when applying regex exclusions
29 |
30 | ## [0.12] - 2024-07-23
31 |
32 | ### Added
33 |
34 | * `exclusions` configuration option that allows multiple exclusions rules to filter what is displayed in the treeview based on regex, tags, or a custom space function.
35 | * Use a prefix when using `console.error` to make it clear that the error originated from the TreeView plug.
36 |
37 | ### Deprecated
38 |
39 | * The `pageExcludeRegex` configuration option is deprected in favor or using an exclusion rule of `type: "regex"`, instead.
40 |
41 | ## [0.11] - 2024-07-15
42 |
43 | ### Added
44 |
45 | * Allow excluding pages based on a user-provided regex (by [@djm2k](https://github.com/joekrill/silverbullet-treeview/pull/16))
46 |
47 | ## [0.10] - 2024-04-20
48 |
49 | ### Fixed
50 |
51 | * Fix `sortable-tree` library throwing errors on state load (by [@MrMugame](https://github.com/joekrill/silverbullet-treeview/pull/14))
52 | * Use correct events
53 |
54 |
55 | ## [0.9] - 2024-03-19
56 |
57 | ### Fixed
58 |
59 | * Fix error when `page:deleted` event is triggered ([#11](https://github.com/joekrill/silverbullet-treeview/issues/11))
60 |
61 |
62 | ## [0.8] - 2024-02-26
63 |
64 | ### Fixed
65 |
66 | * `clientStore` being called on the server-side was causing SilverBullet to crash ([SB#772](https://github.com/silverbulletmd/silverbullet/issues/772))
67 |
68 | ### Added
69 |
70 | * Include [custom styles](https://silverbullet.md/STYLES) in tree panel (requires SilverBullet 0.7.2 or greater).
71 |
72 | ### Fixed
73 |
74 | * Fix header button tooltips ([#9](https://github.com/joekrill/silverbullet-treeview/pull/9))
75 | * Wrap toolbar items when necessary on smaller screens ([#6](https://github.com/joekrill/silverbullet-treeview/issues/6))
76 |
77 | ## [0.7] - 2024-02-20
78 |
79 | ### Fixed
80 |
81 | * Include the main SilverBullet stylesheet when rendering the treeview so we can access the CSS variables (previously these were duplicated and hard-coded into the plug)
82 |
83 |
84 | ## [0.6] - 2024-02-18
85 |
86 | ### Fixed
87 |
88 | * Refresh the tree when a page is deleted.
89 |
90 |
91 | ## [0.5] - 2024-02-18
92 |
93 | ### Added
94 |
95 | * Drag-and-drop support. Nodes can be dragged to move/rename pages.
96 |
97 |
98 | ## [0.4] - 2024-02-17
99 |
100 | ### Added
101 |
102 | * README dark mode screenshot.
103 | * README instructions for adding treeview toggle as an action button.
104 |
105 | ### Fixed
106 |
107 | * Fix an error in the initialization retry code which can be triggered if the local treeview UI state is invalid.
108 |
109 | ## [0.3] - 2024-02-17
110 |
111 | ### Fixed
112 |
113 | * Disable drag-and-drop functionality in the UI (it isn't implemented yet).
114 |
115 | ## [0.2] - 2024-02-16
116 |
117 | ### Fixed
118 |
119 | * An error was being incorrectly shown if there was no `treeview` settings in the `SETTINGS` page.
120 |
121 | ## [0.1] - 2024-02-16
122 |
123 | ### Added
124 |
125 | * Initial Release.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Joe Krill
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # SilverBullet TreeView plug
3 |
4 | This plugs adds a tree view that allows you to navigate your SilverBullet pages Hierarchically.
5 |
6 |
7 |
8 |
9 |
10 | Dragging-and-dropping files and folders is supported but requires SilverBullet v0.7.2 or greater. If running < v0.7.2, this feature will be automatically disabled (regardless of [configuration](#configuration)).
11 |
12 | ## Installation
13 |
14 | Use the `Plugs: Add` command and enter the following URI:
15 |
16 | `github:joekrill/silverbullet-treeview/treeview.plug.js`
17 |
18 | _or_
19 |
20 | Open (`cmd+k`) your `PLUGS` note in SilverBullet and add this plug to the list:
21 |
22 | ```yaml
23 | - github:joekrill/silverbullet-treeview/treeview.plug.js
24 | ```
25 |
26 | Then run the `Plugs: Update` command and off you go!
27 |
28 | ## Configuration
29 |
30 | This plug can be configured using the `SETTINGS` page (default values shown):
31 |
32 | ```yaml
33 | treeview:
34 | # Determines where the panel is displayed:
35 | # - "lhs" - left hand side
36 | # - "rhs" - right hand side
37 | # - "bhs" - bottom
38 | # - "modal" - in a modal
39 | position: lhs
40 |
41 | # Must be > 0.
42 | # position = "lhs" | "rhs": determines the width of the panel.
43 | # position = "modal": sets the margin around the modal window.
44 | # position = "bhs": No effect
45 | size: 1
46 |
47 | dragAndDrop:
48 | # Set to false to disable drag-and-drop
49 | enabled: true
50 |
51 | # Set to false to disable the confirmation prompt shown when dragging and
52 | # dropping pages that causes them to be renamed/moved.
53 | confirmOnRename: true
54 |
55 | # An array of exclusion rules that will exclude pages from being
56 | # displayed in the sidebar.
57 | exclusions:
58 |
59 | # Filter by regular expression:
60 | - type: "regex"
61 | # Regular Expression string to exclude pages from the tree
62 | # Examples:
63 | # - Any page that is all-caps: "^[A-Z]+$"
64 | # - A specific set of pages: "^(?:SETTINGS|PLUGS|index|Library)$"
65 | # - Any path containing Hidden (e.g. test/Hidden/page1): "Hidden"
66 | rule: "^(?:SETTINGS|PLUGS|index|Library)$"
67 | # Optional: set to true to negate the rule, only showing pages that match this regex.
68 | negate: false
69 |
70 | # Filter by page tags:
71 | - type: "tags"
72 | tags: ["meta"]
73 | # Optional: set to true to negate the rule, only showing pages that include any of the tags.
74 | negate: false
75 |
76 | # Filter by a space function (see "Filtering by custom function example", below)
77 | - type: "space-function"
78 | name: "myCustomFilterFunction"
79 | # Optional: set to true to negate the rule, only showing pages for which the function returns false
80 | negate: false
81 |
82 | # This setting has been deprected - use an `exclusion` rule of `type: regec` instead.
83 | pageExcludeRegex: "^(?:SETTINGS|PLUGS|index|Library)$"
84 | ```
85 |
86 | ### Adding a top bar toggle icon
87 |
88 | 
89 |
90 | You can add add a button to the top bar that will toggle the tree view by adding
91 | the following to your `actionButtons` array in your `SETTINGS` page:
92 |
93 | ```yaml
94 | actionButtons:
95 | - icon: sidebar
96 | command: "{[Tree View: Toggle]}"
97 | description: "Toggle Tree View"
98 | ```
99 |
100 | ### Filtering by custom function example
101 |
102 | Using an exclusion rule with `type: "space-function"` allows you to write your own logic around which pages to show in the tree view. The function will be called with the page object as the first and only parameter.
103 |
104 | As an example, we could create a function that excludes daily journal pages
105 | that are older than 7 days.
106 |
107 | 1. Create a space script which defines the filter logic:
108 |
109 | ````
110 | ```space-script
111 | silverbullet.registerFunction({name: "filterOldDailyNotes"}, async (page) => {
112 | if (!page.name.startsWith("Journal/Day/")) {
113 | // If it's not a daily journal page, don't exclude it.
114 | return false;
115 | }
116 |
117 | // Extract the date part from the page name and parse it
118 | const datePart = page.name.split("/")[2];
119 | const parsedDate = Temporal.PlainDate.from(datePart);
120 | const timeSince = Temporal.Now.plainDateISO().since(parsedDate, { largestUnit: 'days' });
121 |
122 | return timeSince.days > 7;
123 | });
124 | ```
125 | ````
126 |
127 | 2. Add the exclusion rule to the `SETTINGS` page:
128 |
129 | ```yaml
130 | treeview:
131 | exclusions:
132 | - type: "space-function"
133 | name: "filterOldDailyNotes"
134 | ```
135 |
136 |
137 | ## Build
138 |
139 | To build this plug, make sure you have [SilverBullet installed](https://silverbullet.md/Install). Then, build the plug with:
140 |
141 | ```shell
142 | deno task build
143 | ```
144 |
145 | Or to watch for changes and rebuild automatically
146 |
147 | ```shell
148 | deno task watch
149 | ```
150 |
151 | Then, copy the resulting `.plug.js` file into your space's `_plug` folder. Or build and copy in one command:
152 |
153 | ```shell
154 | deno task build && cp *.plug.js /my/space/_plug/
155 | ```
156 |
157 | SilverBullet will automatically sync and load the new version of the plug (or speed up this process by running the {[Sync: Now]} command).
158 |
159 | ## Development
160 |
161 | ### `SortableTree`
162 |
163 | The tree component used is Marc Anton Dahmen's [SortableTree](https://marcantondahmen.github.io/sortable-tree) component ([Github Repo](https://github.com/marcantondahmen/sortable-tree)).
164 |
165 | Latest build files can be found here (replace them in `assets/sortable-tree` to upgrade):
166 |
167 | - https://unpkg.com/sortable-tree/dist/sortable-tree.js
168 | - https://unpkg.com/sortable-tree/dist/sortable-tree.css
169 |
--------------------------------------------------------------------------------
/api.ts:
--------------------------------------------------------------------------------
1 | import { editor, system } from "@silverbulletmd/silverbullet/syscalls";
2 | import { PageMeta } from "@silverbulletmd/silverbullet/types";
3 | import { PLUG_DISPLAY_NAME, TreeViewConfig } from "./config.ts";
4 | import { filterPagesByFunction } from "./filters/filterByFunction.ts";
5 | import { filterPagesByRegex } from "./filters/filterByRegex.ts";
6 | import { filterPagesByTags } from "./filters/filterByTags.ts";
7 |
8 | export type NodeData = {
9 | /**
10 | * The complete page or folder name.
11 | */
12 | name: string;
13 |
14 | /**
15 | * The name to display in the node to the user (generally the last
16 | * portion of the `name`)
17 | */
18 | title: string;
19 |
20 | /**
21 | * True if this node represents the current active page
22 | */
23 | isCurrentPage?: boolean;
24 |
25 | nodeType: string;
26 | };
27 |
28 | export type PageData = PageMeta & NodeData & {
29 | nodeType: "page";
30 | };
31 |
32 | export type FolderData = NodeData & {
33 | nodeType: "folder";
34 | };
35 |
36 | export type TreeNode = {
37 | data: PageData | FolderData;
38 | nodes: TreeNode[];
39 | };
40 |
41 | /**
42 | * Generates a TreeNode array from the list of pages in the current space.
43 | */
44 | export async function getPageTree(config: TreeViewConfig) {
45 | const currentPage = await editor.getCurrentPage();
46 | // The index plug's `queryObjects` function is used so that we include the
47 | // page tags -- `space.listPages()` does not populate those attributes.
48 | let pages = await system.invokeFunction(
49 | "index.queryLuaObjects",
50 | "page",
51 | {},
52 | ) as PageMeta[];
53 |
54 | const root = { nodes: [] as TreeNode[] };
55 |
56 | if (config.pageExcludeRegex) {
57 | const deprecationWarning = `${PLUG_DISPLAY_NAME}:
58 | \`pageExcludeRegex\` setting is deprecated. Please use \`exclusions\`:
59 |
60 | \`\`\`yaml
61 | treeview:
62 | exclusions:
63 | - type: regex
64 | rule: "${config.pageExcludeRegex}"
65 | \`\`\`
66 | `;
67 | console.warn(deprecationWarning);
68 | pages = filterPagesByRegex(pages, {
69 | rule: config.pageExcludeRegex,
70 | negate: false,
71 | });
72 | }
73 |
74 | if (config.exclusions) {
75 | for (const exclusion of config.exclusions) {
76 | switch (exclusion.type) {
77 | case "regex": {
78 | pages = filterPagesByRegex(pages, exclusion);
79 | break;
80 | }
81 | case "tags": {
82 | pages = filterPagesByTags(pages, exclusion);
83 | break;
84 | }
85 | case "space-function": {
86 | pages = await filterPagesByFunction(pages, exclusion);
87 | break;
88 | }
89 | }
90 | }
91 | }
92 |
93 | pages.sort((a, b) => a.name.localeCompare(b.name));
94 |
95 | pages.forEach((page) => {
96 | page.name.split("/").reduce((parent, title, currentIndex, parts) => {
97 | const isLeaf = parts.length - 1 === currentIndex;
98 | let node = parent.nodes.find((child) => child.data.title === title);
99 | if (node) {
100 | if (isLeaf && !("created" in node.data)) {
101 | // The node was found but is currently identified as a "folder",
102 | // so we need to change it to a "page" type.
103 | node.data = {
104 | ...page,
105 | title,
106 | isCurrentPage: currentPage === page.name,
107 | nodeType: "page",
108 | };
109 | }
110 | return node;
111 | }
112 |
113 | if (isLeaf) {
114 | // We're at the last part of the page name, so this reprents the page itself.
115 | node = {
116 | data: {
117 | ...page,
118 | title,
119 | isCurrentPage: currentPage === page.name,
120 | nodeType: "page",
121 | },
122 | nodes: [],
123 | };
124 | } else {
125 | // This is an intermediate part of the page name and a node doesn't exist
126 | // yet, so this represents a "folder" (and may be converted to a page
127 | // at some later iteration, if the page is found)
128 | const name = parts.slice(0, currentIndex + 1).join("/");
129 | node = {
130 | data: {
131 | title,
132 | // A folder can still be the "current page" if it's being created
133 | isCurrentPage: currentPage === name,
134 | name,
135 | nodeType: "folder",
136 | },
137 | nodes: [],
138 | };
139 | }
140 |
141 | parent.nodes.push(node);
142 | return node;
143 | }, root);
144 | });
145 |
146 | return {
147 | nodes: root.nodes,
148 | currentPage,
149 | };
150 | }
151 |
--------------------------------------------------------------------------------
/assets/icons/folder-minus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icons/folder-plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icons/navigation-2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icons/refresh-cw.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icons/x-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/sortable-tree/sortable-tree.css:
--------------------------------------------------------------------------------
1 | /*! Sortable Tree 0.7.2, (c) 2023 Marc Anton Dahmen, MIT license */
2 | :root {
3 | --st-label-height: 2.5rem;
4 | --st-subnodes-padding-left: 1.5rem;
5 | --st-collapse-icon-height: var(--st-label-height);
6 | --st-collapse-icon-width: 1.25rem;
7 | --st-collapse-icon-size: 0.75rem;
8 | }
9 | sortable-tree-node {
10 | position: relative;
11 | z-index: 1;
12 | display: flex;
13 | flex-direction: column;
14 | }
15 | sortable-tree-node * {
16 | user-select: none;
17 | }
18 | sortable-tree-node > :first-child {
19 | display: flex;
20 | align-items: center;
21 | height: var(--st-label-height);
22 | }
23 | sortable-tree-node > :nth-child(2) {
24 | display: none;
25 | flex-direction: column;
26 | padding-left: var(--st-subnodes-padding-left);
27 | }
28 | sortable-tree-node[open] > div:nth-child(2) {
29 | display: flex;
30 | }
31 | sortable-tree-node > :nth-child(3) {
32 | position: absolute;
33 | display: flex;
34 | align-items: center;
35 | top: 0;
36 | left: calc(var(--st-collapse-icon-width) * -1);
37 | height: var(--st-collapse-icon-height);
38 | font-size: var(--st-collapse-icon-size);
39 | cursor: pointer;
40 | }
41 | sortable-tree-node > :nth-child(2):empty + span {
42 | display: none;
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/assets/sortable-tree/sortable-tree.js:
--------------------------------------------------------------------------------
1 | /*! Sortable Tree 0.7.2, (c) 2024 Marc Anton Dahmen, MIT license */
2 | /* Modified by MrMugame (https://github.com/marcantondahmen/sortable-tree/pull/11) */
3 | !function (e, t) { "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.SortableTree = t() : e.SortableTree = t() }(self, (() => (() => { "use strict"; var e = { d: (t, n) => { for (var o in n) e.o(n, o) && !e.o(t, o) && Object.defineProperty(t, o, { enumerable: !0, get: n[o] }) }, o: (e, t) => Object.prototype.hasOwnProperty.call(e, t) }, t = {}; e.d(t, { default: () => L }); var n = function (e, t, n, o) { return new (n || (n = Promise))((function (r, s) { function i(e) { try { l(o.next(e)) } catch (e) { s(e) } } function a(e) { try { l(o.throw(e)) } catch (e) { s(e) } } function l(e) { var t; e.done ? r(e.value) : (t = e.value, t instanceof n ? t : new n((function (e) { e(t) }))).then(i, a) } l((o = o.apply(e, t || [])).next()) })) }; const o = e => `${e.title}`, r = { collapsed: '\n\t\t', open: '\n\t\t\n\t' }, s = { tree: "tree", node: "tree__node", nodeHover: "tree__node--hover", nodeDragging: "tree__node--dragging", nodeDropBefore: "tree__node--drop-before", nodeDropInside: "tree__node--drop-inside", nodeDropAfter: "tree__node--drop-after", label: "tree__label", subnodes: "tree__subnodes", collapse: "tree__collapse" }, i = ({ nodes: e, movedNode: t, srcParentNode: o, targetParentNode: r }) => n(void 0, void 0, void 0, (function* () { })), a = (e, t) => n(void 0, void 0, void 0, (function* () { })), l = (e, t) => n(void 0, void 0, void 0, (function* () { return !0 })); const d = (e, t = [], n = null) => { const o = document.createElement(e); return t.forEach((e => { o.classList.add(e) })), n && n.appendChild(o), o }, c = () => ((e = 21) => crypto.getRandomValues(new Uint8Array(e)).reduce(((e, t) => e + ((t &= 63) < 36 ? t.toString(36) : t < 62 ? (t - 26).toString(36).toUpperCase() : t > 62 ? "-" : "_")), ""))(); class u extends HTMLElement { static create({ data: e, renderLabel: t, icons: n, styles: o, parent: r, onClick: s, draggable: i }) { const a = d(u.TAG_NAME, [o.node], r), l = d("div", [o.label], a), c = d("div", [o.subnodes], a), h = d("span", [o.collapse], a); return l.innerHTML = t(e), h.innerHTML = n.collapsed, h.addEventListener("click", a.toggle.bind(a)), l.addEventListener("click", (e => { s(e, a) })), i && a.setAttribute("draggable", "true"), a._data = e, a._icons = n, a._label = l, a._nodes = c, a._collapseButton = h, a } get data() { return this._data } get label() { return this._label } get subnodes() { return this._nodes } get subnodesData() { const e = []; return Array.from(this._nodes.children).forEach((t => { e.push(t.data) })), e } get id() { return this._id } constructor() { super(), this._id = c() } collapse(e) { e ? (this.removeAttribute("open"), this._collapseButton.innerHTML = this._icons.collapsed) : (this.setAttribute("open", "true"), this._collapseButton.innerHTML = this._icons.open) } toggle() { this.collapse(this.hasAttribute("open")) } reveal() { ((e, t) => { const n = []; let o = t.closest(e); for (; null !== o;)n.push(o), o = o.parentNode.closest(e); return n })(u.TAG_NAME, this).forEach((e => { e.collapse(!1) })) } } u.TAG_NAME = "sortable-tree-node"; var h = function (e, t, n, o) { return new (n || (n = Promise))((function (r, s) { function i(e) { try { l(o.next(e)) } catch (e) { s(e) } } function a(e) { try { l(o.throw(e)) } catch (e) { s(e) } } function l(e) { var t; e.done ? r(e.value) : (t = e.value, t instanceof n ? t : new n((function (e) { e(t) }))).then(i, a) } l((o = o.apply(e, t || [])).next()) })) }; const p = ({ node: e, eventName: t, handler: n, tree: o }) => { e.addEventListener(t, (e => { n(e, o) }), !1) }; var f; !function (e) { e.BEFORE = "BEFORE", e.INSIDE = "INSIDE", e.AFTER = "AFTER" }(f || (f = {})); const g = e => { const t = e.clientY, n = v(e).label.getBoundingClientRect(), o = Math.round(n.height / 4); return n.top + o > t ? f.BEFORE : n.bottom - o < t ? f.AFTER : f.INSIDE }, v = e => e.target.closest(u.TAG_NAME), b = e => { const t = null == e ? void 0 : e.parentElement.parentElement; return (null == t ? void 0 : t.tagName.toLowerCase()) !== u.TAG_NAME ? null : t }, m = (e, t) => { v(e).classList.remove(t.styles.nodeDropAfter, t.styles.nodeDropBefore, t.styles.nodeDropInside) }, E = (e, t) => { e.stopPropagation(); const n = e.target; n.tagName.toLowerCase() === u.TAG_NAME && (e.dataTransfer.setData("text", n.id), e.dataTransfer.effectAllowed = "move", n.classList.add(t.styles.nodeDragging)) }, _ = (e, t) => h(void 0, void 0, void 0, (function* () { e.stopPropagation(), e.preventDefault(), m(e, t); const n = v(e); if (!n) return !1; const o = b(n), r = e.dataTransfer.getData("text"), s = g(e), i = t.getNode(r); if (!i || (null == i ? void 0 : i.contains(n))) return !1; const a = b(i); if (t.lockRootLevel && !(null == n ? void 0 : n.parentElement.closest(u.TAG_NAME)) && (s === f.BEFORE || s === f.AFTER)) return !1; if (s === f.BEFORE) return !!(yield t.confirm(i, o)) && (n.parentNode.insertBefore(i, n), t.onDrop(i, a, o), !1); if (s === f.AFTER) { if (!(yield t.confirm(i, o))) return !1; const e = n.nextElementSibling; return e ? (n.parentNode.insertBefore(i, e), t.onDrop(i, a, o)) : (n.parentNode.appendChild(i), t.onDrop(i, a, o)), !1 } return !!(yield t.confirm(i, n)) && (n.subnodes.appendChild(i), t.onDrop(i, a, n), !1) })), y = (e, t) => { e.preventDefault(), e.dataTransfer.dropEffect = "move", ((e, t) => { const n = v(e), o = g(e); n.classList.toggle(t.styles.nodeDropBefore, o === f.BEFORE), n.classList.toggle(t.styles.nodeDropInside, o === f.INSIDE), n.classList.toggle(t.styles.nodeDropAfter, o === f.AFTER) })(e, t) }, A = (e, t) => { m(e, t) }, T = (e, t) => { e.target.classList.remove(t.styles.nodeDragging), m(e, t) }, N = e => `sortableTreeState-${e.replace(/[^\w]+/, "-")}`; const L = class { constructor({ nodes: e, element: t, renderLabel: n, icons: d, styles: c, lockRootLevel: u, onChange: h, onClick: p, initCollapseLevel: f, confirm: g, disableSorting: v, stateId: b }) { this.nodeCollection = {}, e && (t ? (this.defineElements(), this.root = t, this.icons = Object.assign(Object.assign({}, r), d), this.styles = Object.assign(Object.assign({}, s), c), this.renderLabel = n || o, this.lockRootLevel = void 0 === u || u, this.onChange = h || i, this.onClick = p || a, this.confirm = g || l, this.initCollapseLevel = void 0 === f ? 2 : f, this.disableSorting = v || !1, t.classList.add(this.styles.tree), this.render({ nodes: e, element: t }), b && (((e, t) => { const n = sessionStorage.getItem(N(e)); if (!n) return; const o = JSON.parse(n), r = (e, t) => { const [n, o] = t; e.element.collapse(0 === n), o && e.subnodes.forEach(((e, t) => { void 0 !== o[t] && r(e, o[t]) })) }; t.forEach(((e, t) => { void 0 !== o[t] && r(e, o[t]) })) })(b, this.parseTree(this.root)), this.initStateObserver(b))) : console.error('Error: "element" is not a valid HTML element!')) } getNode(e) { return this.nodeCollection[e] } findNode(e, t) { const n = Object.values(this.nodeCollection); for (let o = 0; o < n.length; o++) { const r = n[o], s = r.data; if (e in s && s[e] == t) return r } return null } onDrop(e, t, n) { const o = { nodes: this.parseTree(this.root), movedNode: e, srcParentNode: t, targetParentNode: n }; null == n || n.collapse(!1), this.onChange(o) } destroy() { this.observer.disconnect(), this.observer = null } initStateObserver(e) { this.observer = new MutationObserver((() => { ((e, t) => { const n = [], o = e => { const t = [], n = [e.element.getAttribute("open") ? 1 : 0, t]; return e.subnodes.forEach((e => { t.push(o(e)) })), n }; t.forEach((e => { n.push(o(e)) })), sessionStorage.setItem(N(e), JSON.stringify(n)) })(e, this.parseTree(this.root)) })), this.observer.observe(this.root, { childList: !0, attributes: !0, subtree: !0 }) } defineElements() { try { customElements.define(u.TAG_NAME, u) } catch (e) { } } render({ nodes: e, element: t }, n = 0) { n++, e.forEach((e => { const o = u.create({ icons: this.icons, styles: this.styles, parent: t, renderLabel: this.renderLabel, data: e.data, onClick: this.onClick, draggable: !this.disableSorting }); this.disableSorting || ((e, t) => { const n = { dragstart: E, drop: _, dragover: y, dragend: T, dragleave: A }; for (const [o, r] of Object.entries(n)) p({ node: e, eventName: o, handler: r, tree: t }) })(o, this), o.collapse(n > this.initCollapseLevel), this.nodeCollection[o.id] = o, e.nodes && this.render({ nodes: e.nodes, element: o.subnodes }, n) })) } parseTree(e) { const t = Array.from(e.querySelectorAll(`:scope > ${u.TAG_NAME}`)), n = []; return t.forEach((e => { n.push({ element: e, id: e.id, subnodes: this.parseTree(e.subnodes) }) })), n } }; return t = t.default })()));
--------------------------------------------------------------------------------
/assets/treeview.css:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Page variables
3 | *****************************************************************************/
4 |
5 | html {
6 | --treeview-node-border-width: 2px;
7 | --treeview-node-border-radius: 5px;
8 |
9 | --treeview-page-color: var(--editor-wiki-link-page-color);
10 | --treeview-page-background-color: var(--editor-wiki-link-page-background-color);
11 | --treeview-page-border-color: var(--treeview-page-background-color);
12 |
13 | --treeview-folder-color: var(--editor-wiki-link-page-missing-color);
14 | --treeview-folder-background-color: var(--treeview-page-background-color);
15 | --treeview-folder-border-color: var(--treeview-page-background-color);
16 |
17 | --treeview-current-page-color: #eee;
18 | --treeview-current-page-background-color: var(--ui-accent-color);
19 | --treeview-current-page-border-color: var(--treeview-page-border-color);
20 | }
21 |
22 | .treeview-root {
23 | /* SortableTree variables */
24 | --st-label-height: auto;
25 | --st-subnodes-padding-left: 1.25rem;
26 | --st-collapse-icon-height: 2.1rem;
27 | --st-collapse-icon-width: 1.25rem;
28 | --st-collapse-icon-size: 1rem;
29 | }
30 |
31 | /******************************************************************************
32 | * Page styles
33 | *****************************************************************************/
34 |
35 | html, body {
36 | background-color: var(--root-background-color);
37 | padding: 0;
38 | margin: 0;
39 | overflow: initial !important;
40 | }
41 |
42 | .treeview-root {
43 | background-color: var(--root-background-color);
44 | color: var(--root-color);
45 | font-family: var(--ui-font);
46 | }
47 |
48 | /******************************************************************************
49 | * Header styles
50 | *
51 | * Action styles are meant to mimic the Top Bar icons (`sb-actions`)
52 | *****************************************************************************/
53 |
54 | .treeview-header {
55 | position: sticky;
56 | top: 0;
57 | z-index: 2;
58 | padding: 0.5rem 0.5rem 0rem;
59 | background-color: var(--root-background-color);
60 | }
61 |
62 | .treeview-actions {
63 | display: flex;
64 | justify-content: space-between;
65 | align-items: flex-start;
66 | background-color: var(--editor-widget-background-color);
67 | border: var(--top-border-color) 1px solid;
68 | border-radius: 5px;
69 | color: var(--top-color);
70 | }
71 |
72 | .treeview-actions-left,
73 | .treeview-actions-right {
74 | display: flex;
75 | }
76 |
77 | .treeview-actions-left {
78 | flex: 1;
79 | flex-wrap: wrap;
80 | }
81 |
82 | .treeview-actions button {
83 | display: flex;
84 | align-items: center;
85 | margin: 3px;
86 | padding: 5px;
87 | background-color: var(--action-button-background-color);
88 | border: 0;
89 | color: var(--action-button-color);
90 | cursor: pointer;
91 | }
92 |
93 | .treeview-actions button:hover {
94 | color: var(--action-button-hover-color);
95 | }
96 |
97 | .treeview-actions button:hover {
98 | color: var(--action-button-active-color);
99 | }
100 |
101 | .treeview-actions button > svg {
102 | height: 18px;
103 | width: 18px;
104 | }
105 |
106 | /******************************************************************************
107 | * SortableTree styles
108 | *****************************************************************************/
109 |
110 | .tree {
111 | display: flex;
112 | flex-direction: column;
113 | margin: 0.25rem 0.5rem 1rem;
114 | padding-left: var(--st-subnodes-padding-left);
115 | }
116 |
117 | .tree__label {
118 | display: flex;
119 | padding: 2px;
120 | }
121 |
122 | .tree__label:after {
123 | content: ' ';
124 | position: absolute;
125 | z-index: 4;
126 | inset: calc(var(--treeview-node-border-width) * -1) var(--treeview-node-border-width);
127 | border-top: calc(var(--treeview-node-border-width) * 2) solid transparent;
128 | border-bottom: calc(var(--treeview-node-border-width) * 2) solid transparent;
129 | transition: border-color 0.2s;
130 | pointer-events: none;
131 | }
132 |
133 | .tree__node--drop-before > .tree__label:after {
134 | border-top-color: var(--ui-accent-color);
135 | }
136 |
137 | .tree__node--drop-after > .tree__label:after {
138 | border-bottom-color: var(--ui-accent-color);
139 | }
140 |
141 | .tree__label > span {
142 | overflow: hidden;
143 | padding: 0 5px;
144 | border-color: transparent;
145 | border-width: var(--treeview-node-border-width);
146 | border-style: solid;
147 | border-radius: var(--treeview-node-border-radius);
148 | cursor: pointer;
149 | font-family: var(--editor-font);
150 | font-size: 18px;
151 | line-height: 1.4;
152 | text-decoration: none;
153 | text-overflow: ellipsis;
154 | white-space: nowrap;
155 | }
156 |
157 | .tree__label > span[data-node-type="page"] {
158 | background-color: var(--treeview-page-background-color);
159 | border-color: var(--treeview-page-border-color);
160 | color: var(--treeview-page-color);
161 | }
162 |
163 | .tree__label > span[data-node-type="folder"] {
164 | background-color: var(--treeview-folder-background-color);
165 | border-color: var(--treeview-folder-border-color);
166 | color: var(--treeview-folder-color);
167 | }
168 |
169 |
170 | .tree__label > span[data-current-page="true"] {
171 | background-color: var(--treeview-current-page-background-color);
172 | border-color: var(--treeview-current-page-border-color);
173 | color: var(--treeview-current-page-color);
174 | }
175 |
176 | .tree__collapse {
177 | color: var(--editor-command-button-color);
178 | }
179 |
180 | .tree__node--dragging {
181 | margin: calc(var(--treeview-node-border-width) * -1);
182 | border: var(--treeview-node-border-width) dashed var(--subtle-color);
183 | border-radius: var(--treeview-node-border-radius);
184 | cursor: move !important;
185 | }
186 |
187 | .tree__node--dragging .tree__label > span {
188 | opacity: 0.75;
189 | }
190 |
191 | .tree__node--drop-inside > .tree__label > span {
192 | z-index: 3;
193 | background-color: var(--subtle-background-color);
194 | border-color: var(--ui-accent-color);
195 | }
196 |
197 | .tree__node--drop-inside > .tree__label > span[data-current-page="true"] {
198 | color: var(--treeview-page-color);
199 | }
--------------------------------------------------------------------------------
/assets/treeview.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef {import("../api.ts").TreeNode} TreeNode
3 | */
4 |
5 | /**
6 | * @typedef SortableTreeNode
7 | * @type {Object}
8 | * @property {TreeNode["data"]} data
9 | */
10 |
11 | /**
12 | *
13 | * @typedef TreeViewConfig
14 | * @type {Object}
15 | * @property {string} currentPage - the current page shown in SilverBullet.
16 | * @property {TreeNode[]} nodes - a tree of all pages in the current space.
17 | * @property {Object} dragAndDrop - drag and drop related config
18 | * @property {boolean} dragAndDrop.enabled - true if drag and drop is enabled
19 | * @property {boolean} dragAndDrop.confirmOnRename - true if a confirmation should be shown
20 | * when a node is dragged and dropped.
21 | */
22 |
23 |
24 | const TREE_STATE_ID = "treeview";
25 |
26 | /**
27 | * Initializes the TreeView's `SortableTree` instance.
28 | * @param {TreeViewConfig} config
29 | * @returns {SortableTree}
30 | */
31 | function createTreeView(config) {
32 | return new SortableTree({
33 | nodes: config.nodes,
34 | disableSorting: !config.dragAndDrop.enabled,
35 | element: document.getElementById(config.treeElementId),
36 | stateId: TREE_STATE_ID,
37 | initCollapseLevel: 0,
38 | lockRootLevel: false,
39 |
40 | /**
41 | * @param {SortableTreeNode} movedNode
42 | * @param {SortableTreeNode} targetParentNode
43 | */
44 | confirm: async (movedNode, targetParentNode) => {
45 | const oldPrefix = movedNode.data.name;
46 | const newPrefix = targetParentNode ? `${targetParentNode.data.name}/${movedNode.data.title}` : movedNode.data.title;
47 |
48 | if (oldPrefix === newPrefix) {
49 | return;
50 | }
51 |
52 | const success = await syscall("system.invokeFunction", "index.renamePrefixCommand", {
53 | oldPrefix,
54 | newPrefix,
55 | disableConfirmation: !config.dragAndDrop.confirmOnRename,
56 | });
57 |
58 | if (success && config.currentPage.indexOf(oldPrefix) === 0) {
59 | // If this renamed the current page, navigate to it at it's updated name.
60 | await syscall("editor.navigate", config.currentPage.replace(oldPrefix, newPrefix), false, false);
61 | }
62 |
63 | return success;
64 | },
65 |
66 | onChange: async () => {
67 | await syscall("system.invokeFunction", "treeview.show");
68 | },
69 |
70 | /**
71 | * @param {SortableTreeNode} node
72 | */
73 | onClick: async (_event, node) => {
74 | await syscall("editor.navigate", node.data.name, false, false);
75 | },
76 |
77 | /**
78 | * @param {SortableTreeNode["data"]} data
79 | * @returns {string}
80 | */
81 | renderLabel: (data) => `
82 |
87 | ${data.title}
88 | `
89 | ,
90 | });
91 | }
92 |
93 | /**
94 | * Initializes the tree view and it's action bar.
95 | * @param {TreeViewConfig} config
96 | */
97 | // deno-lint-ignore no-unused-vars
98 | function initializeTreeViewPanel(config) {
99 | const tree = createTreeView(config);
100 | const handleAction = (action) => {
101 | switch (action) {
102 | case "collapse-all": {
103 | document.querySelectorAll("sortable-tree-node[open='true']").forEach((node) => node.collapse(true));
104 | return true;
105 | }
106 | case "expand-all": {
107 | document.querySelectorAll("sortable-tree-node:not([open='true'])").forEach((node) => node.collapse(false));
108 | return true;
109 | }
110 | case "close-panel": {
111 | syscall("system.invokeFunction", "treeview.hide");
112 | return true;
113 | }
114 | case "refresh": {
115 | syscall("system.invokeFunction", "treeview.show");
116 | return true;
117 | }
118 | case "reveal-current-page": {
119 | const currentNode = tree.findNode("isCurrentPage", true);
120 | if (currentNode) {
121 | currentNode.reveal();
122 | currentNode.scrollIntoView({
123 | behavior: "auto",
124 | block: "nearest",
125 | inline: "nearest",
126 | });
127 | return true;
128 | }
129 | return false;
130 | }
131 | }
132 |
133 | return false;
134 | }
135 |
136 | handleAction("reveal-current-page");
137 |
138 | document.querySelectorAll("[data-treeview-action]").forEach((el) => {
139 | el.addEventListener("click", (e) => {
140 | if (handleAction(el.dataset["treeviewAction"])) {
141 | e.stopPropagation();
142 | e.preventDefault();
143 | }
144 | });
145 | })
146 | }
147 |
--------------------------------------------------------------------------------
/config.ts:
--------------------------------------------------------------------------------
1 | import {
2 | clientStore,
3 | editor,
4 | system,
5 | } from "@silverbulletmd/silverbullet/syscalls";
6 | import { z, ZodError } from "zod";
7 |
8 | /**
9 | * The name of this plug.
10 | * TODO: is there a way to get this programatically?
11 | */
12 | export const PLUG_NAME = "treeview";
13 |
14 | export const PLUG_DISPLAY_NAME = "TreeView Plug";
15 |
16 | /**
17 | * The key used to save the current enabled state of the treeview.
18 | */
19 | const ENABLED_STATE_KEY = "enableTreeView";
20 |
21 | /**
22 | * The possible position where the treeview can be rendered.
23 | */
24 | const POSITIONS = ["rhs", "lhs", "bhs", "modal"] as const;
25 |
26 | export type Position = typeof POSITIONS[number];
27 |
28 | /**
29 | * Defines an exclusion rule based on a regular expression
30 | */
31 | export const exclusionRuleByRegexSchema = z.object({
32 | type: z.literal("regex"),
33 | rule: z.string(),
34 | negate: z.boolean().optional().default(false),
35 | });
36 |
37 | /**
38 | * Defines an exclusion rule based on a list of tags
39 | */
40 | export const exclusionRuleByTagsSchema = z.object({
41 | type: z.literal("tags"),
42 | tags: z.array(z.string()),
43 | negate: z.boolean().optional().default(false),
44 | attribute: z.enum(["tags", "itags", "tag"]).optional().default("tags"),
45 | });
46 |
47 | /**
48 | * Defines an exclusion rule based on a regular expression
49 | */
50 | export const exclusionRuleByFunctionSchema = z.object({
51 | type: z.literal("space-function"),
52 | name: z.string(),
53 | negate: z.boolean().optional().default(false),
54 | });
55 |
56 | /**
57 | * The schema for the tree view configuration read from the SETTINGS page.
58 | */
59 | const treeViewConfigSchema = z.object({
60 | /**
61 | * Where to position the tree view in the UI.
62 | */
63 | position: z.enum(POSITIONS).optional().default("lhs"),
64 |
65 | /**
66 | * The size of the treeview pane.
67 | */
68 | size: z.number().gt(0).optional().default(1),
69 |
70 | /**
71 | * Drag-and-drop options
72 | */
73 | dragAndDrop: z.object({
74 | /**
75 | * Whether dragging/dropping functionality is
76 | */
77 | enabled: z.boolean().optional().default(true),
78 | /**
79 | * True to confirm on rename actions by showing a popup prompt.
80 | */
81 | confirmOnRename: z.boolean().optional().default(true),
82 | }).optional().default({}),
83 |
84 | /**
85 | * @deprecated
86 | */
87 | pageExcludeRegex: z.string().optional().default(""),
88 |
89 | /**
90 | * A list of exclusion rules to apply.
91 | */
92 | exclusions: z.array(z.discriminatedUnion("type", [
93 | exclusionRuleByRegexSchema,
94 | exclusionRuleByTagsSchema,
95 | exclusionRuleByFunctionSchema,
96 | ])).optional(),
97 | });
98 |
99 | export type TreeViewConfig = z.infer;
100 |
101 | async function showConfigErrorNotification(error: unknown) {
102 | if (configErrorShown) {
103 | return;
104 | }
105 |
106 | configErrorShown = true;
107 | let errorMessage = `${typeof error}: ${String(error)}`;
108 |
109 | if (error instanceof ZodError) {
110 | const { formErrors, fieldErrors } = error.flatten();
111 | const fieldErrorMessages = Object.keys(fieldErrors).map((field) =>
112 | `\`${field}\` - ${fieldErrors[field]!.join(", ")}`
113 | );
114 |
115 | // Not pretty, but we don't have any formatting options available here.
116 | errorMessage = [...formErrors, ...fieldErrorMessages].join("; ");
117 | }
118 |
119 | // Some rudimentary notification about an invalid configuration.
120 | // Not pretty, but we can't use html/formatting here.
121 | await editor.flashNotification(
122 | `There was an error with your ${PLUG_NAME} configuration. Check your SETTINGS file: ${errorMessage}`,
123 | "error",
124 | );
125 | }
126 |
127 | let configErrorShown = false;
128 |
129 | export async function getPlugConfig(): Promise {
130 | const userConfig = await system.getSpaceConfig("treeview", {});
131 |
132 | try {
133 | return treeViewConfigSchema.parse(userConfig || {});
134 | } catch (_err) {
135 | if (!configErrorShown) {
136 | showConfigErrorNotification(_err);
137 | configErrorShown = true;
138 | }
139 | // Fallback to the default configuration
140 | return treeViewConfigSchema.parse({});
141 | }
142 | }
143 |
144 | export async function isTreeViewEnabled() {
145 | return !!(await clientStore.get(ENABLED_STATE_KEY));
146 | }
147 |
148 | export async function setTreeViewEnabled(value: boolean) {
149 | return await clientStore.set(ENABLED_STATE_KEY, value);
150 | }
151 |
152 | export async function getCustomStyles() {
153 | const customStyles = await editor.getUiOption("customStyles") as
154 | | string
155 | | undefined;
156 | return customStyles;
157 | }
158 |
--------------------------------------------------------------------------------
/deno.json:
--------------------------------------------------------------------------------
1 | {
2 | "imports": {
3 | "@silverbulletmd/silverbullet": "jsr:@silverbulletmd/silverbullet@^0.10.4",
4 | "zod": "https://deno.land/x/zod@v3.23.8/mod.ts"
5 | },
6 | "tasks": {
7 | "build": "silverbullet plug:compile -c deno.json treeview.plug.yaml",
8 | "debug": "silverbullet plug:compile --info --debug -c deno.json treeview.plug.yaml",
9 | "watch": "silverbullet plug:compile treeview.plug.yaml -w --debug -c deno.json",
10 | "test": "deno test -A --unstable-kv --unstable-worker-options"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/deno.lock:
--------------------------------------------------------------------------------
1 | {
2 | "version": "4",
3 | "specifiers": {
4 | "jsr:@silverbulletmd/silverbullet@~0.10.4": "0.10.4",
5 | "npm:js-yaml@4.1.0": "4.1.0"
6 | },
7 | "jsr": {
8 | "@silverbulletmd/silverbullet@0.10.4": {
9 | "integrity": "021c53f3ad82b5e05247517ae90a458e00c6b8d95826b12454da0c956fff4c12",
10 | "dependencies": [
11 | "npm:js-yaml"
12 | ]
13 | }
14 | },
15 | "npm": {
16 | "argparse@2.0.1": {
17 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
18 | },
19 | "js-yaml@4.1.0": {
20 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
21 | "dependencies": [
22 | "argparse"
23 | ]
24 | }
25 | },
26 | "remote": {
27 | "https://deno.land/x/silverbullet@0.10.4/lib/asset_bundle/bundle.ts": "5cebb61d5ec523c9d2d8b222516ed3593d40601834c3c7d2aa2b48dad00986b1",
28 | "https://deno.land/x/silverbullet@0.10.4/lib/command.ts": "2ec8089f8abf3a26bbf48db89a787f5796c66dfeee0a0065bbb8344c4d7ded59",
29 | "https://deno.land/x/silverbullet@0.10.4/lib/crypto.ts": "62a2fa4fa5656de53856fcaf70f8e1ec561fc949d26d34168372d7963a727886",
30 | "https://deno.land/x/silverbullet@0.10.4/lib/data/kv_primitives.ts": "98d7367dbcd1303defd728ef6764b32765600c18ec3359964cc2758e29bb2f26",
31 | "https://deno.land/x/silverbullet@0.10.4/lib/manifest.ts": "53fbd1b79c13b77e94490a277bd087cb9f4a24dcae8dcdbefe443bc7ceff7480",
32 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/event.ts": "da055088f3d1d93f31aadd7e16a97061033fdba5807609f3838280352dbbc15e",
33 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/manifest_cache.ts": "c6eaed062ade506ed98a0fa3686f161f58ff839e939f0aa536a371dabd43ca8f",
34 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/namespace.ts": "0a870e11ffefcf9c5fe9e8d11d5ed07dcd19bdd28c4289f96f8bcf95ec44baf2",
35 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/plug.ts": "d3470c6b2040c7e94576f8685a37ca1553ab5ad95760d9566f3c336cb97eee9d",
36 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/protocol.ts": "953341d218c74d662b549e328551033e303ae196a6b27f464b5b394fa7fb1940",
37 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/sandboxes/sandbox.ts": "b1ce8da12cb7658482c74888693a8d7ecc02e772d4ac245fbf9935a191ebf5a2",
38 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/system.ts": "9543bc8bf0e000f7ab647ebc9bd3132f4b8aa3755980c72ea8f291948f27d4dd",
39 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/types.ts": "bb8d220c152304961c815edc8f71bcb843c761c7a789893f579cf57d088a5333",
40 | "https://deno.land/x/silverbullet@0.10.4/lib/plugos/worker_runtime.ts": "a3244ba1e63e5d5755a3d6fd65eea3995980e7647020a5fdb2949a82c3d4621c",
41 | "https://deno.land/x/silverbullet@0.10.4/lib/proxy_fetch.ts": "831d98cf7f9ada653fc958f52ad367d8511e2634400c29e1fe9d6babd230c0bf",
42 | "https://deno.land/x/silverbullet@0.10.4/plug-api/lib/tree.ts": "48f1080ba0e7e2545b64524328bf2673830bf6ccee37fc97286644387536e0cd",
43 | "https://deno.land/x/silverbullet@0.10.4/plug-api/types.ts": "2656ea5e261ba2d7bf685580c823c2bc87142a0139b655ff794c3b89ffd7cf62",
44 | "https://deno.land/x/silverbullet@0.10.4/web/change.ts": "bc3204e4f34f86edd11b0fcf3fdfc1e8599cb08ca4eebe7f22451195b74440ef",
45 | "https://deno.land/x/silverbullet@0.8.2/lib/command.ts": "1b131c5da91f0bdb8c58eb3058befc4f5861827a38d9196a08026206f51379b1",
46 | "https://deno.land/x/silverbullet@0.8.2/lib/crypto.ts": "a90267ed8eb936da3ee5d395b00be8978699007ec95f84d81720770a5fd819a0",
47 | "https://deno.land/x/silverbullet@0.8.2/lib/web.ts": "e5950585bcfd711b1d6f1a4cb81b6a6c87323a6576573d8764d6b10fd1b69b79",
48 | "https://deno.land/x/silverbullet@0.8.2/plug-api/lib/page_ref.ts": "de5e4ecee3ad28f909c74e512b6c2804f4d9fd4df8278c52a8c0cc4a05f7a238",
49 | "https://deno.land/x/silverbullet@0.8.2/plug-api/lib/query.ts": "20bba1579607f094ffb5bed44b176f6ebc0b73184085ea11542eb7e4127018f3",
50 | "https://deno.land/x/silverbullet@0.8.2/plug-api/lib/query_expression.ts": "2e5f078792365a916f0ffe9ab75de092efcc3f2f398f292709e3c722755b6a7f",
51 | "https://deno.land/x/silverbullet@0.8.2/plug-api/lib/tree.ts": "e4e8cd4f2d409e6bff4fefef25244504cde5788ac4f3c748301c31d35c0fa802",
52 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscall.ts": "e92c9e4b25808cf3d2a193d70bab7194fc5f5e8697a20dcd72b4fc3f3beb0e8e",
53 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls.ts": "f86dddaa420498e820b3feb11431f33852837d816166ced3530dd41a33914d3e",
54 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/asset.ts": "7598702fb497bf69e5522d05556e9887ce1d95ada47c10d8386de29bc7535262",
55 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/clientStore.ts": "e623682ccd83d3f3155fd7f5062a716e1a0422abebb68f71613e284ca705f807",
56 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/code_widget.ts": "2d4c4f2393a860496209c057c3eef4c9b8ceb49b34e433958b331b269a1afc25",
57 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/datastore.ts": "cb51f7ae55509cad3804c7593564f5142f11a966a676d6ec2484150060d2deca",
58 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/debug.ts": "b374379d16c1ce523a56d29353a484ed7d7b633c167bb82350f78fa779d4b72e",
59 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/decoration.ts": "197d0b5dee5a4501bc08d94cb7f28db8dbbcd0dd0ae7b375f616961aef1dda56",
60 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/editor.ts": "6d3609f9daba2cc6018ef415d06c19a6c40e5d8b08a36cfac74242a565528974",
61 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/event.ts": "46e7449b166bfed4df68db034244fc638bd189a1d1dacf3ae451fbe5ac0f5161",
62 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/language.ts": "6a038b674db294f5c09bb5ba8bf44c36301b04b4717a4d53ab7eef8594d81574",
63 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/markdown.ts": "51a0afc48beb4b67ac20b3e2e0166726b05170da0f0f396215c940af6eec3aa4",
64 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/mq.ts": "5a638511bea78f2175e1002502184a9a8f545ec55cc3f5e34b3df3221adf81c5",
65 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/shell.ts": "2c6329f7236405682065ab55fd5c0ec5fe354bdf67e040dd651492c4b64de998",
66 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/space.ts": "c204858c83beec3ace603b11fae2ff487e053c2a8182f725690470a07ea27cab",
67 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/sync.ts": "1a2430bcfa7f9e1d6d8c99a90a0e1a7e5a2075b11b0916e9e8facd8ff36767db",
68 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/system.ts": "5a6fb1db99656087bc73cfa16755e6b579e40d1b6d5e71647e7f91e9b56d1148",
69 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/template.ts": "92f4dfd8b76838852a6ea3964b3acd24bc66a38bcf59727190ea149523036591",
70 | "https://deno.land/x/silverbullet@0.8.2/plug-api/syscalls/yaml.ts": "db850fe538ae924ecda4af269af5f02abacd11e020893043f828796bd2d7833b",
71 | "https://deno.land/x/silverbullet@0.8.2/plug-api/types.ts": "50ef0307df24ebdf6e684e7c41ba34e58f22d40a42344f96a6a9403c96adcace",
72 | "https://deno.land/x/silverbullet@0.8.2/web/change.ts": "bc3204e4f34f86edd11b0fcf3fdfc1e8599cb08ca4eebe7f22451195b74440ef",
73 | "https://deno.land/x/zod@v3.23.8/ZodError.ts": "528da200fbe995157b9ae91498b103c4ef482217a5c086249507ac850bd78f52",
74 | "https://deno.land/x/zod@v3.23.8/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef",
75 | "https://deno.land/x/zod@v3.23.8/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe",
76 | "https://deno.land/x/zod@v3.23.8/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c",
77 | "https://deno.land/x/zod@v3.23.8/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7",
78 | "https://deno.land/x/zod@v3.23.8/helpers/parseUtil.ts": "c14814d167cc286972b6e094df88d7d982572a08424b7cd50f862036b6fcaa77",
79 | "https://deno.land/x/zod@v3.23.8/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7",
80 | "https://deno.land/x/zod@v3.23.8/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e",
81 | "https://deno.land/x/zod@v3.23.8/helpers/util.ts": "30c273131661ca5dc973f2cfb196fa23caf3a43e224cdde7a683b72e101a31fc",
82 | "https://deno.land/x/zod@v3.23.8/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268",
83 | "https://deno.land/x/zod@v3.23.8/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c",
84 | "https://deno.land/x/zod@v3.23.8/mod.ts": "ec6e2b1255c1a350b80188f97bd0a6bac45801bb46fc48f50b9763aa66046039",
85 | "https://deno.land/x/zod@v3.23.8/types.ts": "1b172c90782b1eaa837100ebb6abd726d79d6c1ec336350c8e851e0fd706bf5c"
86 | },
87 | "workspace": {
88 | "dependencies": [
89 | "jsr:@silverbulletmd/silverbullet@~0.10.4"
90 | ]
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/filters/filterByFunction.ts:
--------------------------------------------------------------------------------
1 | import { PageMeta } from "@silverbulletmd/silverbullet/types";
2 | import { z } from "zod";
3 | import { exclusionRuleByFunctionSchema, PLUG_DISPLAY_NAME } from "../config.ts";
4 | import { system } from "@silverbulletmd/silverbullet/syscalls";
5 |
6 | export type FilterPagesByFunctionOptions = z.infer<
7 | typeof exclusionRuleByFunctionSchema
8 | >;
9 |
10 | export const filterPagesByFunction = async (
11 | pages: PageMeta[],
12 | { name, negate }: Omit,
13 | ) => {
14 | try {
15 | const results = await Promise.all(
16 | pages.map((page) => system.invokeSpaceFunction(name, page)),
17 | );
18 |
19 | return pages.filter((_, index) =>
20 | negate ? results[index] : !results[index]
21 | );
22 | } catch (err: unknown) {
23 | console.error(
24 | `${PLUG_DISPLAY_NAME}: filtering pages by function "${name}" failed`,
25 | err,
26 | );
27 | return pages;
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/filters/filterByRegex.ts:
--------------------------------------------------------------------------------
1 | import { PageMeta } from "@silverbulletmd/silverbullet/types";
2 | import { z } from "zod";
3 | import { exclusionRuleByRegexSchema, PLUG_DISPLAY_NAME } from "../config.ts";
4 |
5 | export type FilterPagesByRegexOptions = z.infer<
6 | typeof exclusionRuleByRegexSchema
7 | >;
8 |
9 | export const filterPagesByRegex = (
10 | pages: PageMeta[],
11 | { rule, negate }: Omit,
12 | ) => {
13 | try {
14 | const regexFilter = new RegExp(rule);
15 | return pages.filter(({ name }) => (regexFilter.test(name) === negate));
16 | } catch (err: unknown) {
17 | console.error(
18 | `${PLUG_DISPLAY_NAME}: filtering pages by regex "${rule}" failed`,
19 | err,
20 | );
21 | return pages;
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/filters/filterByTags.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { exclusionRuleByTagsSchema } from "../config.ts";
3 | import { PageMeta } from "@silverbulletmd/silverbullet/types";
4 |
5 | export type FilterPagesByTagsOptions = z.infer<
6 | typeof exclusionRuleByTagsSchema
7 | >;
8 |
9 | export const filterPagesByTags = (
10 | pages: PageMeta[],
11 | { attribute, negate, tags }: Omit,
12 | ) =>
13 | pages.filter((page) => {
14 | const value = page[attribute];
15 |
16 | const hasTag = value !== undefined &&
17 | (Array.isArray(value)
18 | ? value.some((tag) => tags.includes(tag))
19 | : tags.includes(value));
20 |
21 | return negate ? hasTag : !hasTag;
22 | });
23 |
--------------------------------------------------------------------------------
/screenshot-action-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joekrill/silverbullet-treeview/c1b95e87410b177c4b0ca3fb53fe2ec3d490f7fa/screenshot-action-button.png
--------------------------------------------------------------------------------
/screenshot-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joekrill/silverbullet-treeview/c1b95e87410b177c4b0ca3fb53fe2ec3d490f7fa/screenshot-dark.png
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joekrill/silverbullet-treeview/c1b95e87410b177c4b0ca3fb53fe2ec3d490f7fa/screenshot.png
--------------------------------------------------------------------------------
/treeview.plug.js:
--------------------------------------------------------------------------------
1 | var ft=Object.defineProperty;var ne=(n,e)=>{for(var t in e)ft(n,t,{get:e[t],enumerable:!0})};var re=n=>{throw new Error("Not initialized yet")},Le=typeof window>"u"&&typeof globalThis.WebSocketPair>"u";typeof Deno>"u"&&(self.Deno={args:[],build:{arch:"x86_64"},env:{get(){}}});var Ne=new Map,_e=0;Le&&(globalThis.syscall=async(n,...e)=>await new Promise((t,r)=>{_e++,Ne.set(_e,{resolve:t,reject:r}),re({type:"sys",id:_e,name:n,args:e})}));function Ye(n,e,t){Le&&(re=t,self.addEventListener("message",r=>{(async()=>{let s=r.data;switch(s.type){case"inv":{let a=n[s.name];if(!a)throw new Error(`Function not loaded: ${s.name}`);try{let o=await Promise.resolve(a(...s.args||[]));re({type:"invr",id:s.id,result:o})}catch(o){console.error("An exception was thrown as a result of invoking function",s.name,"error:",o.message),re({type:"invr",id:s.id,error:o.message})}}break;case"sysr":{let a=s.id,o=Ne.get(a);if(!o)throw Error("Invalid request id");Ne.delete(a),s.error?o.reject(new Error(s.error)):o.resolve(s.result)}break}})().catch(console.error)}),re({type:"manifest",manifest:e}))}function Zt(n){let e=atob(n),t=e.length,r=new Uint8Array(t);for(let s=0;s0?He(t):void 0;e={method:n.method,headers:Object.fromEntries(n.headers.entries()),base64Body:r},n=n.url}return syscall("sandboxFetch.fetch",n,e)}globalThis.nativeFetch=globalThis.fetch;function ht(){globalThis.fetch=async function(n,e){let t=e&&e.body?He(new Uint8Array(await new Response(e.body).arrayBuffer())):void 0,r=await It(n,e&&{method:e.method,headers:e.headers,base64Body:t});return new Response(r.base64Body?Zt(r.base64Body):null,{status:r.status,headers:r.headers})}}Le&&ht();var G={};ne(G,{confirm:()=>qt,copyToClipboard:()=>un,deleteLine:()=>cn,dispatch:()=>Jt,downloadFile:()=>Lt,filterBox:()=>Xt,flashNotification:()=>Et,fold:()=>en,foldAll:()=>rn,getCurrentPage:()=>bt,getCurrentPageMeta:()=>xt,getCursor:()=>vt,getSelection:()=>kt,getText:()=>Tt,getUiOption:()=>Qt,goHistory:()=>Nt,hidePanel:()=>Ot,insertAtCursor:()=>jt,insertAtPos:()=>Yt,moveCursor:()=>Ft,moveCursorToLine:()=>Mt,moveLineDown:()=>pn,moveLineUp:()=>ln,navigate:()=>Pt,newWindow:()=>_t,openCommandPalette:()=>wt,openPageNavigator:()=>St,openSearchPanel:()=>dn,openUrl:()=>Vt,prompt:()=>zt,rebuildEditorState:()=>Bt,redo:()=>on,reloadConfigAndCommands:()=>Wt,reloadPage:()=>Kt,reloadUI:()=>Gt,replaceRange:()=>Ht,save:()=>Rt,setSelection:()=>At,setText:()=>Ct,setUiOption:()=>$t,showPanel:()=>Dt,toggleFold:()=>nn,undo:()=>an,unfold:()=>tn,unfoldAll:()=>sn,uploadFile:()=>Ut,vimEx:()=>yn});typeof self>"u"&&(self={syscall:()=>{throw new Error("Not implemented here")}});function u(n,...e){return globalThis.syscall(n,...e)}function bt(){return u("editor.getCurrentPage")}function xt(){return u("editor.getCurrentPageMeta")}function Tt(){return u("editor.getText")}function Ct(n,e=!1){return u("editor.setText",n,e)}function vt(){return u("editor.getCursor")}function kt(){return u("editor.getSelection")}function At(n,e){return u("editor.setSelection",n,e)}function Rt(){return u("editor.save")}function Pt(n,e=!1,t=!1){return u("editor.navigate",n,e,t)}function St(n="page"){return u("editor.openPageNavigator",n)}function wt(){return u("editor.openCommandPalette")}function Kt(){return u("editor.reloadPage")}function Gt(){return u("editor.reloadUI")}function Bt(){return u("editor.rebuildEditorState")}function Wt(){return u("editor.reloadConfigAndCommands")}function Vt(n,e=!1){return u("editor.openUrl",n,e)}function _t(){return u("editor.newWindow")}function Nt(n){return u("editor.goHistory",n)}function Lt(n,e){return u("editor.downloadFile",n,e)}function Ut(n,e){return u("editor.uploadFile",n,e)}function Et(n,e="info"){return u("editor.flashNotification",n,e)}function Xt(n,e,t="",r=""){return u("editor.filterBox",n,e,t,r)}function Dt(n,e,t,r=""){return u("editor.showPanel",n,e,t,r)}function Ot(n){return u("editor.hidePanel",n)}function Yt(n,e){return u("editor.insertAtPos",n,e)}function Ht(n,e,t){return u("editor.replaceRange",n,e,t)}function Ft(n,e=!1){return u("editor.moveCursor",n,e)}function Mt(n,e=1,t=!1){return u("editor.moveCursorToLine",n,e,t)}function jt(n,e=!1){return u("editor.insertAtCursor",n,e)}function Jt(n){return u("editor.dispatch",n)}function zt(n,e=""){return u("editor.prompt",n,e)}function qt(n){return u("editor.confirm",n)}function Qt(n){return u("editor.getUiOption",n)}function $t(n,e){return u("editor.setUiOption",n,e)}function en(){return u("editor.fold")}function tn(){return u("editor.unfold")}function nn(){return u("editor.toggleFold")}function rn(){return u("editor.foldAll")}function sn(){return u("editor.unfoldAll")}function an(){return u("editor.undo")}function on(){return u("editor.redo")}function dn(){return u("editor.openSearchPanel")}function un(n){return u("editor.copyToClipboard",n)}function cn(){return u("editor.deleteLine")}function ln(){return u("editor.moveLineUp")}function pn(){return u("editor.moveLineDown")}function yn(n){return u("editor.vimEx",n)}var B={};ne(B,{applyAttributeExtractors:()=>xn,getEnv:()=>kn,getMode:()=>An,getSpaceConfig:()=>Tn,getVersion:()=>Rn,invokeCommand:()=>Zn,invokeFunction:()=>fn,invokeSpaceFunction:()=>bn,listCommands:()=>In,listSyscalls:()=>hn,reloadConfig:()=>vn,reloadPlugs:()=>Cn});function fn(n,...e){return u("system.invokeFunction",n,...e)}function Zn(n,e){return u("system.invokeCommand",n,e)}function In(){return u("system.listCommands")}function hn(){return u("system.listSyscalls")}function bn(n,...e){return u("system.invokeSpaceFunction",n,...e)}function xn(n,e,t){return u("system.applyAttributeExtractors",n,e,t)}async function Tn(n,e){return await u("system.getSpaceConfig",n)??e}function Cn(){return u("system.reloadPlugs")}function vn(){return u("system.reloadConfig")}function kn(){return u("system.getEnv")}function An(){return u("system.getMode")}function Rn(){return u("system.getVersion")}var se={};ne(se,{del:()=>wn,get:()=>Sn,set:()=>Pn});function Pn(n,e){return u("clientStore.set",n,e)}function Sn(n){return u("clientStore.get",n)}function wn(n){return u("clientStore.delete",n)}var S={};ne(S,{getFileMeta:()=>Un,listFiles:()=>Ln,readAsset:()=>Nn});function _n(n){let e=atob(n),t=e.length,r=new Uint8Array(t);for(let s=0;syr,DIRTY:()=>Y,EMPTY_PATH:()=>qn,INVALID:()=>g,NEVER:()=>qr,OK:()=>A,ParseStatus:()=>k,Schema:()=>I,ZodAny:()=>Q,ZodArray:()=>F,ZodBigInt:()=>ie,ZodBoolean:()=>de,ZodBranded:()=>he,ZodCatch:()=>Ie,ZodDate:()=>ue,ZodDefault:()=>Ze,ZodDiscriminatedUnion:()=>Re,ZodEffects:()=>X,ZodEnum:()=>$,ZodError:()=>P,ZodFirstPartyTypeKind:()=>tt,ZodFunction:()=>Ke,ZodIntersection:()=>ye,ZodIssueCode:()=>d,ZodLazy:()=>me,ZodLiteral:()=>ge,ZodMap:()=>Se,ZodNaN:()=>Ge,ZodNativeEnum:()=>fe,ZodNever:()=>L,ZodNull:()=>le,ZodNullable:()=>D,ZodNumber:()=>oe,ZodObject:()=>U,ZodOptional:()=>W,ZodParsedType:()=>p,ZodPipeline:()=>be,ZodPromise:()=>ee,ZodReadonly:()=>xe,ZodRecord:()=>Pe,ZodSchema:()=>I,ZodSet:()=>we,ZodString:()=>q,ZodSymbol:()=>ke,ZodTransformer:()=>X,ZodTuple:()=>E,ZodType:()=>I,ZodUndefined:()=>ce,ZodUnion:()=>pe,ZodUnknown:()=>H,ZodVoid:()=>Ae,addIssueToContext:()=>l,any:()=>Tr,array:()=>Ar,bigint:()=>Zr,boolean:()=>st,coerce:()=>zr,custom:()=>et,date:()=>Ir,datetimeRegex:()=>Qe,defaultErrorMap:()=>_,discriminatedUnion:()=>wr,effect:()=>Dr,enum:()=>Ur,function:()=>_r,getErrorMap:()=>M,getParsedType:()=>V,instanceof:()=>gr,intersection:()=>Kr,isAborted:()=>Ce,isAsync:()=>J,isDirty:()=>ve,isValid:()=>j,late:()=>mr,lazy:()=>Nr,literal:()=>Lr,makeIssue:()=>ae,map:()=>Wr,nan:()=>fr,nativeEnum:()=>Er,never:()=>vr,null:()=>xr,nullable:()=>Yr,number:()=>rt,object:()=>Rr,objectUtil:()=>Me,oboolean:()=>Jr,onumber:()=>jr,optional:()=>Or,ostring:()=>Mr,pipeline:()=>Fr,preprocess:()=>Hr,promise:()=>Xr,quotelessJson:()=>jn,record:()=>Br,set:()=>Vr,setErrorMap:()=>zn,strictObject:()=>Pr,string:()=>nt,symbol:()=>hr,transformer:()=>Dr,tuple:()=>Gr,undefined:()=>br,union:()=>Sr,unknown:()=>Cr,util:()=>b,void:()=>kr});var b;(T=>{T.assertEqual=x=>x;function e(x){}T.assertIs=e;function t(x){throw new Error}T.assertNever=t,T.arrayToEnum=x=>{let v={};for(let R of x)v[R]=R;return v},T.getValidEnumValues=x=>{let v=(0,T.objectKeys)(x).filter(Te=>typeof x[x[Te]]!="number"),R={};for(let Te of v)R[Te]=x[Te];return(0,T.objectValues)(R)},T.objectValues=x=>(0,T.objectKeys)(x).map(function(v){return x[v]}),T.objectKeys=typeof Object.keys=="function"?x=>Object.keys(x):x=>{let v=[];for(let R in x)Object.prototype.hasOwnProperty.call(x,R)&&v.push(R);return v},T.find=(x,v)=>{for(let R of x)if(v(R))return R},T.isInteger=typeof Number.isInteger=="function"?x=>Number.isInteger(x):x=>typeof x=="number"&&isFinite(x)&&Math.floor(x)===x;function c(x,v=" | "){return x.map(R=>typeof R=="string"?`'${R}'`:R).join(v)}T.joinValues=c,T.jsonStringifyReplacer=(x,v)=>typeof v=="bigint"?v.toString():v})(b||={});var Me;(e=>e.mergeShapes=(t,r)=>({...t,...r}))(Me||={});var p=b.arrayToEnum(["string","nan","number","integer","float","boolean","date","bigint","symbol","function","undefined","null","array","object","unknown","promise","void","never","map","set"]),V=n=>{switch(typeof n){case"undefined":return p.undefined;case"string":return p.string;case"number":return isNaN(n)?p.nan:p.number;case"boolean":return p.boolean;case"function":return p.function;case"bigint":return p.bigint;case"symbol":return p.symbol;case"object":return Array.isArray(n)?p.array:n===null?p.null:n.then&&typeof n.then=="function"&&n.catch&&typeof n.catch=="function"?p.promise:typeof Map<"u"&&n instanceof Map?p.map:typeof Set<"u"&&n instanceof Set?p.set:typeof Date<"u"&&n instanceof Date?p.date:p.object;default:return p.unknown}};var d=b.arrayToEnum(["invalid_type","invalid_literal","custom","invalid_union","invalid_union_discriminator","invalid_enum_value","unrecognized_keys","invalid_arguments","invalid_return_type","invalid_date","invalid_string","too_small","too_big","invalid_intersection_types","not_multiple_of","not_finite"]),jn=n=>JSON.stringify(n,null,2).replace(/"([^"]+)":/g,"$1:"),P=class n extends Error{issues=[];get errors(){return this.issues}constructor(e){super();let t=new.target.prototype;Object.setPrototypeOf?Object.setPrototypeOf(this,t):this.__proto__=t,this.name="ZodError",this.issues=e}format(e){let t=e||function(a){return a.message},r={_errors:[]},s=a=>{for(let o of a.issues)if(o.code==="invalid_union")o.unionErrors.map(s);else if(o.code==="invalid_return_type")s(o.returnTypeError);else if(o.code==="invalid_arguments")s(o.argumentsError);else if(o.path.length===0)r._errors.push(t(o));else{let i=r,y=0;for(;ynew n(e);static assert(e){if(!(e instanceof n))throw new Error(`Not a ZodError: ${e}`)}toString(){return this.message}get message(){return JSON.stringify(this.issues,b.jsonStringifyReplacer,2)}get isEmpty(){return this.issues.length===0}addIssue=e=>{this.issues=[...this.issues,e]};addIssues=(e=[])=>{this.issues=[...this.issues,...e]};flatten(e=t=>t.message){let t={},r=[];for(let s of this.issues)s.path.length>0?(t[s.path[0]]=t[s.path[0]]||[],t[s.path[0]].push(e(s))):r.push(e(s));return{formErrors:r,fieldErrors:t}}get formErrors(){return this.flatten()}};var Jn=(n,e)=>{let t;switch(n.code){case d.invalid_type:n.received===p.undefined?t="Required":t=`Expected ${n.expected}, received ${n.received}`;break;case d.invalid_literal:t=`Invalid literal value, expected ${JSON.stringify(n.expected,b.jsonStringifyReplacer)}`;break;case d.unrecognized_keys:t=`Unrecognized key(s) in object: ${b.joinValues(n.keys,", ")}`;break;case d.invalid_union:t="Invalid input";break;case d.invalid_union_discriminator:t=`Invalid discriminator value. Expected ${b.joinValues(n.options)}`;break;case d.invalid_enum_value:t=`Invalid enum value. Expected ${b.joinValues(n.options)}, received '${n.received}'`;break;case d.invalid_arguments:t="Invalid function arguments";break;case d.invalid_return_type:t="Invalid function return type";break;case d.invalid_date:t="Invalid date";break;case d.invalid_string:typeof n.validation=="object"?"includes"in n.validation?(t=`Invalid input: must include "${n.validation.includes}"`,typeof n.validation.position=="number"&&(t=`${t} at one or more positions greater than or equal to ${n.validation.position}`)):"startsWith"in n.validation?t=`Invalid input: must start with "${n.validation.startsWith}"`:"endsWith"in n.validation?t=`Invalid input: must end with "${n.validation.endsWith}"`:b.assertNever(n.validation):n.validation!=="regex"?t=`Invalid ${n.validation}`:t="Invalid";break;case d.too_small:n.type==="array"?t=`Array must contain ${n.exact?"exactly":n.inclusive?"at least":"more than"} ${n.minimum} element(s)`:n.type==="string"?t=`String must contain ${n.exact?"exactly":n.inclusive?"at least":"over"} ${n.minimum} character(s)`:n.type==="number"?t=`Number must be ${n.exact?"exactly equal to ":n.inclusive?"greater than or equal to ":"greater than "}${n.minimum}`:n.type==="date"?t=`Date must be ${n.exact?"exactly equal to ":n.inclusive?"greater than or equal to ":"greater than "}${new Date(Number(n.minimum))}`:t="Invalid input";break;case d.too_big:n.type==="array"?t=`Array must contain ${n.exact?"exactly":n.inclusive?"at most":"less than"} ${n.maximum} element(s)`:n.type==="string"?t=`String must contain ${n.exact?"exactly":n.inclusive?"at most":"under"} ${n.maximum} character(s)`:n.type==="number"?t=`Number must be ${n.exact?"exactly":n.inclusive?"less than or equal to":"less than"} ${n.maximum}`:n.type==="bigint"?t=`BigInt must be ${n.exact?"exactly":n.inclusive?"less than or equal to":"less than"} ${n.maximum}`:n.type==="date"?t=`Date must be ${n.exact?"exactly":n.inclusive?"smaller than or equal to":"smaller than"} ${new Date(Number(n.maximum))}`:t="Invalid input";break;case d.custom:t="Invalid input";break;case d.invalid_intersection_types:t="Intersection results could not be merged";break;case d.not_multiple_of:t=`Number must be a multiple of ${n.multipleOf}`;break;case d.not_finite:t="Number must be finite";break;default:t=e.defaultError,b.assertNever(n)}return{message:t}},_=Jn;var je=_;function zn(n){je=n}function M(){return je}var ae=n=>{let{data:e,path:t,errorMaps:r,issueData:s}=n,a=[...t,...s.path||[]],o={...s,path:a};if(s.message!==void 0)return{...s,path:a,message:s.message};let i="",y=r.filter(c=>!!c).slice().reverse();for(let c of y)i=c(o,{data:e,defaultError:i}).message;return{...s,path:a,message:i}},qn=[];function l(n,e){let t=M(),r=ae({issueData:e,data:n.data,path:n.path,errorMaps:[n.common.contextualErrorMap,n.schemaErrorMap,t,t===_?void 0:_].filter(s=>!!s)});n.common.issues.push(r)}var k=class n{value="valid";dirty(){this.value==="valid"&&(this.value="dirty")}abort(){this.value!=="aborted"&&(this.value="aborted")}static mergeArray(e,t){let r=[];for(let s of t){if(s.status==="aborted")return g;s.status==="dirty"&&e.dirty(),r.push(s.value)}return{status:e.value,value:r}}static async mergeObjectAsync(e,t){let r=[];for(let s of t){let a=await s.key,o=await s.value;r.push({key:a,value:o})}return n.mergeObjectSync(e,r)}static mergeObjectSync(e,t){let r={};for(let s of t){let{key:a,value:o}=s;if(a.status==="aborted"||o.status==="aborted")return g;a.status==="dirty"&&e.dirty(),o.status==="dirty"&&e.dirty(),a.value!=="__proto__"&&(typeof o.value<"u"||s.alwaysSet)&&(r[a.value]=o.value)}return{status:e.value,value:r}}},g=Object.freeze({status:"aborted"}),Y=n=>({status:"dirty",value:n}),A=n=>({status:"valid",value:n}),Ce=n=>n.status==="aborted",ve=n=>n.status==="dirty",j=n=>n.status==="valid",J=n=>typeof Promise<"u"&&n instanceof Promise;var m;(t=>(t.errToObj=r=>typeof r=="string"?{message:r}:r||{},t.toString=r=>typeof r=="string"?r:r?.message))(m||={});var w=class{parent;data;_path;_key;_cachedPath=[];constructor(e,t,r,s){this.parent=e,this.data=t,this._path=r,this._key=s}get path(){return this._cachedPath.length||(this._key instanceof Array?this._cachedPath.push(...this._path,...this._key):this._cachedPath.push(...this._path,this._key)),this._cachedPath}},Je=(n,e)=>{if(j(e))return{success:!0,data:e.value};if(!n.common.issues.length)throw new Error("Validation failed but no issues detected.");return{success:!1,get error(){if(this._error)return this._error;let t=new P(n.common.issues);return this._error=t,this._error}}};function Z(n){if(!n)return{};let{errorMap:e,invalid_type_error:t,required_error:r,description:s}=n;if(e&&(t||r))throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);return e?{errorMap:e,description:s}:{errorMap:(o,i)=>{let{message:y}=n;return o.code==="invalid_enum_value"?{message:y??i.defaultError}:typeof i.data>"u"?{message:y??r??i.defaultError}:o.code!=="invalid_type"?{message:i.defaultError}:{message:y??t??i.defaultError}},description:s}}var I=class{_type;_output;_input;_def;get description(){return this._def.description}_getType(e){return V(e.data)}_getOrReturnCtx(e,t){return t||{common:e.parent.common,data:e.data,parsedType:V(e.data),schemaErrorMap:this._def.errorMap,path:e.path,parent:e.parent}}_processInputParams(e){return{status:new k,ctx:{common:e.parent.common,data:e.data,parsedType:V(e.data),schemaErrorMap:this._def.errorMap,path:e.path,parent:e.parent}}}_parseSync(e){let t=this._parse(e);if(J(t))throw new Error("Synchronous parse encountered promise.");return t}_parseAsync(e){let t=this._parse(e);return Promise.resolve(t)}parse(e,t){let r=this.safeParse(e,t);if(r.success)return r.data;throw r.error}safeParse(e,t){let r={common:{issues:[],async:t?.async??!1,contextualErrorMap:t?.errorMap},path:t?.path||[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:V(e)},s=this._parseSync({data:e,path:r.path,parent:r});return Je(r,s)}async parseAsync(e,t){let r=await this.safeParseAsync(e,t);if(r.success)return r.data;throw r.error}async safeParseAsync(e,t){let r={common:{issues:[],contextualErrorMap:t?.errorMap,async:!0},path:t?.path||[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:V(e)},s=this._parse({data:e,path:r.path,parent:r}),a=await(J(s)?s:Promise.resolve(s));return Je(r,a)}spa=this.safeParseAsync;refine(e,t){let r=s=>typeof t=="string"||typeof t>"u"?{message:t}:typeof t=="function"?t(s):t;return this._refinement((s,a)=>{let o=e(s),i=()=>a.addIssue({code:d.custom,...r(s)});return typeof Promise<"u"&&o instanceof Promise?o.then(y=>y?!0:(i(),!1)):o?!0:(i(),!1)})}refinement(e,t){return this._refinement((r,s)=>e(r)?!0:(s.addIssue(typeof t=="function"?t(r,s):t),!1))}_refinement(e){return new X({schema:this,typeName:"ZodEffects",effect:{type:"refinement",refinement:e}})}superRefine(e){return this._refinement(e)}constructor(e){this._def=e,this.parse=this.parse.bind(this),this.safeParse=this.safeParse.bind(this),this.parseAsync=this.parseAsync.bind(this),this.safeParseAsync=this.safeParseAsync.bind(this),this.spa=this.spa.bind(this),this.refine=this.refine.bind(this),this.refinement=this.refinement.bind(this),this.superRefine=this.superRefine.bind(this),this.optional=this.optional.bind(this),this.nullable=this.nullable.bind(this),this.nullish=this.nullish.bind(this),this.array=this.array.bind(this),this.promise=this.promise.bind(this),this.or=this.or.bind(this),this.and=this.and.bind(this),this.transform=this.transform.bind(this),this.brand=this.brand.bind(this),this.default=this.default.bind(this),this.catch=this.catch.bind(this),this.describe=this.describe.bind(this),this.pipe=this.pipe.bind(this),this.readonly=this.readonly.bind(this),this.isNullable=this.isNullable.bind(this),this.isOptional=this.isOptional.bind(this)}optional(){return W.create(this,this._def)}nullable(){return D.create(this,this._def)}nullish(){return this.nullable().optional()}array(){return F.create(this,this._def)}promise(){return ee.create(this,this._def)}or(e){return pe.create([this,e],this._def)}and(e){return ye.create(this,e,this._def)}transform(e){return new X({...Z(this._def),schema:this,typeName:"ZodEffects",effect:{type:"transform",transform:e}})}default(e){let t=typeof e=="function"?e:()=>e;return new Ze({...Z(this._def),innerType:this,defaultValue:t,typeName:"ZodDefault"})}brand(){return new he({typeName:"ZodBranded",type:this,...Z(this._def)})}catch(e){let t=typeof e=="function"?e:()=>e;return new Ie({...Z(this._def),innerType:this,catchValue:t,typeName:"ZodCatch"})}describe(e){let t=this.constructor;return new t({...this._def,description:e})}pipe(e){return be.create(this,e)}readonly(){return xe.create(this)}isOptional(){return this.safeParse(void 0).success}isNullable(){return this.safeParse(null).success}},Qn=/^c[^\s-]{8,}$/i,$n=/^[0-9a-z]+$/,er=/^[0-9A-HJKMNP-TV-Z]{26}$/,tr=/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i,nr=/^[a-z0-9_-]{21}$/i,rr=/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/,sr=/^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i,ar="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$",Ue,or=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ir=/^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/,dr=/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/,ze="((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))",ur=new RegExp(`^${ze}$`);function qe(n){let e="([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";return n.precision?e=`${e}\\.\\d{${n.precision}}`:n.precision==null&&(e=`${e}(\\.\\d+)?`),e}function cr(n){return new RegExp(`^${qe(n)}$`)}function Qe(n){let e=`${ze}T${qe(n)}`,t=[];return t.push(n.local?"Z?":"Z"),n.offset&&t.push("([+-]\\d{2}:?\\d{2})"),e=`${e}(${t.join("|")})`,new RegExp(`^${e}$`)}function lr(n,e){return!!((e==="v4"||!e)&&or.test(n)||(e==="v6"||!e)&&ir.test(n))}var q=class n extends I{_parse(e){if(this._def.coerce&&(e.data=String(e.data)),this._getType(e)!==p.string){let a=this._getOrReturnCtx(e);return l(a,{code:d.invalid_type,expected:p.string,received:a.parsedType}),g}let r=new k,s;for(let a of this._def.checks)if(a.kind==="min")e.data.lengtha.value&&(s=this._getOrReturnCtx(e,s),l(s,{code:d.too_big,maximum:a.value,type:"string",inclusive:!0,exact:!1,message:a.message}),r.dirty());else if(a.kind==="length"){let o=e.data.length>a.value,i=e.data.lengthe.test(s),{validation:t,code:d.invalid_string,...m.errToObj(r)})}_addCheck(e){return new n({...this._def,checks:[...this._def.checks,e]})}email(e){return this._addCheck({kind:"email",...m.errToObj(e)})}url(e){return this._addCheck({kind:"url",...m.errToObj(e)})}emoji(e){return this._addCheck({kind:"emoji",...m.errToObj(e)})}uuid(e){return this._addCheck({kind:"uuid",...m.errToObj(e)})}nanoid(e){return this._addCheck({kind:"nanoid",...m.errToObj(e)})}cuid(e){return this._addCheck({kind:"cuid",...m.errToObj(e)})}cuid2(e){return this._addCheck({kind:"cuid2",...m.errToObj(e)})}ulid(e){return this._addCheck({kind:"ulid",...m.errToObj(e)})}base64(e){return this._addCheck({kind:"base64",...m.errToObj(e)})}ip(e){return this._addCheck({kind:"ip",...m.errToObj(e)})}datetime(e){return typeof e=="string"?this._addCheck({kind:"datetime",precision:null,offset:!1,local:!1,message:e}):this._addCheck({kind:"datetime",precision:typeof e?.precision>"u"?null:e?.precision,offset:e?.offset??!1,local:e?.local??!1,...m.errToObj(e?.message)})}date(e){return this._addCheck({kind:"date",message:e})}time(e){return typeof e=="string"?this._addCheck({kind:"time",precision:null,message:e}):this._addCheck({kind:"time",precision:typeof e?.precision>"u"?null:e?.precision,...m.errToObj(e?.message)})}duration(e){return this._addCheck({kind:"duration",...m.errToObj(e)})}regex(e,t){return this._addCheck({kind:"regex",regex:e,...m.errToObj(t)})}includes(e,t){return this._addCheck({kind:"includes",value:e,position:t?.position,...m.errToObj(t?.message)})}startsWith(e,t){return this._addCheck({kind:"startsWith",value:e,...m.errToObj(t)})}endsWith(e,t){return this._addCheck({kind:"endsWith",value:e,...m.errToObj(t)})}min(e,t){return this._addCheck({kind:"min",value:e,...m.errToObj(t)})}max(e,t){return this._addCheck({kind:"max",value:e,...m.errToObj(t)})}length(e,t){return this._addCheck({kind:"length",value:e,...m.errToObj(t)})}nonempty(e){return this.min(1,m.errToObj(e))}trim(){return new n({...this._def,checks:[...this._def.checks,{kind:"trim"}]})}toLowerCase(){return new n({...this._def,checks:[...this._def.checks,{kind:"toLowerCase"}]})}toUpperCase(){return new n({...this._def,checks:[...this._def.checks,{kind:"toUpperCase"}]})}get isDatetime(){return!!this._def.checks.find(e=>e.kind==="datetime")}get isDate(){return!!this._def.checks.find(e=>e.kind==="date")}get isTime(){return!!this._def.checks.find(e=>e.kind==="time")}get isDuration(){return!!this._def.checks.find(e=>e.kind==="duration")}get isEmail(){return!!this._def.checks.find(e=>e.kind==="email")}get isURL(){return!!this._def.checks.find(e=>e.kind==="url")}get isEmoji(){return!!this._def.checks.find(e=>e.kind==="emoji")}get isUUID(){return!!this._def.checks.find(e=>e.kind==="uuid")}get isNANOID(){return!!this._def.checks.find(e=>e.kind==="nanoid")}get isCUID(){return!!this._def.checks.find(e=>e.kind==="cuid")}get isCUID2(){return!!this._def.checks.find(e=>e.kind==="cuid2")}get isULID(){return!!this._def.checks.find(e=>e.kind==="ulid")}get isIP(){return!!this._def.checks.find(e=>e.kind==="ip")}get isBase64(){return!!this._def.checks.find(e=>e.kind==="base64")}get minLength(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e}get maxLength(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuenew n({checks:[],typeName:"ZodString",coerce:e?.coerce??!1,...Z(e)})};function pr(n,e){let t=(n.toString().split(".")[1]||"").length,r=(e.toString().split(".")[1]||"").length,s=t>r?t:r,a=parseInt(n.toFixed(s).replace(".","")),o=parseInt(e.toFixed(s).replace(".",""));return a%o/Math.pow(10,s)}var oe=class n extends I{_parse(e){if(this._def.coerce&&(e.data=Number(e.data)),this._getType(e)!==p.number){let a=this._getOrReturnCtx(e);return l(a,{code:d.invalid_type,expected:p.number,received:a.parsedType}),g}let r,s=new k;for(let a of this._def.checks)a.kind==="int"?b.isInteger(e.data)||(r=this._getOrReturnCtx(e,r),l(r,{code:d.invalid_type,expected:"integer",received:"float",message:a.message}),s.dirty()):a.kind==="min"?(a.inclusive?e.dataa.value:e.data>=a.value)&&(r=this._getOrReturnCtx(e,r),l(r,{code:d.too_big,maximum:a.value,type:"number",inclusive:a.inclusive,exact:!1,message:a.message}),s.dirty()):a.kind==="multipleOf"?pr(e.data,a.value)!==0&&(r=this._getOrReturnCtx(e,r),l(r,{code:d.not_multiple_of,multipleOf:a.value,message:a.message}),s.dirty()):a.kind==="finite"?Number.isFinite(e.data)||(r=this._getOrReturnCtx(e,r),l(r,{code:d.not_finite,message:a.message}),s.dirty()):b.assertNever(a);return{status:s.value,value:e.data}}static create=e=>new n({checks:[],typeName:"ZodNumber",coerce:e?.coerce||!1,...Z(e)});gte(e,t){return this.setLimit("min",e,!0,m.toString(t))}min=this.gte;gt(e,t){return this.setLimit("min",e,!1,m.toString(t))}lte(e,t){return this.setLimit("max",e,!0,m.toString(t))}max=this.lte;lt(e,t){return this.setLimit("max",e,!1,m.toString(t))}setLimit(e,t,r,s){return new n({...this._def,checks:[...this._def.checks,{kind:e,value:t,inclusive:r,message:m.toString(s)}]})}_addCheck(e){return new n({...this._def,checks:[...this._def.checks,e]})}int(e){return this._addCheck({kind:"int",message:m.toString(e)})}positive(e){return this._addCheck({kind:"min",value:0,inclusive:!1,message:m.toString(e)})}negative(e){return this._addCheck({kind:"max",value:0,inclusive:!1,message:m.toString(e)})}nonpositive(e){return this._addCheck({kind:"max",value:0,inclusive:!0,message:m.toString(e)})}nonnegative(e){return this._addCheck({kind:"min",value:0,inclusive:!0,message:m.toString(e)})}multipleOf(e,t){return this._addCheck({kind:"multipleOf",value:e,message:m.toString(t)})}step=this.multipleOf;finite(e){return this._addCheck({kind:"finite",message:m.toString(e)})}safe(e){return this._addCheck({kind:"min",inclusive:!0,value:Number.MIN_SAFE_INTEGER,message:m.toString(e)})._addCheck({kind:"max",inclusive:!0,value:Number.MAX_SAFE_INTEGER,message:m.toString(e)})}get minValue(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e}get maxValue(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuee.kind==="int"||e.kind==="multipleOf"&&b.isInteger(e.value))}get isFinite(){let e=null,t=null;for(let r of this._def.checks){if(r.kind==="finite"||r.kind==="int"||r.kind==="multipleOf")return!0;r.kind==="min"?(t===null||r.value>t)&&(t=r.value):r.kind==="max"&&(e===null||r.valuea.value:e.data>=a.value)&&(r=this._getOrReturnCtx(e,r),l(r,{code:d.too_big,type:"bigint",maximum:a.value,inclusive:a.inclusive,message:a.message}),s.dirty()):a.kind==="multipleOf"?e.data%a.value!==BigInt(0)&&(r=this._getOrReturnCtx(e,r),l(r,{code:d.not_multiple_of,multipleOf:a.value,message:a.message}),s.dirty()):b.assertNever(a);return{status:s.value,value:e.data}}static create=e=>new n({checks:[],typeName:"ZodBigInt",coerce:e?.coerce??!1,...Z(e)});gte(e,t){return this.setLimit("min",e,!0,m.toString(t))}min=this.gte;gt(e,t){return this.setLimit("min",e,!1,m.toString(t))}lte(e,t){return this.setLimit("max",e,!0,m.toString(t))}max=this.lte;lt(e,t){return this.setLimit("max",e,!1,m.toString(t))}setLimit(e,t,r,s){return new n({...this._def,checks:[...this._def.checks,{kind:e,value:t,inclusive:r,message:m.toString(s)}]})}_addCheck(e){return new n({...this._def,checks:[...this._def.checks,e]})}positive(e){return this._addCheck({kind:"min",value:BigInt(0),inclusive:!1,message:m.toString(e)})}negative(e){return this._addCheck({kind:"max",value:BigInt(0),inclusive:!1,message:m.toString(e)})}nonpositive(e){return this._addCheck({kind:"max",value:BigInt(0),inclusive:!0,message:m.toString(e)})}nonnegative(e){return this._addCheck({kind:"min",value:BigInt(0),inclusive:!0,message:m.toString(e)})}multipleOf(e,t){return this._addCheck({kind:"multipleOf",value:e,message:m.toString(t)})}get minValue(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e}get maxValue(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuenew n({typeName:"ZodBoolean",coerce:e?.coerce||!1,...Z(e)})},ue=class n extends I{_parse(e){if(this._def.coerce&&(e.data=new Date(e.data)),this._getType(e)!==p.date){let a=this._getOrReturnCtx(e);return l(a,{code:d.invalid_type,expected:p.date,received:a.parsedType}),g}if(isNaN(e.data.getTime())){let a=this._getOrReturnCtx(e);return l(a,{code:d.invalid_date}),g}let r=new k,s;for(let a of this._def.checks)a.kind==="min"?e.data.getTime()a.value&&(s=this._getOrReturnCtx(e,s),l(s,{code:d.too_big,message:a.message,inclusive:!0,exact:!1,maximum:a.value,type:"date"}),r.dirty()):b.assertNever(a);return{status:r.value,value:new Date(e.data.getTime())}}_addCheck(e){return new n({...this._def,checks:[...this._def.checks,e]})}min(e,t){return this._addCheck({kind:"min",value:e.getTime(),message:m.toString(t)})}max(e,t){return this._addCheck({kind:"max",value:e.getTime(),message:m.toString(t)})}get minDate(){let e=null;for(let t of this._def.checks)t.kind==="min"&&(e===null||t.value>e)&&(e=t.value);return e!=null?new Date(e):null}get maxDate(){let e=null;for(let t of this._def.checks)t.kind==="max"&&(e===null||t.valuenew n({checks:[],coerce:e?.coerce||!1,typeName:"ZodDate",...Z(e)})},ke=class n extends I{_parse(e){if(this._getType(e)!==p.symbol){let r=this._getOrReturnCtx(e);return l(r,{code:d.invalid_type,expected:p.symbol,received:r.parsedType}),g}return A(e.data)}static create=e=>new n({typeName:"ZodSymbol",...Z(e)})},ce=class n extends I{_parse(e){if(this._getType(e)!==p.undefined){let r=this._getOrReturnCtx(e);return l(r,{code:d.invalid_type,expected:p.undefined,received:r.parsedType}),g}return A(e.data)}params;static create=e=>new n({typeName:"ZodUndefined",...Z(e)})},le=class n extends I{_parse(e){if(this._getType(e)!==p.null){let r=this._getOrReturnCtx(e);return l(r,{code:d.invalid_type,expected:p.null,received:r.parsedType}),g}return A(e.data)}static create=e=>new n({typeName:"ZodNull",...Z(e)})},Q=class n extends I{_any=!0;_parse(e){return A(e.data)}static create=e=>new n({typeName:"ZodAny",...Z(e)})},H=class n extends I{_unknown=!0;_parse(e){return A(e.data)}static create=e=>new n({typeName:"ZodUnknown",...Z(e)})},L=class n extends I{_parse(e){let t=this._getOrReturnCtx(e);return l(t,{code:d.invalid_type,expected:p.never,received:t.parsedType}),g}static create=e=>new n({typeName:"ZodNever",...Z(e)})},Ae=class n extends I{_parse(e){if(this._getType(e)!==p.undefined){let r=this._getOrReturnCtx(e);return l(r,{code:d.invalid_type,expected:p.void,received:r.parsedType}),g}return A(e.data)}static create=e=>new n({typeName:"ZodVoid",...Z(e)})},F=class n extends I{_parse(e){let{ctx:t,status:r}=this._processInputParams(e),s=this._def;if(t.parsedType!==p.array)return l(t,{code:d.invalid_type,expected:p.array,received:t.parsedType}),g;if(s.exactLength!==null){let o=t.data.length>s.exactLength.value,i=t.data.lengths.maxLength.value&&(l(t,{code:d.too_big,maximum:s.maxLength.value,type:"array",inclusive:!0,exact:!1,message:s.maxLength.message}),r.dirty()),t.common.async)return Promise.all([...t.data].map((o,i)=>s.type._parseAsync(new w(t,o,t.path,i)))).then(o=>k.mergeArray(r,o));let a=[...t.data].map((o,i)=>s.type._parseSync(new w(t,o,t.path,i)));return k.mergeArray(r,a)}get element(){return this._def.type}min(e,t){return new n({...this._def,minLength:{value:e,message:m.toString(t)}})}max(e,t){return new n({...this._def,maxLength:{value:e,message:m.toString(t)}})}length(e,t){return new n({...this._def,exactLength:{value:e,message:m.toString(t)}})}nonempty(e){return this.min(1,e)}static create=(e,t)=>new n({type:e,minLength:null,maxLength:null,exactLength:null,typeName:"ZodArray",...Z(t)})};function z(n){if(n instanceof U){let e={};for(let t in n.shape){let r=n.shape[t];e[t]=W.create(z(r))}return new U({...n._def,shape:()=>e})}else return n instanceof F?new F({...n._def,type:z(n.element)}):n instanceof W?W.create(z(n.unwrap())):n instanceof D?D.create(z(n.unwrap())):n instanceof E?E.create(n.items.map(e=>z(e))):n}var U=class n extends I{_cached=null;_getCached(){if(this._cached!==null)return this._cached;let e=this._def.shape(),t=b.objectKeys(e);return this._cached={shape:e,keys:t}}_parse(e){if(this._getType(e)!==p.object){let c=this._getOrReturnCtx(e);return l(c,{code:d.invalid_type,expected:p.object,received:c.parsedType}),g}let{status:r,ctx:s}=this._processInputParams(e),{shape:a,keys:o}=this._getCached(),i=[];if(!(this._def.catchall instanceof L&&this._def.unknownKeys==="strip"))for(let c in s.data)o.includes(c)||i.push(c);let y=[];for(let c of o){let f=a[c],T=s.data[c];y.push({key:{status:"valid",value:c},value:f._parse(new w(s,T,s.path,c)),alwaysSet:c in s.data})}if(this._def.catchall instanceof L){let c=this._def.unknownKeys;if(c==="passthrough")for(let f of i)y.push({key:{status:"valid",value:f},value:{status:"valid",value:s.data[f]}});else if(c==="strict")i.length>0&&(l(s,{code:d.unrecognized_keys,keys:i}),r.dirty());else if(c!=="strip")throw new Error("Internal ZodObject error: invalid unknownKeys value.")}else{let c=this._def.catchall;for(let f of i){let T=s.data[f];y.push({key:{status:"valid",value:f},value:c._parse(new w(s,T,s.path,f)),alwaysSet:f in s.data})}}return s.common.async?Promise.resolve().then(async()=>{let c=[];for(let f of y){let T=await f.key,x=await f.value;c.push({key:T,value:x,alwaysSet:f.alwaysSet})}return c}).then(c=>k.mergeObjectSync(r,c)):k.mergeObjectSync(r,y)}get shape(){return this._def.shape()}strict(e){return m.errToObj,new n({...this._def,unknownKeys:"strict",...e!==void 0?{errorMap:(t,r)=>{let s=this._def.errorMap?.(t,r).message??r.defaultError;return t.code==="unrecognized_keys"?{message:m.errToObj(e).message??s}:{message:s}}}:{}})}strip(){return new n({...this._def,unknownKeys:"strip"})}passthrough(){return new n({...this._def,unknownKeys:"passthrough"})}nonstrict=this.passthrough;extend(e){return new n({...this._def,shape:()=>({...this._def.shape(),...e})})}augment=this.extend;merge(e){return new n({unknownKeys:e._def.unknownKeys,catchall:e._def.catchall,shape:()=>({...this._def.shape(),...e._def.shape()}),typeName:"ZodObject"})}setKey(e,t){return this.augment({[e]:t})}catchall(e){return new n({...this._def,catchall:e})}pick(e){let t={};return b.objectKeys(e).forEach(r=>{e[r]&&this.shape[r]&&(t[r]=this.shape[r])}),new n({...this._def,shape:()=>t})}omit(e){let t={};return b.objectKeys(this.shape).forEach(r=>{e[r]||(t[r]=this.shape[r])}),new n({...this._def,shape:()=>t})}deepPartial(){return z(this)}partial(e){let t={};return b.objectKeys(this.shape).forEach(r=>{let s=this.shape[r];e&&!e[r]?t[r]=s:t[r]=s.optional()}),new n({...this._def,shape:()=>t})}required(e){let t={};return b.objectKeys(this.shape).forEach(r=>{if(e&&!e[r])t[r]=this.shape[r];else{let a=this.shape[r];for(;a instanceof W;)a=a._def.innerType;t[r]=a}}),new n({...this._def,shape:()=>t})}keyof(){return $e(b.objectKeys(this.shape))}static create=(e,t)=>new n({shape:()=>e,unknownKeys:"strip",catchall:L.create(),typeName:"ZodObject",...Z(t)});static strictCreate=(e,t)=>new n({shape:()=>e,unknownKeys:"strict",catchall:L.create(),typeName:"ZodObject",...Z(t)});static lazycreate=(e,t)=>new n({shape:e,unknownKeys:"strip",catchall:L.create(),typeName:"ZodObject",...Z(t)})},pe=class n extends I{_parse(e){let{ctx:t}=this._processInputParams(e),r=this._def.options;function s(a){for(let i of a)if(i.result.status==="valid")return i.result;for(let i of a)if(i.result.status==="dirty")return t.common.issues.push(...i.ctx.common.issues),i.result;let o=a.map(i=>new P(i.ctx.common.issues));return l(t,{code:d.invalid_union,unionErrors:o}),g}if(t.common.async)return Promise.all(r.map(async a=>{let o={...t,common:{...t.common,issues:[]},parent:null};return{result:await a._parseAsync({data:t.data,path:t.path,parent:o}),ctx:o}})).then(s);{let a,o=[];for(let y of r){let c={...t,common:{...t.common,issues:[]},parent:null},f=y._parseSync({data:t.data,path:t.path,parent:c});if(f.status==="valid")return f;f.status==="dirty"&&!a&&(a={result:f,ctx:c}),c.common.issues.length&&o.push(c.common.issues)}if(a)return t.common.issues.push(...a.ctx.common.issues),a.result;let i=o.map(y=>new P(y));return l(t,{code:d.invalid_union,unionErrors:i}),g}}get options(){return this._def.options}static create=(e,t)=>new n({options:e,typeName:"ZodUnion",...Z(t)})},N=n=>n instanceof me?N(n.schema):n instanceof X?N(n.innerType()):n instanceof ge?[n.value]:n instanceof $?n.options:n instanceof fe?b.objectValues(n.enum):n instanceof Ze?N(n._def.innerType):n instanceof ce?[void 0]:n instanceof le?[null]:n instanceof W?[void 0,...N(n.unwrap())]:n instanceof D?[null,...N(n.unwrap())]:n instanceof he||n instanceof xe?N(n.unwrap()):n instanceof Ie?N(n._def.innerType):[],Re=class n extends I{_parse(e){let{ctx:t}=this._processInputParams(e);if(t.parsedType!==p.object)return l(t,{code:d.invalid_type,expected:p.object,received:t.parsedType}),g;let r=this.discriminator,s=t.data[r],a=this.optionsMap.get(s);return a?t.common.async?a._parseAsync({data:t.data,path:t.path,parent:t}):a._parseSync({data:t.data,path:t.path,parent:t}):(l(t,{code:d.invalid_union_discriminator,options:Array.from(this.optionsMap.keys()),path:[r]}),g)}get discriminator(){return this._def.discriminator}get options(){return this._def.options}get optionsMap(){return this._def.optionsMap}static create(e,t,r){let s=new Map;for(let a of t){let o=N(a.shape[e]);if(!o.length)throw new Error(`A discriminator value for key \`${e}\` could not be extracted from all schema options`);for(let i of o){if(s.has(i))throw new Error(`Discriminator property ${String(e)} has duplicate value ${String(i)}`);s.set(i,a)}}return new n({typeName:"ZodDiscriminatedUnion",discriminator:e,options:t,optionsMap:s,...Z(r)})}};function Ee(n,e){let t=V(n),r=V(e);if(n===e)return{valid:!0,data:n};if(t===p.object&&r===p.object){let s=b.objectKeys(e),a=b.objectKeys(n).filter(i=>s.indexOf(i)!==-1),o={...n,...e};for(let i of a){let y=Ee(n[i],e[i]);if(!y.valid)return{valid:!1};o[i]=y.data}return{valid:!0,data:o}}else if(t===p.array&&r===p.array){if(n.length!==e.length)return{valid:!1};let s=[];for(let a=0;a{if(Ce(a)||Ce(o))return g;let i=Ee(a.value,o.value);return i.valid?((ve(a)||ve(o))&&t.dirty(),{status:t.value,value:i.data}):(l(r,{code:d.invalid_intersection_types}),g)};return r.common.async?Promise.all([this._def.left._parseAsync({data:r.data,path:r.path,parent:r}),this._def.right._parseAsync({data:r.data,path:r.path,parent:r})]).then(([a,o])=>s(a,o)):s(this._def.left._parseSync({data:r.data,path:r.path,parent:r}),this._def.right._parseSync({data:r.data,path:r.path,parent:r}))}static create=(e,t,r)=>new n({left:e,right:t,typeName:"ZodIntersection",...Z(r)})},E=class n extends I{_parse(e){let{status:t,ctx:r}=this._processInputParams(e);if(r.parsedType!==p.array)return l(r,{code:d.invalid_type,expected:p.array,received:r.parsedType}),g;if(r.data.lengththis._def.items.length&&(l(r,{code:d.too_big,maximum:this._def.items.length,inclusive:!0,exact:!1,type:"array"}),t.dirty());let a=[...r.data].map((o,i)=>{let y=this._def.items[i]||this._def.rest;return y?y._parse(new w(r,o,r.path,i)):null}).filter(o=>!!o);return r.common.async?Promise.all(a).then(o=>k.mergeArray(t,o)):k.mergeArray(t,a)}get items(){return this._def.items}rest(e){return new n({...this._def,rest:e})}static create=(e,t)=>{if(!Array.isArray(e))throw new Error("You must pass an array of schemas to z.tuple([ ... ])");return new n({items:e,typeName:"ZodTuple",rest:null,...Z(t)})}},Pe=class n extends I{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(e){let{status:t,ctx:r}=this._processInputParams(e);if(r.parsedType!==p.object)return l(r,{code:d.invalid_type,expected:p.object,received:r.parsedType}),g;let s=[],a=this._def.keyType,o=this._def.valueType;for(let i in r.data)s.push({key:a._parse(new w(r,i,r.path,i)),value:o._parse(new w(r,r.data[i],r.path,i)),alwaysSet:i in r.data});return r.common.async?k.mergeObjectAsync(t,s):k.mergeObjectSync(t,s)}get element(){return this._def.valueType}static create(e,t,r){return t instanceof I?new n({keyType:e,valueType:t,typeName:"ZodRecord",...Z(r)}):new n({keyType:q.create(),valueType:e,typeName:"ZodRecord",...Z(t)})}},Se=class n extends I{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(e){let{status:t,ctx:r}=this._processInputParams(e);if(r.parsedType!==p.map)return l(r,{code:d.invalid_type,expected:p.map,received:r.parsedType}),g;let s=this._def.keyType,a=this._def.valueType,o=[...r.data.entries()].map(([i,y],c)=>({key:s._parse(new w(r,i,r.path,[c,"key"])),value:a._parse(new w(r,y,r.path,[c,"value"]))}));if(r.common.async){let i=new Map;return Promise.resolve().then(async()=>{for(let y of o){let c=await y.key,f=await y.value;if(c.status==="aborted"||f.status==="aborted")return g;(c.status==="dirty"||f.status==="dirty")&&t.dirty(),i.set(c.value,f.value)}return{status:t.value,value:i}})}else{let i=new Map;for(let y of o){let c=y.key,f=y.value;if(c.status==="aborted"||f.status==="aborted")return g;(c.status==="dirty"||f.status==="dirty")&&t.dirty(),i.set(c.value,f.value)}return{status:t.value,value:i}}}static create=(e,t,r)=>new n({valueType:t,keyType:e,typeName:"ZodMap",...Z(r)})},we=class n extends I{_parse(e){let{status:t,ctx:r}=this._processInputParams(e);if(r.parsedType!==p.set)return l(r,{code:d.invalid_type,expected:p.set,received:r.parsedType}),g;let s=this._def;s.minSize!==null&&r.data.sizes.maxSize.value&&(l(r,{code:d.too_big,maximum:s.maxSize.value,type:"set",inclusive:!0,exact:!1,message:s.maxSize.message}),t.dirty());let a=this._def.valueType;function o(y){let c=new Set;for(let f of y){if(f.status==="aborted")return g;f.status==="dirty"&&t.dirty(),c.add(f.value)}return{status:t.value,value:c}}let i=[...r.data.values()].map((y,c)=>a._parse(new w(r,y,r.path,c)));return r.common.async?Promise.all(i).then(y=>o(y)):o(i)}min(e,t){return new n({...this._def,minSize:{value:e,message:m.toString(t)}})}max(e,t){return new n({...this._def,maxSize:{value:e,message:m.toString(t)}})}size(e,t){return this.min(e,t).max(e,t)}nonempty(e){return this.min(1,e)}static create=(e,t)=>new n({valueType:e,minSize:null,maxSize:null,typeName:"ZodSet",...Z(t)})},Ke=class n extends I{_parse(e){let{ctx:t}=this._processInputParams(e);if(t.parsedType!==p.function)return l(t,{code:d.invalid_type,expected:p.function,received:t.parsedType}),g;function r(i,y){return ae({data:i,path:t.path,errorMaps:[t.common.contextualErrorMap,t.schemaErrorMap,M(),_].filter(c=>!!c),issueData:{code:d.invalid_arguments,argumentsError:y}})}function s(i,y){return ae({data:i,path:t.path,errorMaps:[t.common.contextualErrorMap,t.schemaErrorMap,M(),_].filter(c=>!!c),issueData:{code:d.invalid_return_type,returnTypeError:y}})}let a={errorMap:t.common.contextualErrorMap},o=t.data;if(this._def.returns instanceof ee){let i=this;return A(async function(...y){let c=new P([]),f=await i._def.args.parseAsync(y,a).catch(v=>{throw c.addIssue(r(y,v)),c}),T=await Reflect.apply(o,this,f);return await i._def.returns._def.type.parseAsync(T,a).catch(v=>{throw c.addIssue(s(T,v)),c})})}else{let i=this;return A(function(...y){let c=i._def.args.safeParse(y,a);if(!c.success)throw new P([r(y,c.error)]);let f=Reflect.apply(o,this,c.data),T=i._def.returns.safeParse(f,a);if(!T.success)throw new P([s(f,T.error)]);return T.data})}}parameters(){return this._def.args}returnType(){return this._def.returns}args(...e){return new n({...this._def,args:E.create(e).rest(H.create())})}returns(e){return new n({...this._def,returns:e})}implement(e){return this.parse(e)}strictImplement(e){return this.parse(e)}validate=this.implement;static create(e,t,r){return new n({args:e||E.create([]).rest(H.create()),returns:t||H.create(),typeName:"ZodFunction",...Z(r)})}},me=class n extends I{get schema(){return this._def.getter()}_parse(e){let{ctx:t}=this._processInputParams(e);return this._def.getter()._parse({data:t.data,path:t.path,parent:t})}static create=(e,t)=>new n({getter:e,typeName:"ZodLazy",...Z(t)})},ge=class n extends I{_parse(e){if(e.data!==this._def.value){let t=this._getOrReturnCtx(e);return l(t,{received:t.data,code:d.invalid_literal,expected:this._def.value}),g}return{status:"valid",value:e.data}}get value(){return this._def.value}static create=(e,t)=>new n({value:e,typeName:"ZodLiteral",...Z(t)})};function $e(n,e){return new $({values:n,typeName:"ZodEnum",...Z(e)})}var $=class n extends I{#e;_parse(e){if(typeof e.data!="string"){let t=this._getOrReturnCtx(e),r=this._def.values;return l(t,{expected:b.joinValues(r),received:t.parsedType,code:d.invalid_type}),g}if(this.#e||(this.#e=new Set(this._def.values)),!this.#e.has(e.data)){let t=this._getOrReturnCtx(e),r=this._def.values;return l(t,{received:t.data,code:d.invalid_enum_value,options:r}),g}return A(e.data)}get options(){return this._def.values}get enum(){let e={};for(let t of this._def.values)e[t]=t;return e}get Values(){let e={};for(let t of this._def.values)e[t]=t;return e}get Enum(){let e={};for(let t of this._def.values)e[t]=t;return e}extract(e,t=this._def){return n.create(e,{...this._def,...t})}exclude(e,t=this._def){return n.create(this.options.filter(r=>!e.includes(r)),{...this._def,...t})}static create=$e},fe=class n extends I{#e;_parse(e){let t=b.getValidEnumValues(this._def.values),r=this._getOrReturnCtx(e);if(r.parsedType!==p.string&&r.parsedType!==p.number){let s=b.objectValues(t);return l(r,{expected:b.joinValues(s),received:r.parsedType,code:d.invalid_type}),g}if(this.#e||(this.#e=new Set(b.getValidEnumValues(this._def.values))),!this.#e.has(e.data)){let s=b.objectValues(t);return l(r,{received:r.data,code:d.invalid_enum_value,options:s}),g}return A(e.data)}get enum(){return this._def.values}static create=(e,t)=>new n({values:e,typeName:"ZodNativeEnum",...Z(t)})},ee=class n extends I{unwrap(){return this._def.type}_parse(e){let{ctx:t}=this._processInputParams(e);if(t.parsedType!==p.promise&&t.common.async===!1)return l(t,{code:d.invalid_type,expected:p.promise,received:t.parsedType}),g;let r=t.parsedType===p.promise?t.data:Promise.resolve(t.data);return A(r.then(s=>this._def.type.parseAsync(s,{path:t.path,errorMap:t.common.contextualErrorMap})))}static create=(e,t)=>new n({type:e,typeName:"ZodPromise",...Z(t)})},X=class n extends I{innerType(){return this._def.schema}sourceType(){return this._def.schema._def.typeName==="ZodEffects"?this._def.schema.sourceType():this._def.schema}_parse(e){let{status:t,ctx:r}=this._processInputParams(e),s=this._def.effect||null,a={addIssue:o=>{l(r,o),o.fatal?t.abort():t.dirty()},get path(){return r.path}};if(a.addIssue=a.addIssue.bind(a),s.type==="preprocess"){let o=s.transform(r.data,a);if(r.common.async)return Promise.resolve(o).then(async i=>{if(t.value==="aborted")return g;let y=await this._def.schema._parseAsync({data:i,path:r.path,parent:r});return y.status==="aborted"?g:y.status==="dirty"?Y(y.value):t.value==="dirty"?Y(y.value):y});{if(t.value==="aborted")return g;let i=this._def.schema._parseSync({data:o,path:r.path,parent:r});return i.status==="aborted"?g:i.status==="dirty"?Y(i.value):t.value==="dirty"?Y(i.value):i}}if(s.type==="refinement"){let o=i=>{let y=s.refinement(i,a);if(r.common.async)return Promise.resolve(y);if(y instanceof Promise)throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");return i};if(r.common.async===!1){let i=this._def.schema._parseSync({data:r.data,path:r.path,parent:r});return i.status==="aborted"?g:(i.status==="dirty"&&t.dirty(),o(i.value),{status:t.value,value:i.value})}else return this._def.schema._parseAsync({data:r.data,path:r.path,parent:r}).then(i=>i.status==="aborted"?g:(i.status==="dirty"&&t.dirty(),o(i.value).then(()=>({status:t.value,value:i.value}))))}if(s.type==="transform")if(r.common.async===!1){let o=this._def.schema._parseSync({data:r.data,path:r.path,parent:r});if(!j(o))return o;let i=s.transform(o.value,a);if(i instanceof Promise)throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.");return{status:t.value,value:i}}else return this._def.schema._parseAsync({data:r.data,path:r.path,parent:r}).then(o=>j(o)?Promise.resolve(s.transform(o.value,a)).then(i=>({status:t.value,value:i})):o);b.assertNever(s)}static create=(e,t,r)=>new n({schema:e,typeName:"ZodEffects",effect:t,...Z(r)});static createWithPreprocess=(e,t,r)=>new n({schema:t,effect:{type:"preprocess",transform:e},typeName:"ZodEffects",...Z(r)})};var W=class n extends I{_parse(e){return this._getType(e)===p.undefined?A(void 0):this._def.innerType._parse(e)}unwrap(){return this._def.innerType}static create=(e,t)=>new n({innerType:e,typeName:"ZodOptional",...Z(t)})},D=class n extends I{_parse(e){return this._getType(e)===p.null?A(null):this._def.innerType._parse(e)}unwrap(){return this._def.innerType}static create=(e,t)=>new n({innerType:e,typeName:"ZodNullable",...Z(t)})},Ze=class n extends I{_parse(e){let{ctx:t}=this._processInputParams(e),r=t.data;return t.parsedType===p.undefined&&(r=this._def.defaultValue()),this._def.innerType._parse({data:r,path:t.path,parent:t})}removeDefault(){return this._def.innerType}static create=(e,t)=>new n({innerType:e,typeName:"ZodDefault",defaultValue:typeof t.default=="function"?t.default:()=>t.default,...Z(t)})},Ie=class n extends I{_parse(e){let{ctx:t}=this._processInputParams(e),r={...t,common:{...t.common,issues:[]}},s=this._def.innerType._parse({data:r.data,path:r.path,parent:{...r}});return J(s)?s.then(a=>({status:"valid",value:a.status==="valid"?a.value:this._def.catchValue({get error(){return new P(r.common.issues)},input:r.data})})):{status:"valid",value:s.status==="valid"?s.value:this._def.catchValue({get error(){return new P(r.common.issues)},input:r.data})}}removeCatch(){return this._def.innerType}static create=(e,t)=>new n({innerType:e,typeName:"ZodCatch",catchValue:typeof t.catch=="function"?t.catch:()=>t.catch,...Z(t)})},Ge=class n extends I{_parse(e){if(this._getType(e)!==p.nan){let r=this._getOrReturnCtx(e);return l(r,{code:d.invalid_type,expected:p.nan,received:r.parsedType}),g}return{status:"valid",value:e.data}}static create=e=>new n({typeName:"ZodNaN",...Z(e)})},yr=Symbol("zod_brand"),he=class extends I{_parse(e){let{ctx:t}=this._processInputParams(e),r=t.data;return this._def.type._parse({data:r,path:t.path,parent:t})}unwrap(){return this._def.type}},be=class n extends I{_parse(e){let{status:t,ctx:r}=this._processInputParams(e);if(r.common.async)return(async()=>{let a=await this._def.in._parseAsync({data:r.data,path:r.path,parent:r});return a.status==="aborted"?g:a.status==="dirty"?(t.dirty(),Y(a.value)):this._def.out._parseAsync({data:a.value,path:r.path,parent:r})})();{let s=this._def.in._parseSync({data:r.data,path:r.path,parent:r});return s.status==="aborted"?g:s.status==="dirty"?(t.dirty(),{status:"dirty",value:s.value}):this._def.out._parseSync({data:s.value,path:r.path,parent:r})}}static create(e,t){return new n({in:e,out:t,typeName:"ZodPipeline"})}},xe=class n extends I{_parse(e){let t=this._def.innerType._parse(e),r=s=>(j(s)&&(s.value=Object.freeze(s.value)),s);return J(t)?t.then(s=>r(s)):r(t)}static create=(e,t)=>new n({innerType:e,typeName:"ZodReadonly",...Z(t)});unwrap(){return this._def.innerType}};function et(n,e={},t){return n?Q.create().superRefine((r,s)=>{if(!n(r)){let a=typeof e=="function"?e(r):typeof e=="string"?{message:e}:e,o=a.fatal??t??!0,i=typeof a=="string"?{message:a}:a;s.addIssue({code:"custom",...i,fatal:o})}}):Q.create()}var mr={object:U.lazycreate},tt=(h=>(h.ZodString="ZodString",h.ZodNumber="ZodNumber",h.ZodNaN="ZodNaN",h.ZodBigInt="ZodBigInt",h.ZodBoolean="ZodBoolean",h.ZodDate="ZodDate",h.ZodSymbol="ZodSymbol",h.ZodUndefined="ZodUndefined",h.ZodNull="ZodNull",h.ZodAny="ZodAny",h.ZodUnknown="ZodUnknown",h.ZodNever="ZodNever",h.ZodVoid="ZodVoid",h.ZodArray="ZodArray",h.ZodObject="ZodObject",h.ZodUnion="ZodUnion",h.ZodDiscriminatedUnion="ZodDiscriminatedUnion",h.ZodIntersection="ZodIntersection",h.ZodTuple="ZodTuple",h.ZodRecord="ZodRecord",h.ZodMap="ZodMap",h.ZodSet="ZodSet",h.ZodFunction="ZodFunction",h.ZodLazy="ZodLazy",h.ZodLiteral="ZodLiteral",h.ZodEnum="ZodEnum",h.ZodEffects="ZodEffects",h.ZodNativeEnum="ZodNativeEnum",h.ZodOptional="ZodOptional",h.ZodNullable="ZodNullable",h.ZodDefault="ZodDefault",h.ZodCatch="ZodCatch",h.ZodPromise="ZodPromise",h.ZodBranded="ZodBranded",h.ZodPipeline="ZodPipeline",h.ZodReadonly="ZodReadonly",h))(tt||{});var gr=(n,e={message:`Input not instance of ${n.name}`})=>et(t=>t instanceof n,e),nt=q.create,rt=oe.create,fr=Ge.create,Zr=ie.create,st=de.create,Ir=ue.create,hr=ke.create,br=ce.create,xr=le.create,Tr=Q.create,Cr=H.create,vr=L.create,kr=Ae.create,Ar=F.create,Rr=U.create,Pr=U.strictCreate,Sr=pe.create,wr=Re.create,Kr=ye.create,Gr=E.create,Br=Pe.create,Wr=Se.create,Vr=we.create,_r=Ke.create,Nr=me.create,Lr=ge.create,Ur=$.create,Er=fe.create,Xr=ee.create,Dr=X.create,Or=W.create,Yr=D.create,Hr=X.createWithPreprocess,Fr=be.create,Mr=()=>nt().optional(),jr=()=>rt().optional(),Jr=()=>st().optional(),zr={string:n=>q.create({...n,coerce:!0}),number:n=>oe.create({...n,coerce:!0}),boolean:n=>de.create({...n,coerce:!0}),bigint:n=>ie.create({...n,coerce:!0}),date:n=>ue.create({...n,coerce:!0})};var qr=g;var K="treeview",O="TreeView Plug",ot="enableTreeView",Qr=["rhs","lhs","bhs","modal"],$r=C.object({type:C.literal("regex"),rule:C.string(),negate:C.boolean().optional().default(!1)}),es=C.object({type:C.literal("tags"),tags:C.array(C.string()),negate:C.boolean().optional().default(!1),attribute:C.enum(["tags","itags","tag"]).optional().default("tags")}),ts=C.object({type:C.literal("space-function"),name:C.string(),negate:C.boolean().optional().default(!1)}),at=C.object({position:C.enum(Qr).optional().default("lhs"),size:C.number().gt(0).optional().default(1),dragAndDrop:C.object({enabled:C.boolean().optional().default(!0),confirmOnRename:C.boolean().optional().default(!0)}).optional().default({}),pageExcludeRegex:C.string().optional().default(""),exclusions:C.array(C.discriminatedUnion("type",[$r,es,ts])).optional()});async function ns(n){if(Be)return;Be=!0;let e=`${typeof n}: ${String(n)}`;if(n instanceof P){let{formErrors:t,fieldErrors:r}=n.flatten(),s=Object.keys(r).map(a=>`\`${a}\` - ${r[a].join(", ")}`);e=[...t,...s].join("; ")}await G.flashNotification(`There was an error with your ${K} configuration. Check your SETTINGS file: ${e}`,"error")}var Be=!1;async function it(){let n=await B.getSpaceConfig("treeview",{});try{return at.parse(n||{})}catch(e){return Be||(ns(e),Be=!0),at.parse({})}}async function Xe(){return!!await se.get(ot)}async function De(n){return await se.set(ot,n)}async function dt(){return await G.getUiOption("customStyles")}var ut=async(n,{name:e,negate:t})=>{try{let r=await Promise.all(n.map(s=>B.invokeSpaceFunction(e,s)));return n.filter((s,a)=>t?r[a]:!r[a])}catch(r){return console.error(`${O}: filtering pages by function "${e}" failed`,r),n}};var Oe=(n,{rule:e,negate:t})=>{try{let r=new RegExp(e);return n.filter(({name:s})=>r.test(s)===t)}catch(r){return console.error(`${O}: filtering pages by regex "${e}" failed`,r),n}};var ct=(n,{attribute:e,negate:t,tags:r})=>n.filter(s=>{let a=s[e],o=a!==void 0&&(Array.isArray(a)?a.some(i=>r.includes(i)):r.includes(a));return t?o:!o});async function lt(n){let e=await G.getCurrentPage(),t=await B.invokeFunction("index.queryLuaObjects","page",{}),r={nodes:[]};if(n.pageExcludeRegex){let s=`${O}:
2 | \`pageExcludeRegex\` setting is deprecated. Please use \`exclusions\`:
3 |
4 | \`\`\`yaml
5 | treeview:
6 | exclusions:
7 | - type: regex
8 | rule: "${n.pageExcludeRegex}"
9 | \`\`\`
10 | `;console.warn(s),t=Oe(t,{rule:n.pageExcludeRegex,negate:!1})}if(n.exclusions)for(let s of n.exclusions)switch(s.type){case"regex":{t=Oe(t,s);break}case"tags":{t=ct(t,s);break}case"space-function":{t=await ut(t,s);break}}return t.sort((s,a)=>s.name.localeCompare(a.name)),t.forEach(s=>{s.name.split("/").reduce((a,o,i,y)=>{let c=y.length-1===i,f=a.nodes.find(T=>T.data.title===o);if(f)return c&&!("created"in f.data)&&(f.data={...s,title:o,isCurrentPage:e===s.name,nodeType:"page"}),f;if(c)f={data:{...s,title:o,isCurrentPage:e===s.name,nodeType:"page"},nodes:[]};else{let T=y.slice(0,i+1).join("/");f={data:{title:o,isCurrentPage:e===T,name:T,nodeType:"folder"},nodes:[]}}return a.nodes.push(f),f},r)}),{nodes:r.nodes,currentPage:e}}var te;async function pt(){await Xe()?await We():await Ve()}async function We(){te&&(await G.hidePanel(te),te=void 0,await De(!1))}async function yt(){try{if(await B.getEnv()==="server")return;if(await Xe())return await Ve()}catch(n){console.error(`${O}: showTreeIfEnabled failed`,n)}}async function Ve(){let n=await it();te&&n.position!==te&&await We();let[e,t,r,s,a,o,i,y,c]=await Promise.all([S.readAsset(K,"assets/sortable-tree/sortable-tree.css"),S.readAsset(K,"assets/sortable-tree/sortable-tree.js"),S.readAsset(K,"assets/treeview.css"),S.readAsset(K,"assets/treeview.js"),S.readAsset(K,"assets/icons/folder-minus.svg"),S.readAsset(K,"assets/icons/folder-plus.svg"),S.readAsset(K,"assets/icons/navigation-2.svg"),S.readAsset(K,"assets/icons/refresh-cw.svg"),S.readAsset(K,"assets/icons/x-circle.svg")]),{currentPage:f,nodes:T}=await lt(n),x=await dt(),v={nodes:T,currentPage:f,treeElementId:"treeview-tree",dragAndDrop:{...n.dragAndDrop,enabled:n.dragAndDrop.enabled}};await G.showPanel(n.position,n.size,`
11 |
12 |
17 | `,`
33 | ${t}
34 | ${s}
35 | initializeTreeViewPanel(${JSON.stringify(v)});
36 | `),await De(!0),te=n.position}var mt={hide:We,show:Ve,showIfEnabled:yt,toggle:pt},gt={name:"treeview",version:.15,assets:{"assets/treeview.js":{data:"data:application/javascript;base64,LyoqCiAqIEB0eXBlZGVmIHtpbXBvcnQoIi4uL2FwaS50cyIpLlRyZWVOb2RlfSBUcmVlTm9kZQogKi8KCi8qKgogKiBAdHlwZWRlZiBTb3J0YWJsZVRyZWVOb2RlCiAqIEB0eXBlIHtPYmplY3R9CiAqIEBwcm9wZXJ0eSB7VHJlZU5vZGVbImRhdGEiXX0gZGF0YQogKi8KCi8qKgogKgogKiBAdHlwZWRlZiBUcmVlVmlld0NvbmZpZwogKiBAdHlwZSB7T2JqZWN0fQogKiBAcHJvcGVydHkge3N0cmluZ30gY3VycmVudFBhZ2UgLSB0aGUgY3VycmVudCBwYWdlIHNob3duIGluIFNpbHZlckJ1bGxldC4KICogQHByb3BlcnR5IHtUcmVlTm9kZVtdfSBub2RlcyAtIGEgdHJlZSBvZiBhbGwgcGFnZXMgaW4gdGhlIGN1cnJlbnQgc3BhY2UuCiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkcmFnQW5kRHJvcCAtIGRyYWcgYW5kIGRyb3AgcmVsYXRlZCBjb25maWcKICogQHByb3BlcnR5IHtib29sZWFufSBkcmFnQW5kRHJvcC5lbmFibGVkIC0gdHJ1ZSBpZiBkcmFnIGFuZCBkcm9wIGlzIGVuYWJsZWQKICogQHByb3BlcnR5IHtib29sZWFufSBkcmFnQW5kRHJvcC5jb25maXJtT25SZW5hbWUgLSB0cnVlIGlmIGEgY29uZmlybWF0aW9uIHNob3VsZCBiZSBzaG93bgogKiAgd2hlbiBhIG5vZGUgaXMgZHJhZ2dlZCBhbmQgZHJvcHBlZC4KKi8KCgpjb25zdCBUUkVFX1NUQVRFX0lEID0gInRyZWV2aWV3IjsKCi8qKgogKiBJbml0aWFsaXplcyB0aGUgVHJlZVZpZXcncyBgU29ydGFibGVUcmVlYCBpbnN0YW5jZS4KICogQHBhcmFtIHtUcmVlVmlld0NvbmZpZ30gY29uZmlnCiAqIEByZXR1cm5zIHtTb3J0YWJsZVRyZWV9CiAqLwpmdW5jdGlvbiBjcmVhdGVUcmVlVmlldyhjb25maWcpIHsKICByZXR1cm4gbmV3IFNvcnRhYmxlVHJlZSh7CiAgICBub2RlczogY29uZmlnLm5vZGVzLAogICAgZGlzYWJsZVNvcnRpbmc6ICFjb25maWcuZHJhZ0FuZERyb3AuZW5hYmxlZCwKICAgIGVsZW1lbnQ6IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGNvbmZpZy50cmVlRWxlbWVudElkKSwKICAgIHN0YXRlSWQ6IFRSRUVfU1RBVEVfSUQsCiAgICBpbml0Q29sbGFwc2VMZXZlbDogMCwKICAgIGxvY2tSb290TGV2ZWw6IGZhbHNlLAoKICAgIC8qKgogICAgICogQHBhcmFtIHtTb3J0YWJsZVRyZWVOb2RlfSBtb3ZlZE5vZGUKICAgICAqIEBwYXJhbSB7U29ydGFibGVUcmVlTm9kZX0gdGFyZ2V0UGFyZW50Tm9kZQogICAgICovCiAgICBjb25maXJtOiBhc3luYyAobW92ZWROb2RlLCB0YXJnZXRQYXJlbnROb2RlKSA9PiB7CiAgICAgIGNvbnN0IG9sZFByZWZpeCA9IG1vdmVkTm9kZS5kYXRhLm5hbWU7CiAgICAgIGNvbnN0IG5ld1ByZWZpeCA9IHRhcmdldFBhcmVudE5vZGUgPyBgJHt0YXJnZXRQYXJlbnROb2RlLmRhdGEubmFtZX0vJHttb3ZlZE5vZGUuZGF0YS50aXRsZX1gIDogbW92ZWROb2RlLmRhdGEudGl0bGU7CgogICAgICBpZiAob2xkUHJlZml4ID09PSBuZXdQcmVmaXgpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBhd2FpdCBzeXNjYWxsKCJzeXN0ZW0uaW52b2tlRnVuY3Rpb24iLCAiaW5kZXgucmVuYW1lUHJlZml4Q29tbWFuZCIsIHsKICAgICAgICBvbGRQcmVmaXgsCiAgICAgICAgbmV3UHJlZml4LAogICAgICAgIGRpc2FibGVDb25maXJtYXRpb246ICFjb25maWcuZHJhZ0FuZERyb3AuY29uZmlybU9uUmVuYW1lLAogICAgICB9KTsKCiAgICAgIGlmIChzdWNjZXNzICYmIGNvbmZpZy5jdXJyZW50UGFnZS5pbmRleE9mKG9sZFByZWZpeCkgPT09IDApIHsKICAgICAgICAvLyBJZiB0aGlzIHJlbmFtZWQgdGhlIGN1cnJlbnQgcGFnZSwgbmF2aWdhdGUgdG8gaXQgYXQgaXQncyB1cGRhdGVkIG5hbWUuCiAgICAgICAgYXdhaXQgc3lzY2FsbCgiZWRpdG9yLm5hdmlnYXRlIiwgY29uZmlnLmN1cnJlbnRQYWdlLnJlcGxhY2Uob2xkUHJlZml4LCBuZXdQcmVmaXgpLCBmYWxzZSwgZmFsc2UpOwogICAgICB9CgogICAgICByZXR1cm4gc3VjY2VzczsKICAgIH0sCgogICAgb25DaGFuZ2U6IGFzeW5jICgpID0+IHsKICAgICAgYXdhaXQgc3lzY2FsbCgic3lzdGVtLmludm9rZUZ1bmN0aW9uIiwgInRyZWV2aWV3LnNob3ciKTsKICAgIH0sCgogICAgLyoqCiAgICAgKiBAcGFyYW0ge1NvcnRhYmxlVHJlZU5vZGV9IG5vZGUKICAgICAqLwogICAgb25DbGljazogYXN5bmMgKF9ldmVudCwgbm9kZSkgPT4gewogICAgICBhd2FpdCBzeXNjYWxsKCJlZGl0b3IubmF2aWdhdGUiLCBub2RlLmRhdGEubmFtZSwgZmFsc2UsIGZhbHNlKTsKICAgIH0sCgogICAgLyoqCiAgICAgKiBAcGFyYW0ge1NvcnRhYmxlVHJlZU5vZGVbImRhdGEiXX0gZGF0YQogICAgICogQHJldHVybnMge3N0cmluZ30KICAgICAqLwogICAgcmVuZGVyTGFiZWw6IChkYXRhKSA9PiBgCiAgICAgIDxzcGFuCiAgICAgICAgZGF0YS1jdXJyZW50LXBhZ2U9IiR7SlNPTi5zdHJpbmdpZnkoZGF0YS5pc0N1cnJlbnRQYWdlIHx8IGZhbHNlKX0iCiAgICAgICAgZGF0YS1ub2RlLXR5cGU9IiR7ZGF0YS5ub2RlVHlwZX0iCiAgICAgICAgZGF0YS1wZXJtaXNzaW9uPSIke2RhdGEucGVybX0iCiAgICAgICAgdGl0bGU9IiR7ZGF0YS5uYW1lfSIgPgogICAgICAgICR7ZGF0YS50aXRsZX0KICAgICAgPC9zcGFuPmAKICAgICwKICB9KTsKfQoKLyoqCiAqIEluaXRpYWxpemVzIHRoZSB0cmVlIHZpZXcgYW5kIGl0J3MgYWN0aW9uIGJhci4KICogQHBhcmFtIHtUcmVlVmlld0NvbmZpZ30gY29uZmlnCiAqLwovLyBkZW5vLWxpbnQtaWdub3JlIG5vLXVudXNlZC12YXJzCmZ1bmN0aW9uIGluaXRpYWxpemVUcmVlVmlld1BhbmVsKGNvbmZpZykgewogIGNvbnN0IHRyZWUgPSBjcmVhdGVUcmVlVmlldyhjb25maWcpOwogIGNvbnN0IGhhbmRsZUFjdGlvbiA9IChhY3Rpb24pID0+IHsKICAgIHN3aXRjaCAoYWN0aW9uKSB7CiAgICAgIGNhc2UgImNvbGxhcHNlLWFsbCI6IHsKICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCJzb3J0YWJsZS10cmVlLW5vZGVbb3Blbj0ndHJ1ZSddIikuZm9yRWFjaCgobm9kZSkgPT4gbm9kZS5jb2xsYXBzZSh0cnVlKSk7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgY2FzZSAiZXhwYW5kLWFsbCI6IHsKICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCJzb3J0YWJsZS10cmVlLW5vZGU6bm90KFtvcGVuPSd0cnVlJ10pIikuZm9yRWFjaCgobm9kZSkgPT4gbm9kZS5jb2xsYXBzZShmYWxzZSkpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGNhc2UgImNsb3NlLXBhbmVsIjogewogICAgICAgIHN5c2NhbGwoInN5c3RlbS5pbnZva2VGdW5jdGlvbiIsICJ0cmVldmlldy5oaWRlIik7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgY2FzZSAicmVmcmVzaCI6IHsKICAgICAgICBzeXNjYWxsKCJzeXN0ZW0uaW52b2tlRnVuY3Rpb24iLCAidHJlZXZpZXcuc2hvdyIpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGNhc2UgInJldmVhbC1jdXJyZW50LXBhZ2UiOiB7CiAgICAgICAgY29uc3QgY3VycmVudE5vZGUgPSB0cmVlLmZpbmROb2RlKCJpc0N1cnJlbnRQYWdlIiwgdHJ1ZSk7CiAgICAgICAgaWYgKGN1cnJlbnROb2RlKSB7CiAgICAgICAgICBjdXJyZW50Tm9kZS5yZXZlYWwoKTsKICAgICAgICAgIGN1cnJlbnROb2RlLnNjcm9sbEludG9WaWV3KHsKICAgICAgICAgICAgYmVoYXZpb3I6ICJhdXRvIiwKICAgICAgICAgICAgYmxvY2s6ICJuZWFyZXN0IiwKICAgICAgICAgICAgaW5saW5lOiAibmVhcmVzdCIsCiAgICAgICAgICB9KTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBoYW5kbGVBY3Rpb24oInJldmVhbC1jdXJyZW50LXBhZ2UiKTsKCiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiW2RhdGEtdHJlZXZpZXctYWN0aW9uXSIpLmZvckVhY2goKGVsKSA9PiB7CiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIChlKSA9PiB7CiAgICAgIGlmIChoYW5kbGVBY3Rpb24oZWwuZGF0YXNldFsidHJlZXZpZXdBY3Rpb24iXSkpIHsKICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpOwogICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgfQogICAgfSk7CiAgfSkKfQo=",mtime:1743017042939},"assets/icons/x-circle.svg":{data:"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXIteC1jaXJjbGUiPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIj48L2NpcmNsZT48bGluZSB4MT0iMTUiIHkxPSI5IiB4Mj0iOSIgeTI9IjE1Ij48L2xpbmU+PGxpbmUgeDE9IjkiIHkxPSI5IiB4Mj0iMTUiIHkyPSIxNSI+PC9saW5lPjwvc3ZnPg==",mtime:1743017042939},"assets/icons/refresh-cw.svg":{data:"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItcmVmcmVzaC1jdyI+PHBvbHlsaW5lIHBvaW50cz0iMjMgNCAyMyAxMCAxNyAxMCI+PC9wb2x5bGluZT48cG9seWxpbmUgcG9pbnRzPSIxIDIwIDEgMTQgNyAxNCI+PC9wb2x5bGluZT48cGF0aCBkPSJNMy41MSA5YTkgOSAwIDAgMSAxNC44NS0zLjM2TDIzIDEwTTEgMTRsNC42NCA0LjM2QTkgOSAwIDAgMCAyMC40OSAxNSI+PC9wYXRoPjwvc3ZnPg==",mtime:1743017042940},"assets/icons/folder-plus.svg":{data:"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItZm9sZGVyLXBsdXMiPjxwYXRoIGQ9Ik0yMiAxOWEyIDIgMCAwIDEtMiAySDRhMiAyIDAgMCAxLTItMlY1YTIgMiAwIDAgMSAyLTJoNWwyIDNoOWEyIDIgMCAwIDEgMiAyeiI+PC9wYXRoPjxsaW5lIHgxPSIxMiIgeTE9IjExIiB4Mj0iMTIiIHkyPSIxNyI+PC9saW5lPjxsaW5lIHgxPSI5IiB5MT0iMTQiIHgyPSIxNSIgeTI9IjE0Ij48L2xpbmU+PC9zdmc+",mtime:1743017042940},"assets/icons/folder-minus.svg":{data:"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItZm9sZGVyLW1pbnVzIj48cGF0aCBkPSJNMjIgMTlhMiAyIDAgMCAxLTIgMkg0YTIgMiAwIDAgMS0yLTJWNWEyIDIgMCAwIDEgMi0yaDVsMiAzaDlhMiAyIDAgMCAxIDIgMnoiPjwvcGF0aD48bGluZSB4MT0iOSIgeTE9IjE0IiB4Mj0iMTUiIHkyPSIxNCI+PC9saW5lPjwvc3ZnPg==",mtime:1743017042943},"assets/icons/navigation-2.svg":{data:"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIgogICAgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIgogICAgY2xhc3M9ImZlYXRoZXIgZmVhdGhlci1uYXZpZ2F0aW9uLTIiPgogICAgPHBvbHlnb24gcG9pbnRzPSIxMiAyIDE5IDIxIDEyIDE3IDUgMjEgMTIgMiI+PC9wb2x5Z29uPgo8L3N2Zz4=",mtime:1743017042944},"assets/sortable-tree/sortable-tree.css":{data:"data:text/css;base64,LyohIFNvcnRhYmxlIFRyZWUgMC43LjIsIChjKSAyMDIzIE1hcmMgQW50b24gRGFobWVuLCBNSVQgbGljZW5zZSAqLwo6cm9vdCB7CiAgICAtLXN0LWxhYmVsLWhlaWdodDogMi41cmVtOwogICAgLS1zdC1zdWJub2Rlcy1wYWRkaW5nLWxlZnQ6IDEuNXJlbTsKICAgIC0tc3QtY29sbGFwc2UtaWNvbi1oZWlnaHQ6IHZhcigtLXN0LWxhYmVsLWhlaWdodCk7CiAgICAtLXN0LWNvbGxhcHNlLWljb24td2lkdGg6IDEuMjVyZW07CiAgICAtLXN0LWNvbGxhcHNlLWljb24tc2l6ZTogMC43NXJlbTsKICB9CiAgc29ydGFibGUtdHJlZS1ub2RlIHsKICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICAgIHotaW5kZXg6IDE7CiAgICBkaXNwbGF5OiBmbGV4OwogICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICB9CiAgc29ydGFibGUtdHJlZS1ub2RlICogewogICAgdXNlci1zZWxlY3Q6IG5vbmU7CiAgfQogIHNvcnRhYmxlLXRyZWUtbm9kZSA+IDpmaXJzdC1jaGlsZCB7CiAgICBkaXNwbGF5OiBmbGV4OwogICAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICAgIGhlaWdodDogdmFyKC0tc3QtbGFiZWwtaGVpZ2h0KTsKICB9CiAgc29ydGFibGUtdHJlZS1ub2RlID4gOm50aC1jaGlsZCgyKSB7CiAgICBkaXNwbGF5OiBub25lOwogICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICAgIHBhZGRpbmctbGVmdDogdmFyKC0tc3Qtc3Vibm9kZXMtcGFkZGluZy1sZWZ0KTsKICB9CiAgc29ydGFibGUtdHJlZS1ub2RlW29wZW5dID4gZGl2Om50aC1jaGlsZCgyKSB7CiAgICBkaXNwbGF5OiBmbGV4OwogIH0KICBzb3J0YWJsZS10cmVlLW5vZGUgPiA6bnRoLWNoaWxkKDMpIHsKICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICAgIGRpc3BsYXk6IGZsZXg7CiAgICBhbGlnbi1pdGVtczogY2VudGVyOwogICAgdG9wOiAwOwogICAgbGVmdDogY2FsYyh2YXIoLS1zdC1jb2xsYXBzZS1pY29uLXdpZHRoKSAqIC0xKTsKICAgIGhlaWdodDogdmFyKC0tc3QtY29sbGFwc2UtaWNvbi1oZWlnaHQpOwogICAgZm9udC1zaXplOiB2YXIoLS1zdC1jb2xsYXBzZS1pY29uLXNpemUpOwogICAgY3Vyc29yOiBwb2ludGVyOwogIH0KICBzb3J0YWJsZS10cmVlLW5vZGUgPiA6bnRoLWNoaWxkKDIpOmVtcHR5ICsgc3BhbiB7CiAgICBkaXNwbGF5OiBub25lOwogIH0KICAKICA=",mtime:1743017042944},"assets/sortable-tree/sortable-tree.js":{data:"data:application/javascript;base64,LyohIFNvcnRhYmxlIFRyZWUgMC43LjIsIChjKSAyMDI0IE1hcmMgQW50b24gRGFobWVuLCBNSVQgbGljZW5zZSAqLwovKiBNb2RpZmllZCBieSBNck11Z2FtZSAoaHR0cHM6Ly9naXRodWIuY29tL21hcmNhbnRvbmRhaG1lbi9zb3J0YWJsZS10cmVlL3B1bGwvMTEpICovCiFmdW5jdGlvbiAoZSwgdCkgeyAib2JqZWN0IiA9PSB0eXBlb2YgZXhwb3J0cyAmJiAib2JqZWN0IiA9PSB0eXBlb2YgbW9kdWxlID8gbW9kdWxlLmV4cG9ydHMgPSB0KCkgOiAiZnVuY3Rpb24iID09IHR5cGVvZiBkZWZpbmUgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbXSwgdCkgOiAib2JqZWN0IiA9PSB0eXBlb2YgZXhwb3J0cyA/IGV4cG9ydHMuU29ydGFibGVUcmVlID0gdCgpIDogZS5Tb3J0YWJsZVRyZWUgPSB0KCkgfShzZWxmLCAoKCkgPT4gKCgpID0+IHsgInVzZSBzdHJpY3QiOyB2YXIgZSA9IHsgZDogKHQsIG4pID0+IHsgZm9yICh2YXIgbyBpbiBuKSBlLm8obiwgbykgJiYgIWUubyh0LCBvKSAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodCwgbywgeyBlbnVtZXJhYmxlOiAhMCwgZ2V0OiBuW29dIH0pIH0sIG86IChlLCB0KSA9PiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSwgdCkgfSwgdCA9IHt9OyBlLmQodCwgeyBkZWZhdWx0OiAoKSA9PiBMIH0pOyB2YXIgbiA9IGZ1bmN0aW9uIChlLCB0LCBuLCBvKSB7IHJldHVybiBuZXcgKG4gfHwgKG4gPSBQcm9taXNlKSkoKGZ1bmN0aW9uIChyLCBzKSB7IGZ1bmN0aW9uIGkoZSkgeyB0cnkgeyBsKG8ubmV4dChlKSkgfSBjYXRjaCAoZSkgeyBzKGUpIH0gfSBmdW5jdGlvbiBhKGUpIHsgdHJ5IHsgbChvLnRocm93KGUpKSB9IGNhdGNoIChlKSB7IHMoZSkgfSB9IGZ1bmN0aW9uIGwoZSkgeyB2YXIgdDsgZS5kb25lID8gcihlLnZhbHVlKSA6ICh0ID0gZS52YWx1ZSwgdCBpbnN0YW5jZW9mIG4gPyB0IDogbmV3IG4oKGZ1bmN0aW9uIChlKSB7IGUodCkgfSkpKS50aGVuKGksIGEpIH0gbCgobyA9IG8uYXBwbHkoZSwgdCB8fCBbXSkpLm5leHQoKSkgfSkpIH07IGNvbnN0IG8gPSBlID0+IGA8c3Bhbj4ke2UudGl0bGV9PC9zcGFuPmAsIHIgPSB7IGNvbGxhcHNlZDogJ1xuXHRcdDxzdmdcblx0XHR4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIFxuXHRcdHdpZHRoPSIxZW0iIFxuXHRcdGhlaWdodD0iMWVtIiBcblx0XHRmaWxsPSJjdXJyZW50Q29sb3IiIFxuXHRcdGNsYXNzPSJiaSBiaS1jYXJldC1yaWdodC1maWxsIiBcblx0XHR2aWV3Qm94PSIwIDAgMTYgMTYiPlxuXHRcdFx0PHBhdGggZD0ibTEyLjE0IDguNzUzLTUuNDgyIDQuNzk2Yy0uNjQ2LjU2Ni0xLjY1OC4xMDYtMS42NTgtLjc1M1YzLjIwNGExIDEgMCAwIDEgMS42NTktLjc1M2w1LjQ4IDQuNzk2YTEgMSAwIDAgMSAwIDEuNTA2eiIvPlxuXHRcdDwvc3ZnPicsIG9wZW46ICdcblx0XHQ8c3ZnIFxuXHRcdHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgXG5cdFx0d2lkdGg9IjFlbSIgXG5cdFx0aGVpZ2h0PSIxZW0iIFxuXHRcdGZpbGw9ImN1cnJlbnRDb2xvciIgXG5cdFx0Y2xhc3M9ImJpIGJpLWNhcmV0LWRvd24tZmlsbCIgXG5cdFx0dmlld0JveD0iMCAwIDE2IDE2Ij5cblx0XHRcdDxwYXRoIGQ9Ik03LjI0NyAxMS4xNCAyLjQ1MSA1LjY1OEMxLjg4NSA1LjAxMyAyLjM0NSA0IDMuMjA0IDRoOS41OTJhMSAxIDAgMCAxIC43NTMgMS42NTlsLTQuNzk2IDUuNDhhMSAxIDAgMCAxLTEuNTA2IDB6Ii8+XG5cdFx0PC9zdmc+XG5cdCcgfSwgcyA9IHsgdHJlZTogInRyZWUiLCBub2RlOiAidHJlZV9fbm9kZSIsIG5vZGVIb3ZlcjogInRyZWVfX25vZGUtLWhvdmVyIiwgbm9kZURyYWdnaW5nOiAidHJlZV9fbm9kZS0tZHJhZ2dpbmciLCBub2RlRHJvcEJlZm9yZTogInRyZWVfX25vZGUtLWRyb3AtYmVmb3JlIiwgbm9kZURyb3BJbnNpZGU6ICJ0cmVlX19ub2RlLS1kcm9wLWluc2lkZSIsIG5vZGVEcm9wQWZ0ZXI6ICJ0cmVlX19ub2RlLS1kcm9wLWFmdGVyIiwgbGFiZWw6ICJ0cmVlX19sYWJlbCIsIHN1Ym5vZGVzOiAidHJlZV9fc3Vibm9kZXMiLCBjb2xsYXBzZTogInRyZWVfX2NvbGxhcHNlIiB9LCBpID0gKHsgbm9kZXM6IGUsIG1vdmVkTm9kZTogdCwgc3JjUGFyZW50Tm9kZTogbywgdGFyZ2V0UGFyZW50Tm9kZTogciB9KSA9PiBuKHZvaWQgMCwgdm9pZCAwLCB2b2lkIDAsIChmdW5jdGlvbiogKCkgeyB9KSksIGEgPSAoZSwgdCkgPT4gbih2b2lkIDAsIHZvaWQgMCwgdm9pZCAwLCAoZnVuY3Rpb24qICgpIHsgfSkpLCBsID0gKGUsIHQpID0+IG4odm9pZCAwLCB2b2lkIDAsIHZvaWQgMCwgKGZ1bmN0aW9uKiAoKSB7IHJldHVybiAhMCB9KSk7IGNvbnN0IGQgPSAoZSwgdCA9IFtdLCBuID0gbnVsbCkgPT4geyBjb25zdCBvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChlKTsgcmV0dXJuIHQuZm9yRWFjaCgoZSA9PiB7IG8uY2xhc3NMaXN0LmFkZChlKSB9KSksIG4gJiYgbi5hcHBlbmRDaGlsZChvKSwgbyB9LCBjID0gKCkgPT4gKChlID0gMjEpID0+IGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoZSkpLnJlZHVjZSgoKGUsIHQpID0+IGUgKyAoKHQgJj0gNjMpIDwgMzYgPyB0LnRvU3RyaW5nKDM2KSA6IHQgPCA2MiA/ICh0IC0gMjYpLnRvU3RyaW5nKDM2KS50b1VwcGVyQ2FzZSgpIDogdCA+IDYyID8gIi0iIDogIl8iKSksICIiKSkoKTsgY2xhc3MgdSBleHRlbmRzIEhUTUxFbGVtZW50IHsgc3RhdGljIGNyZWF0ZSh7IGRhdGE6IGUsIHJlbmRlckxhYmVsOiB0LCBpY29uczogbiwgc3R5bGVzOiBvLCBwYXJlbnQ6IHIsIG9uQ2xpY2s6IHMsIGRyYWdnYWJsZTogaSB9KSB7IGNvbnN0IGEgPSBkKHUuVEFHX05BTUUsIFtvLm5vZGVdLCByKSwgbCA9IGQoImRpdiIsIFtvLmxhYmVsXSwgYSksIGMgPSBkKCJkaXYiLCBbby5zdWJub2Rlc10sIGEpLCBoID0gZCgic3BhbiIsIFtvLmNvbGxhcHNlXSwgYSk7IHJldHVybiBsLmlubmVySFRNTCA9IHQoZSksIGguaW5uZXJIVE1MID0gbi5jb2xsYXBzZWQsIGguYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCBhLnRvZ2dsZS5iaW5kKGEpKSwgbC5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIChlID0+IHsgcyhlLCBhKSB9KSksIGkgJiYgYS5zZXRBdHRyaWJ1dGUoImRyYWdnYWJsZSIsICJ0cnVlIiksIGEuX2RhdGEgPSBlLCBhLl9pY29ucyA9IG4sIGEuX2xhYmVsID0gbCwgYS5fbm9kZXMgPSBjLCBhLl9jb2xsYXBzZUJ1dHRvbiA9IGgsIGEgfSBnZXQgZGF0YSgpIHsgcmV0dXJuIHRoaXMuX2RhdGEgfSBnZXQgbGFiZWwoKSB7IHJldHVybiB0aGlzLl9sYWJlbCB9IGdldCBzdWJub2RlcygpIHsgcmV0dXJuIHRoaXMuX25vZGVzIH0gZ2V0IHN1Ym5vZGVzRGF0YSgpIHsgY29uc3QgZSA9IFtdOyByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLl9ub2Rlcy5jaGlsZHJlbikuZm9yRWFjaCgodCA9PiB7IGUucHVzaCh0LmRhdGEpIH0pKSwgZSB9IGdldCBpZCgpIHsgcmV0dXJuIHRoaXMuX2lkIH0gY29uc3RydWN0b3IoKSB7IHN1cGVyKCksIHRoaXMuX2lkID0gYygpIH0gY29sbGFwc2UoZSkgeyBlID8gKHRoaXMucmVtb3ZlQXR0cmlidXRlKCJvcGVuIiksIHRoaXMuX2NvbGxhcHNlQnV0dG9uLmlubmVySFRNTCA9IHRoaXMuX2ljb25zLmNvbGxhcHNlZCkgOiAodGhpcy5zZXRBdHRyaWJ1dGUoIm9wZW4iLCAidHJ1ZSIpLCB0aGlzLl9jb2xsYXBzZUJ1dHRvbi5pbm5lckhUTUwgPSB0aGlzLl9pY29ucy5vcGVuKSB9IHRvZ2dsZSgpIHsgdGhpcy5jb2xsYXBzZSh0aGlzLmhhc0F0dHJpYnV0ZSgib3BlbiIpKSB9IHJldmVhbCgpIHsgKChlLCB0KSA9PiB7IGNvbnN0IG4gPSBbXTsgbGV0IG8gPSB0LmNsb3Nlc3QoZSk7IGZvciAoOyBudWxsICE9PSBvOyluLnB1c2gobyksIG8gPSBvLnBhcmVudE5vZGUuY2xvc2VzdChlKTsgcmV0dXJuIG4gfSkodS5UQUdfTkFNRSwgdGhpcykuZm9yRWFjaCgoZSA9PiB7IGUuY29sbGFwc2UoITEpIH0pKSB9IH0gdS5UQUdfTkFNRSA9ICJzb3J0YWJsZS10cmVlLW5vZGUiOyB2YXIgaCA9IGZ1bmN0aW9uIChlLCB0LCBuLCBvKSB7IHJldHVybiBuZXcgKG4gfHwgKG4gPSBQcm9taXNlKSkoKGZ1bmN0aW9uIChyLCBzKSB7IGZ1bmN0aW9uIGkoZSkgeyB0cnkgeyBsKG8ubmV4dChlKSkgfSBjYXRjaCAoZSkgeyBzKGUpIH0gfSBmdW5jdGlvbiBhKGUpIHsgdHJ5IHsgbChvLnRocm93KGUpKSB9IGNhdGNoIChlKSB7IHMoZSkgfSB9IGZ1bmN0aW9uIGwoZSkgeyB2YXIgdDsgZS5kb25lID8gcihlLnZhbHVlKSA6ICh0ID0gZS52YWx1ZSwgdCBpbnN0YW5jZW9mIG4gPyB0IDogbmV3IG4oKGZ1bmN0aW9uIChlKSB7IGUodCkgfSkpKS50aGVuKGksIGEpIH0gbCgobyA9IG8uYXBwbHkoZSwgdCB8fCBbXSkpLm5leHQoKSkgfSkpIH07IGNvbnN0IHAgPSAoeyBub2RlOiBlLCBldmVudE5hbWU6IHQsIGhhbmRsZXI6IG4sIHRyZWU6IG8gfSkgPT4geyBlLmFkZEV2ZW50TGlzdGVuZXIodCwgKGUgPT4geyBuKGUsIG8pIH0pLCAhMSkgfTsgdmFyIGY7ICFmdW5jdGlvbiAoZSkgeyBlLkJFRk9SRSA9ICJCRUZPUkUiLCBlLklOU0lERSA9ICJJTlNJREUiLCBlLkFGVEVSID0gIkFGVEVSIiB9KGYgfHwgKGYgPSB7fSkpOyBjb25zdCBnID0gZSA9PiB7IGNvbnN0IHQgPSBlLmNsaWVudFksIG4gPSB2KGUpLmxhYmVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBvID0gTWF0aC5yb3VuZChuLmhlaWdodCAvIDQpOyByZXR1cm4gbi50b3AgKyBvID4gdCA/IGYuQkVGT1JFIDogbi5ib3R0b20gLSBvIDwgdCA/IGYuQUZURVIgOiBmLklOU0lERSB9LCB2ID0gZSA9PiBlLnRhcmdldC5jbG9zZXN0KHUuVEFHX05BTUUpLCBiID0gZSA9PiB7IGNvbnN0IHQgPSBudWxsID09IGUgPyB2b2lkIDAgOiBlLnBhcmVudEVsZW1lbnQucGFyZW50RWxlbWVudDsgcmV0dXJuIChudWxsID09IHQgPyB2b2lkIDAgOiB0LnRhZ05hbWUudG9Mb3dlckNhc2UoKSkgIT09IHUuVEFHX05BTUUgPyBudWxsIDogdCB9LCBtID0gKGUsIHQpID0+IHsgdihlKS5jbGFzc0xpc3QucmVtb3ZlKHQuc3R5bGVzLm5vZGVEcm9wQWZ0ZXIsIHQuc3R5bGVzLm5vZGVEcm9wQmVmb3JlLCB0LnN0eWxlcy5ub2RlRHJvcEluc2lkZSkgfSwgRSA9IChlLCB0KSA9PiB7IGUuc3RvcFByb3BhZ2F0aW9uKCk7IGNvbnN0IG4gPSBlLnRhcmdldDsgbi50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09IHUuVEFHX05BTUUgJiYgKGUuZGF0YVRyYW5zZmVyLnNldERhdGEoInRleHQiLCBuLmlkKSwgZS5kYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9ICJtb3ZlIiwgbi5jbGFzc0xpc3QuYWRkKHQuc3R5bGVzLm5vZGVEcmFnZ2luZykpIH0sIF8gPSAoZSwgdCkgPT4gaCh2b2lkIDAsIHZvaWQgMCwgdm9pZCAwLCAoZnVuY3Rpb24qICgpIHsgZS5zdG9wUHJvcGFnYXRpb24oKSwgZS5wcmV2ZW50RGVmYXVsdCgpLCBtKGUsIHQpOyBjb25zdCBuID0gdihlKTsgaWYgKCFuKSByZXR1cm4gITE7IGNvbnN0IG8gPSBiKG4pLCByID0gZS5kYXRhVHJhbnNmZXIuZ2V0RGF0YSgidGV4dCIpLCBzID0gZyhlKSwgaSA9IHQuZ2V0Tm9kZShyKTsgaWYgKCFpIHx8IChudWxsID09IGkgPyB2b2lkIDAgOiBpLmNvbnRhaW5zKG4pKSkgcmV0dXJuICExOyBjb25zdCBhID0gYihpKTsgaWYgKHQubG9ja1Jvb3RMZXZlbCAmJiAhKG51bGwgPT0gbiA/IHZvaWQgMCA6IG4ucGFyZW50RWxlbWVudC5jbG9zZXN0KHUuVEFHX05BTUUpKSAmJiAocyA9PT0gZi5CRUZPUkUgfHwgcyA9PT0gZi5BRlRFUikpIHJldHVybiAhMTsgaWYgKHMgPT09IGYuQkVGT1JFKSByZXR1cm4gISEoeWllbGQgdC5jb25maXJtKGksIG8pKSAmJiAobi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShpLCBuKSwgdC5vbkRyb3AoaSwgYSwgbyksICExKTsgaWYgKHMgPT09IGYuQUZURVIpIHsgaWYgKCEoeWllbGQgdC5jb25maXJtKGksIG8pKSkgcmV0dXJuICExOyBjb25zdCBlID0gbi5uZXh0RWxlbWVudFNpYmxpbmc7IHJldHVybiBlID8gKG4ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoaSwgZSksIHQub25Ecm9wKGksIGEsIG8pKSA6IChuLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoaSksIHQub25Ecm9wKGksIGEsIG8pKSwgITEgfSByZXR1cm4gISEoeWllbGQgdC5jb25maXJtKGksIG4pKSAmJiAobi5zdWJub2Rlcy5hcHBlbmRDaGlsZChpKSwgdC5vbkRyb3AoaSwgYSwgbiksICExKSB9KSksIHkgPSAoZSwgdCkgPT4geyBlLnByZXZlbnREZWZhdWx0KCksIGUuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAibW92ZSIsICgoZSwgdCkgPT4geyBjb25zdCBuID0gdihlKSwgbyA9IGcoZSk7IG4uY2xhc3NMaXN0LnRvZ2dsZSh0LnN0eWxlcy5ub2RlRHJvcEJlZm9yZSwgbyA9PT0gZi5CRUZPUkUpLCBuLmNsYXNzTGlzdC50b2dnbGUodC5zdHlsZXMubm9kZURyb3BJbnNpZGUsIG8gPT09IGYuSU5TSURFKSwgbi5jbGFzc0xpc3QudG9nZ2xlKHQuc3R5bGVzLm5vZGVEcm9wQWZ0ZXIsIG8gPT09IGYuQUZURVIpIH0pKGUsIHQpIH0sIEEgPSAoZSwgdCkgPT4geyBtKGUsIHQpIH0sIFQgPSAoZSwgdCkgPT4geyBlLnRhcmdldC5jbGFzc0xpc3QucmVtb3ZlKHQuc3R5bGVzLm5vZGVEcmFnZ2luZyksIG0oZSwgdCkgfSwgTiA9IGUgPT4gYHNvcnRhYmxlVHJlZVN0YXRlLSR7ZS5yZXBsYWNlKC9bXlx3XSsvLCAiLSIpfWA7IGNvbnN0IEwgPSBjbGFzcyB7IGNvbnN0cnVjdG9yKHsgbm9kZXM6IGUsIGVsZW1lbnQ6IHQsIHJlbmRlckxhYmVsOiBuLCBpY29uczogZCwgc3R5bGVzOiBjLCBsb2NrUm9vdExldmVsOiB1LCBvbkNoYW5nZTogaCwgb25DbGljazogcCwgaW5pdENvbGxhcHNlTGV2ZWw6IGYsIGNvbmZpcm06IGcsIGRpc2FibGVTb3J0aW5nOiB2LCBzdGF0ZUlkOiBiIH0pIHsgdGhpcy5ub2RlQ29sbGVjdGlvbiA9IHt9LCBlICYmICh0ID8gKHRoaXMuZGVmaW5lRWxlbWVudHMoKSwgdGhpcy5yb290ID0gdCwgdGhpcy5pY29ucyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgciksIGQpLCB0aGlzLnN0eWxlcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcyksIGMpLCB0aGlzLnJlbmRlckxhYmVsID0gbiB8fCBvLCB0aGlzLmxvY2tSb290TGV2ZWwgPSB2b2lkIDAgPT09IHUgfHwgdSwgdGhpcy5vbkNoYW5nZSA9IGggfHwgaSwgdGhpcy5vbkNsaWNrID0gcCB8fCBhLCB0aGlzLmNvbmZpcm0gPSBnIHx8IGwsIHRoaXMuaW5pdENvbGxhcHNlTGV2ZWwgPSB2b2lkIDAgPT09IGYgPyAyIDogZiwgdGhpcy5kaXNhYmxlU29ydGluZyA9IHYgfHwgITEsIHQuY2xhc3NMaXN0LmFkZCh0aGlzLnN0eWxlcy50cmVlKSwgdGhpcy5yZW5kZXIoeyBub2RlczogZSwgZWxlbWVudDogdCB9KSwgYiAmJiAoKChlLCB0KSA9PiB7IGNvbnN0IG4gPSBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKE4oZSkpOyBpZiAoIW4pIHJldHVybjsgY29uc3QgbyA9IEpTT04ucGFyc2UobiksIHIgPSAoZSwgdCkgPT4geyBjb25zdCBbbiwgb10gPSB0OyBlLmVsZW1lbnQuY29sbGFwc2UoMCA9PT0gbiksIG8gJiYgZS5zdWJub2Rlcy5mb3JFYWNoKCgoZSwgdCkgPT4geyB2b2lkIDAgIT09IG9bdF0gJiYgcihlLCBvW3RdKSB9KSkgfTsgdC5mb3JFYWNoKCgoZSwgdCkgPT4geyB2b2lkIDAgIT09IG9bdF0gJiYgcihlLCBvW3RdKSB9KSkgfSkoYiwgdGhpcy5wYXJzZVRyZWUodGhpcy5yb290KSksIHRoaXMuaW5pdFN0YXRlT2JzZXJ2ZXIoYikpKSA6IGNvbnNvbGUuZXJyb3IoJ0Vycm9yOiAiZWxlbWVudCIgaXMgbm90IGEgdmFsaWQgSFRNTCBlbGVtZW50IScpKSB9IGdldE5vZGUoZSkgeyByZXR1cm4gdGhpcy5ub2RlQ29sbGVjdGlvbltlXSB9IGZpbmROb2RlKGUsIHQpIHsgY29uc3QgbiA9IE9iamVjdC52YWx1ZXModGhpcy5ub2RlQ29sbGVjdGlvbik7IGZvciAobGV0IG8gPSAwOyBvIDwgbi5sZW5ndGg7IG8rKykgeyBjb25zdCByID0gbltvXSwgcyA9IHIuZGF0YTsgaWYgKGUgaW4gcyAmJiBzW2VdID09IHQpIHJldHVybiByIH0gcmV0dXJuIG51bGwgfSBvbkRyb3AoZSwgdCwgbikgeyBjb25zdCBvID0geyBub2RlczogdGhpcy5wYXJzZVRyZWUodGhpcy5yb290KSwgbW92ZWROb2RlOiBlLCBzcmNQYXJlbnROb2RlOiB0LCB0YXJnZXRQYXJlbnROb2RlOiBuIH07IG51bGwgPT0gbiB8fCBuLmNvbGxhcHNlKCExKSwgdGhpcy5vbkNoYW5nZShvKSB9IGRlc3Ryb3koKSB7IHRoaXMub2JzZXJ2ZXIuZGlzY29ubmVjdCgpLCB0aGlzLm9ic2VydmVyID0gbnVsbCB9IGluaXRTdGF0ZU9ic2VydmVyKGUpIHsgdGhpcy5vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKCgoKSA9PiB7ICgoZSwgdCkgPT4geyBjb25zdCBuID0gW10sIG8gPSBlID0+IHsgY29uc3QgdCA9IFtdLCBuID0gW2UuZWxlbWVudC5nZXRBdHRyaWJ1dGUoIm9wZW4iKSA/IDEgOiAwLCB0XTsgcmV0dXJuIGUuc3Vibm9kZXMuZm9yRWFjaCgoZSA9PiB7IHQucHVzaChvKGUpKSB9KSksIG4gfTsgdC5mb3JFYWNoKChlID0+IHsgbi5wdXNoKG8oZSkpIH0pKSwgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShOKGUpLCBKU09OLnN0cmluZ2lmeShuKSkgfSkoZSwgdGhpcy5wYXJzZVRyZWUodGhpcy5yb290KSkgfSkpLCB0aGlzLm9ic2VydmVyLm9ic2VydmUodGhpcy5yb290LCB7IGNoaWxkTGlzdDogITAsIGF0dHJpYnV0ZXM6ICEwLCBzdWJ0cmVlOiAhMCB9KSB9IGRlZmluZUVsZW1lbnRzKCkgeyB0cnkgeyBjdXN0b21FbGVtZW50cy5kZWZpbmUodS5UQUdfTkFNRSwgdSkgfSBjYXRjaCAoZSkgeyB9IH0gcmVuZGVyKHsgbm9kZXM6IGUsIGVsZW1lbnQ6IHQgfSwgbiA9IDApIHsgbisrLCBlLmZvckVhY2goKGUgPT4geyBjb25zdCBvID0gdS5jcmVhdGUoeyBpY29uczogdGhpcy5pY29ucywgc3R5bGVzOiB0aGlzLnN0eWxlcywgcGFyZW50OiB0LCByZW5kZXJMYWJlbDogdGhpcy5yZW5kZXJMYWJlbCwgZGF0YTogZS5kYXRhLCBvbkNsaWNrOiB0aGlzLm9uQ2xpY2ssIGRyYWdnYWJsZTogIXRoaXMuZGlzYWJsZVNvcnRpbmcgfSk7IHRoaXMuZGlzYWJsZVNvcnRpbmcgfHwgKChlLCB0KSA9PiB7IGNvbnN0IG4gPSB7IGRyYWdzdGFydDogRSwgZHJvcDogXywgZHJhZ292ZXI6IHksIGRyYWdlbmQ6IFQsIGRyYWdsZWF2ZTogQSB9OyBmb3IgKGNvbnN0IFtvLCByXSBvZiBPYmplY3QuZW50cmllcyhuKSkgcCh7IG5vZGU6IGUsIGV2ZW50TmFtZTogbywgaGFuZGxlcjogciwgdHJlZTogdCB9KSB9KShvLCB0aGlzKSwgby5jb2xsYXBzZShuID4gdGhpcy5pbml0Q29sbGFwc2VMZXZlbCksIHRoaXMubm9kZUNvbGxlY3Rpb25bby5pZF0gPSBvLCBlLm5vZGVzICYmIHRoaXMucmVuZGVyKHsgbm9kZXM6IGUubm9kZXMsIGVsZW1lbnQ6IG8uc3Vibm9kZXMgfSwgbikgfSkpIH0gcGFyc2VUcmVlKGUpIHsgY29uc3QgdCA9IEFycmF5LmZyb20oZS5xdWVyeVNlbGVjdG9yQWxsKGA6c2NvcGUgPiAke3UuVEFHX05BTUV9YCkpLCBuID0gW107IHJldHVybiB0LmZvckVhY2goKGUgPT4geyBuLnB1c2goeyBlbGVtZW50OiBlLCBpZDogZS5pZCwgc3Vibm9kZXM6IHRoaXMucGFyc2VUcmVlKGUuc3Vibm9kZXMpIH0pIH0pKSwgbiB9IH07IHJldHVybiB0ID0gdC5kZWZhdWx0IH0pKCkpKTs=",mtime:1743017042944},"assets/treeview.css":{data:"data:text/css;base64,LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBQYWdlIHZhcmlhYmxlcwogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgogaHRtbCB7CiAgLS10cmVldmlldy1ub2RlLWJvcmRlci13aWR0aDogMnB4OwogIC0tdHJlZXZpZXctbm9kZS1ib3JkZXItcmFkaXVzOiA1cHg7CgogIC0tdHJlZXZpZXctcGFnZS1jb2xvcjogdmFyKC0tZWRpdG9yLXdpa2ktbGluay1wYWdlLWNvbG9yKTsKICAtLXRyZWV2aWV3LXBhZ2UtYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZWRpdG9yLXdpa2ktbGluay1wYWdlLWJhY2tncm91bmQtY29sb3IpOwogIC0tdHJlZXZpZXctcGFnZS1ib3JkZXItY29sb3I6IHZhcigtLXRyZWV2aWV3LXBhZ2UtYmFja2dyb3VuZC1jb2xvcik7CgogIC0tdHJlZXZpZXctZm9sZGVyLWNvbG9yOiB2YXIoLS1lZGl0b3Itd2lraS1saW5rLXBhZ2UtbWlzc2luZy1jb2xvcik7CiAgLS10cmVldmlldy1mb2xkZXItYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tdHJlZXZpZXctcGFnZS1iYWNrZ3JvdW5kLWNvbG9yKTsKICAtLXRyZWV2aWV3LWZvbGRlci1ib3JkZXItY29sb3I6IHZhcigtLXRyZWV2aWV3LXBhZ2UtYmFja2dyb3VuZC1jb2xvcik7CgogIC0tdHJlZXZpZXctY3VycmVudC1wYWdlLWNvbG9yOiAjZWVlOwoJLS10cmVldmlldy1jdXJyZW50LXBhZ2UtYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tdWktYWNjZW50LWNvbG9yKTsKICAtLXRyZWV2aWV3LWN1cnJlbnQtcGFnZS1ib3JkZXItY29sb3I6IHZhcigtLXRyZWV2aWV3LXBhZ2UtYm9yZGVyLWNvbG9yKTsKfQoKLnRyZWV2aWV3LXJvb3QgewogIC8qIFNvcnRhYmxlVHJlZSB2YXJpYWJsZXMgKi8KICAtLXN0LWxhYmVsLWhlaWdodDogYXV0bzsKICAtLXN0LXN1Ym5vZGVzLXBhZGRpbmctbGVmdDogMS4yNXJlbTsKICAtLXN0LWNvbGxhcHNlLWljb24taGVpZ2h0OiAyLjFyZW07CiAgLS1zdC1jb2xsYXBzZS1pY29uLXdpZHRoOiAxLjI1cmVtOwogIC0tc3QtY29sbGFwc2UtaWNvbi1zaXplOiAxcmVtOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqIFBhZ2Ugc3R5bGVzCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCmh0bWwsIGJvZHkgewogIGJhY2tncm91bmQtY29sb3I6IHZhcigtLXJvb3QtYmFja2dyb3VuZC1jb2xvcik7CiAgcGFkZGluZzogMDsKICBtYXJnaW46IDA7CiAgb3ZlcmZsb3c6IGluaXRpYWwgIWltcG9ydGFudDsKfQoKLnRyZWV2aWV3LXJvb3QgewogIGJhY2tncm91bmQtY29sb3I6IHZhcigtLXJvb3QtYmFja2dyb3VuZC1jb2xvcik7CiAgY29sb3I6IHZhcigtLXJvb3QtY29sb3IpOwogIGZvbnQtZmFtaWx5OiB2YXIoLS11aS1mb250KTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKiBIZWFkZXIgc3R5bGVzCiAqCiAqIEFjdGlvbiBzdHlsZXMgYXJlIG1lYW50IHRvIG1pbWljIHRoZSBUb3AgQmFyIGljb25zIChgc2ItYWN0aW9uc2ApCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCi50cmVldmlldy1oZWFkZXIgewogIHBvc2l0aW9uOiBzdGlja3k7CiAgdG9wOiAwOwogIHotaW5kZXg6IDI7CiAgcGFkZGluZzogMC41cmVtIDAuNXJlbSAwcmVtOwogIGJhY2tncm91bmQtY29sb3I6IHZhcigtLXJvb3QtYmFja2dyb3VuZC1jb2xvcik7Cn0KCi50cmVldmlldy1hY3Rpb25zIHsKICBkaXNwbGF5OiBmbGV4OwogIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsKICBhbGlnbi1pdGVtczogZmxleC1zdGFydDsKICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1lZGl0b3Itd2lkZ2V0LWJhY2tncm91bmQtY29sb3IpOwogIGJvcmRlcjogdmFyKC0tdG9wLWJvcmRlci1jb2xvcikgMXB4IHNvbGlkOwogIGJvcmRlci1yYWRpdXM6IDVweDsKICBjb2xvcjogdmFyKC0tdG9wLWNvbG9yKTsKfQoKLnRyZWV2aWV3LWFjdGlvbnMtbGVmdCwKLnRyZWV2aWV3LWFjdGlvbnMtcmlnaHQgewogIGRpc3BsYXk6IGZsZXg7Cn0KCi50cmVldmlldy1hY3Rpb25zLWxlZnQgewogIGZsZXg6IDE7CiAgZmxleC13cmFwOiB3cmFwOwp9CgoudHJlZXZpZXctYWN0aW9ucyBidXR0b24gewogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBtYXJnaW46IDNweDsKICBwYWRkaW5nOiA1cHg7CiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tYWN0aW9uLWJ1dHRvbi1iYWNrZ3JvdW5kLWNvbG9yKTsKICBib3JkZXI6IDA7CiAgY29sb3I6IHZhcigtLWFjdGlvbi1idXR0b24tY29sb3IpOwogIGN1cnNvcjogcG9pbnRlcjsKfQoKLnRyZWV2aWV3LWFjdGlvbnMgYnV0dG9uOmhvdmVyIHsKICBjb2xvcjogdmFyKC0tYWN0aW9uLWJ1dHRvbi1ob3Zlci1jb2xvcik7Cn0KCi50cmVldmlldy1hY3Rpb25zIGJ1dHRvbjpob3ZlciB7CiAgY29sb3I6IHZhcigtLWFjdGlvbi1idXR0b24tYWN0aXZlLWNvbG9yKTsKfQoKLnRyZWV2aWV3LWFjdGlvbnMgYnV0dG9uID4gc3ZnIHsKICBoZWlnaHQ6IDE4cHg7CiAgd2lkdGg6IDE4cHg7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogU29ydGFibGVUcmVlIHN0eWxlcwogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgoudHJlZSB7CglkaXNwbGF5OiBmbGV4OwoJZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICBtYXJnaW46IDAuMjVyZW0gMC41cmVtIDFyZW07CiAgcGFkZGluZy1sZWZ0OiB2YXIoLS1zdC1zdWJub2Rlcy1wYWRkaW5nLWxlZnQpOwp9CgoudHJlZV9fbGFiZWwgewogIGRpc3BsYXk6IGZsZXg7CiAgcGFkZGluZzogMnB4Owp9CgoudHJlZV9fbGFiZWw6YWZ0ZXIgewogIGNvbnRlbnQ6ICcgJzsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgei1pbmRleDogNDsKICBpbnNldDogY2FsYyh2YXIoLS10cmVldmlldy1ub2RlLWJvcmRlci13aWR0aCkgKiAtMSkgdmFyKC0tdHJlZXZpZXctbm9kZS1ib3JkZXItd2lkdGgpOwogIGJvcmRlci10b3A6IGNhbGModmFyKC0tdHJlZXZpZXctbm9kZS1ib3JkZXItd2lkdGgpICogMikgc29saWQgdHJhbnNwYXJlbnQ7CiAgYm9yZGVyLWJvdHRvbTogY2FsYyh2YXIoLS10cmVldmlldy1ub2RlLWJvcmRlci13aWR0aCkgKiAyKSBzb2xpZCB0cmFuc3BhcmVudDsKICB0cmFuc2l0aW9uOiBib3JkZXItY29sb3IgMC4yczsKICBwb2ludGVyLWV2ZW50czogbm9uZTsKfQoKLnRyZWVfX25vZGUtLWRyb3AtYmVmb3JlID4gLnRyZWVfX2xhYmVsOmFmdGVyIHsKICBib3JkZXItdG9wLWNvbG9yOiB2YXIoLS11aS1hY2NlbnQtY29sb3IpOwp9CgoudHJlZV9fbm9kZS0tZHJvcC1hZnRlciA+IC50cmVlX19sYWJlbDphZnRlciB7CiAgYm9yZGVyLWJvdHRvbS1jb2xvcjogdmFyKC0tdWktYWNjZW50LWNvbG9yKTsKfQoKLnRyZWVfX2xhYmVsID4gc3BhbiB7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKICBwYWRkaW5nOiAwIDVweDsKICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50OwogIGJvcmRlci13aWR0aDogdmFyKC0tdHJlZXZpZXctbm9kZS1ib3JkZXItd2lkdGgpOwogIGJvcmRlci1zdHlsZTogc29saWQ7CiAgYm9yZGVyLXJhZGl1czogdmFyKC0tdHJlZXZpZXctbm9kZS1ib3JkZXItcmFkaXVzKTsKICBjdXJzb3I6IHBvaW50ZXI7CiAgZm9udC1mYW1pbHk6IHZhcigtLWVkaXRvci1mb250KTsKICBmb250LXNpemU6IDE4cHg7CiAgbGluZS1oZWlnaHQ6IDEuNDsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7CiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKfQoKLnRyZWVfX2xhYmVsID4gc3BhbltkYXRhLW5vZGUtdHlwZT0icGFnZSJdIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS10cmVldmlldy1wYWdlLWJhY2tncm91bmQtY29sb3IpOwogIGJvcmRlci1jb2xvcjogdmFyKC0tdHJlZXZpZXctcGFnZS1ib3JkZXItY29sb3IpOwogIGNvbG9yOiB2YXIoLS10cmVldmlldy1wYWdlLWNvbG9yKTsKfQoKLnRyZWVfX2xhYmVsID4gc3BhbltkYXRhLW5vZGUtdHlwZT0iZm9sZGVyIl0gewogIGJhY2tncm91bmQtY29sb3I6IHZhcigtLXRyZWV2aWV3LWZvbGRlci1iYWNrZ3JvdW5kLWNvbG9yKTsKICBib3JkZXItY29sb3I6IHZhcigtLXRyZWV2aWV3LWZvbGRlci1ib3JkZXItY29sb3IpOwogIGNvbG9yOiB2YXIoLS10cmVldmlldy1mb2xkZXItY29sb3IpOwp9CgoKLnRyZWVfX2xhYmVsID4gc3BhbltkYXRhLWN1cnJlbnQtcGFnZT0idHJ1ZSJdIHsKCWJhY2tncm91bmQtY29sb3I6IHZhcigtLXRyZWV2aWV3LWN1cnJlbnQtcGFnZS1iYWNrZ3JvdW5kLWNvbG9yKTsKICBib3JkZXItY29sb3I6IHZhcigtLXRyZWV2aWV3LWN1cnJlbnQtcGFnZS1ib3JkZXItY29sb3IpOwoJY29sb3I6IHZhcigtLXRyZWV2aWV3LWN1cnJlbnQtcGFnZS1jb2xvcik7Cn0KCi50cmVlX19jb2xsYXBzZSB7CiAgY29sb3I6IHZhcigtLWVkaXRvci1jb21tYW5kLWJ1dHRvbi1jb2xvcik7Cn0KCi50cmVlX19ub2RlLS1kcmFnZ2luZyB7CiAgbWFyZ2luOiBjYWxjKHZhcigtLXRyZWV2aWV3LW5vZGUtYm9yZGVyLXdpZHRoKSAqIC0xKTsKICBib3JkZXI6IHZhcigtLXRyZWV2aWV3LW5vZGUtYm9yZGVyLXdpZHRoKSBkYXNoZWQgdmFyKC0tc3VidGxlLWNvbG9yKTsKICBib3JkZXItcmFkaXVzOiB2YXIoLS10cmVldmlldy1ub2RlLWJvcmRlci1yYWRpdXMpOwogIGN1cnNvcjogbW92ZSAhaW1wb3J0YW50Owp9CgoudHJlZV9fbm9kZS0tZHJhZ2dpbmcgLnRyZWVfX2xhYmVsID4gc3BhbiB7CiAgb3BhY2l0eTogMC43NTsKfQoKLnRyZWVfX25vZGUtLWRyb3AtaW5zaWRlID4gLnRyZWVfX2xhYmVsID4gc3BhbiB7CiAgei1pbmRleDogMzsKICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1zdWJ0bGUtYmFja2dyb3VuZC1jb2xvcik7CiAgYm9yZGVyLWNvbG9yOiB2YXIoLS11aS1hY2NlbnQtY29sb3IpOwp9CgoudHJlZV9fbm9kZS0tZHJvcC1pbnNpZGUgPiAudHJlZV9fbGFiZWwgPiBzcGFuW2RhdGEtY3VycmVudC1wYWdlPSJ0cnVlIl0gewoJY29sb3I6IHZhcigtLXRyZWV2aWV3LXBhZ2UtY29sb3IpOwp9",mtime:1743017042945}},functions:{hide:{path:"./treeview.ts:hideTree"},show:{path:"./treeview.ts:showTree"},showIfEnabled:{path:"./treeview.ts:showTreeIfEnabled",events:["editor:init","editor:pageLoaded","editor:pageSaved","file:deleted"]},toggle:{path:"./treeview.ts:toggleTree",command:{name:"Tree View: Toggle",key:"Ctrl-alt-b",mac:"Cmd-alt-b"}}}},Ja={manifest:gt,functionMapping:mt};Ye(mt,gt,self.postMessage);export{Ja as plug};
37 |
--------------------------------------------------------------------------------
/treeview.plug.yaml:
--------------------------------------------------------------------------------
1 | name: treeview
2 | version: 0.15
3 | assets:
4 | - "assets/**/*.*"
5 | functions:
6 | # API
7 | hide:
8 | path: "./treeview.ts:hideTree"
9 |
10 | show:
11 | path: "./treeview.ts:showTree"
12 |
13 | showIfEnabled:
14 | path: "./treeview.ts:showTreeIfEnabled"
15 | events:
16 | - editor:init
17 | - editor:pageLoaded
18 | - editor:pageSaved
19 | - file:deleted
20 |
21 | # User facing
22 | toggle:
23 | path: "./treeview.ts:toggleTree"
24 | command:
25 | name: "Tree View: Toggle"
26 | key: Ctrl-alt-b
27 | mac: Cmd-alt-b
28 |
--------------------------------------------------------------------------------
/treeview.ts:
--------------------------------------------------------------------------------
1 | import { asset, editor, system } from "@silverbulletmd/silverbullet/syscalls";
2 | import { getPageTree } from "./api.ts";
3 | import {
4 | getCustomStyles,
5 | isTreeViewEnabled,
6 | PLUG_DISPLAY_NAME,
7 | PLUG_NAME,
8 | Position,
9 | setTreeViewEnabled,
10 | } from "./config.ts";
11 | import { supportsPageRenaming } from "./compatability.ts";
12 | import { getPlugConfig } from "./config.ts";
13 |
14 | /**
15 | * Keeps track of the current rendered position of the treeview.
16 | */
17 | let currentPosition: Position | undefined;
18 |
19 | /**
20 | * Toggles the treeview and it's preferred state.
21 | */
22 | export async function toggleTree() {
23 | const currentValue = await isTreeViewEnabled();
24 | if (!currentValue) {
25 | await showTree();
26 | } else {
27 | await hideTree();
28 | }
29 | }
30 |
31 | /**
32 | * Hides the treeview and sets it to disabled.
33 | */
34 | export async function hideTree() {
35 | if (currentPosition) {
36 | await editor.hidePanel(currentPosition);
37 | currentPosition = undefined;
38 | await setTreeViewEnabled(false);
39 | }
40 | }
41 |
42 | /**
43 | * Shows the treeview only if it is currently enabled.
44 | */
45 | export async function showTreeIfEnabled() {
46 | try {
47 | const env = await system.getEnv();
48 | if (env === "server") {
49 | return;
50 | }
51 |
52 | if (await isTreeViewEnabled()) {
53 | return await showTree();
54 | }
55 | } catch (err) {
56 | console.error(`${PLUG_DISPLAY_NAME}: showTreeIfEnabled failed`, err);
57 | }
58 | }
59 |
60 | /**
61 | * Shows the treeview and sets it to enabled.
62 | */
63 | export async function showTree() {
64 | const config = await getPlugConfig();
65 |
66 | if (currentPosition && config.position !== currentPosition) {
67 | // This can be caused if the position preference in SETTINGS was changed
68 | // while the tree was visible. If we don't first hide the page tree,
69 | // we'll end up with multiple trees visible.
70 | await hideTree();
71 | }
72 |
73 | const [
74 | sortableTreeCss,
75 | sortableTreeJs,
76 | plugCss,
77 | plugJs,
78 | iconFolderMinus,
79 | iconFolderPlus,
80 | iconNavigation2,
81 | iconRefresh,
82 | iconXCircle,
83 | ] = await Promise.all([
84 | asset.readAsset(PLUG_NAME, "assets/sortable-tree/sortable-tree.css"),
85 | asset.readAsset(PLUG_NAME, "assets/sortable-tree/sortable-tree.js"),
86 | asset.readAsset(PLUG_NAME, "assets/treeview.css"),
87 | asset.readAsset(PLUG_NAME, "assets/treeview.js"),
88 | asset.readAsset(PLUG_NAME, "assets/icons/folder-minus.svg"),
89 | asset.readAsset(PLUG_NAME, "assets/icons/folder-plus.svg"),
90 | asset.readAsset(PLUG_NAME, "assets/icons/navigation-2.svg"),
91 | asset.readAsset(PLUG_NAME, "assets/icons/refresh-cw.svg"),
92 | asset.readAsset(PLUG_NAME, "assets/icons/x-circle.svg"),
93 | ]);
94 |
95 | const { currentPage, nodes } = await getPageTree(config);
96 | const customStyles = await getCustomStyles();
97 |
98 | const treeViewConfig = {
99 | nodes,
100 | currentPage,
101 | treeElementId: "treeview-tree",
102 | dragAndDrop: {
103 | ...config.dragAndDrop,
104 | enabled: config.dragAndDrop.enabled,
105 | },
106 | };
107 |
108 | await editor.showPanel(
109 | config.position,
110 | config.size,
111 | `
112 |
113 |
118 | `,
134 | `
135 | ${sortableTreeJs}
136 | ${plugJs}
137 | initializeTreeViewPanel(${JSON.stringify(treeViewConfig)});
138 | `,
139 | );
140 |
141 | await setTreeViewEnabled(true);
142 | currentPosition = config.position;
143 | }
144 |
--------------------------------------------------------------------------------