pinokiod 7.2.7 → 7.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/api/index.js +28 -0
- package/kernel/api/shell_run_template.js +273 -0
- package/kernel/index.js +2 -0
- package/kernel/shell.js +21 -2
- package/kernel/watch/context.js +42 -0
- package/kernel/watch/drivers/fs.js +71 -0
- package/kernel/watch/drivers/poll.js +33 -0
- package/kernel/watch/index.js +158 -0
- package/package.json +1 -1
- package/server/features/drafts/index.js +41 -0
- package/server/features/drafts/parser.js +169 -0
- package/server/features/drafts/public/drafts.js +1546 -0
- package/server/features/drafts/registry_import.js +427 -0
- package/server/features/drafts/routes.js +68 -0
- package/server/features/drafts/service.js +261 -0
- package/server/features/drafts/watcher.js +76 -0
- package/server/features/index.js +13 -0
- package/server/index.js +56 -7
- package/server/lib/workspace_catalog.js +151 -0
- package/server/lib/workspace_runtime.js +390 -0
- package/server/public/common.js +8 -0
- package/server/routes/workspaces.js +44 -0
- package/server/socket.js +22 -11
- package/server/views/app.ejs +159 -1
- package/server/views/partials/main_sidebar.ejs +1 -0
- package/server/views/partials/workspace_row.ejs +61 -0
- package/server/views/terminal.ejs +8 -0
- package/server/views/terminals.ejs +1 -0
- package/server/views/workspaces.ejs +812 -0
package/server/views/app.ejs
CHANGED
|
@@ -5288,6 +5288,7 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5288
5288
|
</a>
|
|
5289
5289
|
<%})%>
|
|
5290
5290
|
</div>
|
|
5291
|
+
<div class='active-nested-path hidden' id='active-nested-path'></div>
|
|
5291
5292
|
</div>
|
|
5292
5293
|
<div class='menu-actions'>
|
|
5293
5294
|
<% if (type === 'run') { %>
|
|
@@ -7184,6 +7185,7 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7184
7185
|
}
|
|
7185
7186
|
|
|
7186
7187
|
if (!target) {
|
|
7188
|
+
activeNestedFocusMenu = null
|
|
7187
7189
|
syncActiveNestedPath()
|
|
7188
7190
|
browserPopoutSurface.hide()
|
|
7189
7191
|
document.querySelector(".container").classList.remove("active")
|
|
@@ -7217,6 +7219,7 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7217
7219
|
el.classList.remove("selected")
|
|
7218
7220
|
})
|
|
7219
7221
|
target.classList.add("selected")
|
|
7222
|
+
activeNestedFocusMenu = null
|
|
7220
7223
|
syncActiveNestedPath({ selectedLink: target })
|
|
7221
7224
|
if (skipPersistedSelection && target.hasAttribute('data-default')) {
|
|
7222
7225
|
ignorePersistedSelection = false
|
|
@@ -8052,7 +8055,162 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8052
8055
|
|
|
8053
8056
|
const getSubmenu = (menu) => getDirectChild(menu, ".submenu")
|
|
8054
8057
|
const getToggle = (menu) => getDirectChild(menu, ".reveal")
|
|
8055
|
-
const
|
|
8058
|
+
const activeNestedPathRoot = document.getElementById("active-nested-path")
|
|
8059
|
+
const activeNestedProxyMap = new WeakMap()
|
|
8060
|
+
let activeNestedFocusMenu = null
|
|
8061
|
+
|
|
8062
|
+
const getNestedMenuChain = (node) => {
|
|
8063
|
+
if (!node) {
|
|
8064
|
+
return []
|
|
8065
|
+
}
|
|
8066
|
+
let current = node
|
|
8067
|
+
if (!current.classList || !current.classList.contains("nested-menu")) {
|
|
8068
|
+
current = current.closest(".nested-menu")
|
|
8069
|
+
}
|
|
8070
|
+
const chain = []
|
|
8071
|
+
while (current) {
|
|
8072
|
+
chain.unshift(current)
|
|
8073
|
+
current = current.parentElement ? current.parentElement.closest(".nested-menu") : null
|
|
8074
|
+
}
|
|
8075
|
+
return chain
|
|
8076
|
+
}
|
|
8077
|
+
|
|
8078
|
+
const sanitizeActiveNestedProxy = (proxy) => {
|
|
8079
|
+
if (!proxy) {
|
|
8080
|
+
return null
|
|
8081
|
+
}
|
|
8082
|
+
proxy.removeAttribute("id")
|
|
8083
|
+
proxy.classList.remove("frame-link", "selected", "tab-link-popover-host")
|
|
8084
|
+
proxy.classList.add("active-nested-proxy")
|
|
8085
|
+
proxy.setAttribute("data-active-nested-proxy", "true")
|
|
8086
|
+
proxy.querySelectorAll(".tab-link-popover-trigger").forEach((node) => {
|
|
8087
|
+
node.remove()
|
|
8088
|
+
})
|
|
8089
|
+
return proxy
|
|
8090
|
+
}
|
|
8091
|
+
|
|
8092
|
+
const buildActiveNestedProxy = (child, isCurrent) => {
|
|
8093
|
+
if (!child) {
|
|
8094
|
+
return null
|
|
8095
|
+
}
|
|
8096
|
+
let proxy
|
|
8097
|
+
if (child.classList && child.classList.contains("nested-menu")) {
|
|
8098
|
+
const toggle = getToggle(child)
|
|
8099
|
+
if (!toggle) {
|
|
8100
|
+
return null
|
|
8101
|
+
}
|
|
8102
|
+
proxy = toggle.cloneNode(true)
|
|
8103
|
+
} else {
|
|
8104
|
+
proxy = child.cloneNode(true)
|
|
8105
|
+
}
|
|
8106
|
+
sanitizeActiveNestedProxy(proxy)
|
|
8107
|
+
if (child.classList && child.classList.contains("nested-menu")) {
|
|
8108
|
+
const loader = proxy.querySelector(".loader")
|
|
8109
|
+
if (loader) {
|
|
8110
|
+
loader.innerHTML = `<i class="fa-solid ${isCurrent ? "fa-angle-down" : "fa-angle-right"}"></i>`
|
|
8111
|
+
}
|
|
8112
|
+
}
|
|
8113
|
+
proxy.classList.toggle("is-current", Boolean(isCurrent))
|
|
8114
|
+
activeNestedProxyMap.set(proxy, child)
|
|
8115
|
+
return proxy
|
|
8116
|
+
}
|
|
8117
|
+
|
|
8118
|
+
const syncActiveNestedPath = ({ selectedLink = null } = {}) => {
|
|
8119
|
+
if (!activeNestedPathRoot) {
|
|
8120
|
+
return
|
|
8121
|
+
}
|
|
8122
|
+
if (activeNestedFocusMenu && !activeNestedFocusMenu.isConnected) {
|
|
8123
|
+
activeNestedFocusMenu = null
|
|
8124
|
+
}
|
|
8125
|
+
const currentSelectedLink = (selectedLink && selectedLink.isConnected)
|
|
8126
|
+
? selectedLink
|
|
8127
|
+
: document.querySelector("aside .frame-link.selected")
|
|
8128
|
+
const chain = activeNestedFocusMenu
|
|
8129
|
+
? getNestedMenuChain(activeNestedFocusMenu)
|
|
8130
|
+
: getNestedMenuChain(currentSelectedLink)
|
|
8131
|
+
|
|
8132
|
+
activeNestedPathRoot.replaceChildren()
|
|
8133
|
+
|
|
8134
|
+
if (!chain.length) {
|
|
8135
|
+
activeNestedPathRoot.classList.add("hidden")
|
|
8136
|
+
if (window.PinokioMenuScrollHints && typeof window.PinokioMenuScrollHints.update === "function") {
|
|
8137
|
+
window.PinokioMenuScrollHints.update()
|
|
8138
|
+
}
|
|
8139
|
+
return
|
|
8140
|
+
}
|
|
8141
|
+
|
|
8142
|
+
chain.forEach((menu, index) => {
|
|
8143
|
+
const submenu = getSubmenu(menu)
|
|
8144
|
+
if (!submenu) {
|
|
8145
|
+
return
|
|
8146
|
+
}
|
|
8147
|
+
const row = document.createElement("div")
|
|
8148
|
+
row.className = "m active-nested-row"
|
|
8149
|
+
row.dataset.activeNestedLevel = String(index)
|
|
8150
|
+
const nextMenu = chain[index + 1] || null
|
|
8151
|
+
|
|
8152
|
+
Array.from(submenu.children).forEach((child) => {
|
|
8153
|
+
let isCurrent = false
|
|
8154
|
+
if (child.classList && child.classList.contains("nested-menu")) {
|
|
8155
|
+
isCurrent = child === nextMenu || (!nextMenu && currentSelectedLink ? child.contains(currentSelectedLink) : false)
|
|
8156
|
+
} else {
|
|
8157
|
+
isCurrent = child === currentSelectedLink
|
|
8158
|
+
}
|
|
8159
|
+
const proxy = buildActiveNestedProxy(child, isCurrent)
|
|
8160
|
+
if (proxy) {
|
|
8161
|
+
row.appendChild(proxy)
|
|
8162
|
+
}
|
|
8163
|
+
})
|
|
8164
|
+
|
|
8165
|
+
if (row.childElementCount > 0) {
|
|
8166
|
+
activeNestedPathRoot.appendChild(row)
|
|
8167
|
+
}
|
|
8168
|
+
})
|
|
8169
|
+
|
|
8170
|
+
if (!activeNestedPathRoot.childElementCount) {
|
|
8171
|
+
activeNestedPathRoot.classList.add("hidden")
|
|
8172
|
+
if (window.PinokioMenuScrollHints && typeof window.PinokioMenuScrollHints.update === "function") {
|
|
8173
|
+
window.PinokioMenuScrollHints.update()
|
|
8174
|
+
}
|
|
8175
|
+
return
|
|
8176
|
+
}
|
|
8177
|
+
|
|
8178
|
+
activeNestedPathRoot.classList.remove("hidden")
|
|
8179
|
+
const currentProxy = activeNestedPathRoot.querySelector(".active-nested-proxy.is-current")
|
|
8180
|
+
if (currentProxy && typeof currentProxy.scrollIntoView === "function") {
|
|
8181
|
+
currentProxy.scrollIntoView({
|
|
8182
|
+
block: "nearest",
|
|
8183
|
+
inline: "nearest"
|
|
8184
|
+
})
|
|
8185
|
+
}
|
|
8186
|
+
if (window.PinokioMenuScrollHints && typeof window.PinokioMenuScrollHints.update === "function") {
|
|
8187
|
+
window.PinokioMenuScrollHints.update()
|
|
8188
|
+
}
|
|
8189
|
+
}
|
|
8190
|
+
|
|
8191
|
+
if (activeNestedPathRoot) {
|
|
8192
|
+
activeNestedPathRoot.addEventListener("click", (event) => {
|
|
8193
|
+
const proxy = event.target.closest("[data-active-nested-proxy='true']")
|
|
8194
|
+
if (!proxy || !activeNestedPathRoot.contains(proxy)) {
|
|
8195
|
+
return
|
|
8196
|
+
}
|
|
8197
|
+
const source = activeNestedProxyMap.get(proxy)
|
|
8198
|
+
if (!source || !source.isConnected) {
|
|
8199
|
+
return
|
|
8200
|
+
}
|
|
8201
|
+
event.preventDefault()
|
|
8202
|
+
event.stopPropagation()
|
|
8203
|
+
if (source.classList && source.classList.contains("nested-menu")) {
|
|
8204
|
+
activeNestedFocusMenu = source
|
|
8205
|
+
syncActiveNestedPath()
|
|
8206
|
+
return
|
|
8207
|
+
}
|
|
8208
|
+
activeNestedFocusMenu = null
|
|
8209
|
+
if (typeof source.click === "function") {
|
|
8210
|
+
source.click()
|
|
8211
|
+
}
|
|
8212
|
+
})
|
|
8213
|
+
}
|
|
8056
8214
|
|
|
8057
8215
|
renderSelection()
|
|
8058
8216
|
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
</button>
|
|
28
28
|
</div>
|
|
29
29
|
<a href="/home" class="tab <%= sidebarSelected === 'home' ? 'selected' : '' %>" data-tippy-content="This machine"><i class='fas fa-laptop-code'></i><div class='caption'>This machine</div></a>
|
|
30
|
+
<a href="/workspaces" class="tab <%= sidebarSelected === 'workspaces' ? 'selected' : '' %>" data-tippy-content="Workspaces"><i class="fa-solid fa-folder-tree"></i><div class='caption'>Workspaces</div></a>
|
|
30
31
|
<a href="/network" class="tab <%= sidebarSelected === 'network' ? 'selected' : '' %>" data-tippy-content="Local network"><i class="fa-solid fa-wifi"></i><div class='caption'>Local network</div></a>
|
|
31
32
|
<% if (sidebarList.length > 0) { %>
|
|
32
33
|
<% sidebarList.forEach(({ host, name, platform }) => { %>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const shellCount = workspace.counts && Number.isFinite(workspace.counts.shells) ? workspace.counts.shells : 0;
|
|
3
|
+
const scriptCount = workspace.counts && Number.isFinite(workspace.counts.scripts) ? workspace.counts.scripts : 0;
|
|
4
|
+
const draftCount = workspace.counts && Number.isFinite(workspace.counts.drafts) ? workspace.counts.drafts : 0;
|
|
5
|
+
const shellTitles = Array.isArray(workspace.shells) ? workspace.shells.map((shell) => shell.title || shell.id || "").join(" ") : "";
|
|
6
|
+
const scriptTitles = Array.isArray(workspace.scripts) ? workspace.scripts.map((script) => script.title || script.id || "").join(" ") : "";
|
|
7
|
+
const draft = workspace.draft || null;
|
|
8
|
+
const draftId = draft && draft.id ? draft.id : `draft-${index}`;
|
|
9
|
+
const searchText = [workspace.name, workspace.cwd, shellTitles, scriptTitles, draft && draft.title].filter(Boolean).join(" ");
|
|
10
|
+
const modifiedLabel = dateLabel(workspace.modifiedAt);
|
|
11
|
+
const details = [];
|
|
12
|
+
if (shellCount > 0) details.push(plural(shellCount, "terminal"));
|
|
13
|
+
if (scriptCount > 0) details.push(plural(scriptCount, "script"));
|
|
14
|
+
if (draftCount > 0) details.push(draftCount === 1 ? "Draft ready" : plural(draftCount, "draft"));
|
|
15
|
+
if (modifiedLabel) details.push(modifiedLabel);
|
|
16
|
+
%>
|
|
17
|
+
<div
|
|
18
|
+
class="workspace-card workspace-line line align-top"
|
|
19
|
+
data-cwd="<%= workspace.cwd %>"
|
|
20
|
+
data-name="<%= workspace.name %>"
|
|
21
|
+
data-index="<%= index %>"
|
|
22
|
+
data-launch-count-total="<%= workspace.usageCount || 0 %>"
|
|
23
|
+
data-last-launch-at="<%= workspace.lastOpenedAt || workspace.modifiedAt || "" %>"
|
|
24
|
+
data-search="<%= searchText %>"
|
|
25
|
+
>
|
|
26
|
+
<h3>
|
|
27
|
+
<div class="workspace-icon item-icon">
|
|
28
|
+
<i class="fa-solid <%= workspace.running ? "fa-folder-open" : "fa-folder" %>" aria-hidden="true"></i>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="col">
|
|
31
|
+
<div class="title">
|
|
32
|
+
<i class="fa-solid fa-circle" aria-hidden="true"></i>
|
|
33
|
+
<span><%= workspace.name || "Workspace" %></span>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="uri"><%= workspace.cwd %></div>
|
|
36
|
+
<% if (details.length) { %>
|
|
37
|
+
<div class="description"><%= details.join(" / ") %></div>
|
|
38
|
+
<% } %>
|
|
39
|
+
<div class="menu-btns">
|
|
40
|
+
<% if (workspace.primaryUrl && shellCount === 1) { %>
|
|
41
|
+
<a class="btn" href="<%= workspace.primaryUrl %>" title="Open terminal"><i class="fa-solid fa-terminal" aria-hidden="true"></i> Terminal</a>
|
|
42
|
+
<% } else if (shellCount > 1) { %>
|
|
43
|
+
<button class="btn" type="button" data-open-workspace="<%= workspace.cwd %>" data-workspace-modal-mode="terminals" title="Open terminals"><i class="fa-solid fa-terminal" aria-hidden="true"></i> Terminals</button>
|
|
44
|
+
<% } %>
|
|
45
|
+
<% if (workspace.launchUrl) { %>
|
|
46
|
+
<button class="btn" type="button" data-open-workspace="<%= workspace.cwd %>" data-workspace-modal-mode="session" title="Start session"><i class="fa-solid fa-play" aria-hidden="true"></i> Start</button>
|
|
47
|
+
<% } %>
|
|
48
|
+
<button class="btn" type="button" data-open-path="<%= workspace.cwd %>" title="Open folder"><i class="fa-solid fa-folder-open" aria-hidden="true"></i> Folder</button>
|
|
49
|
+
<% if (draft && draft.postPath) { %>
|
|
50
|
+
<button class="btn" type="button" data-open-path="<%= draft.postPath %>" title="Open draft"><i class="fa-solid fa-file-lines" aria-hidden="true"></i> Draft</button>
|
|
51
|
+
<% if (draft.excerpt) { %>
|
|
52
|
+
<button class="btn" type="button" data-preview-toggle="<%= draftId %>"><i class="fa-solid fa-eye" aria-hidden="true"></i> Preview</button>
|
|
53
|
+
<% } %>
|
|
54
|
+
<% } %>
|
|
55
|
+
</div>
|
|
56
|
+
<% if (draft && draft.excerpt) { %>
|
|
57
|
+
<div class="workspace-draft-preview" data-preview-panel="<%= draftId %>" hidden><%= draft.excerpt %></div>
|
|
58
|
+
<% } %>
|
|
59
|
+
</div>
|
|
60
|
+
</h3>
|
|
61
|
+
</div>
|
|
@@ -3086,5 +3086,13 @@ const reloadMemory = async () => {
|
|
|
3086
3086
|
</a>
|
|
3087
3087
|
</div>
|
|
3088
3088
|
</div>
|
|
3089
|
+
<% if (typeof draft_watch_enabled !== 'undefined' && draft_watch_enabled) { %>
|
|
3090
|
+
<script>
|
|
3091
|
+
window.PinokioDraftContext = {
|
|
3092
|
+
cwd: <%- JSON.stringify((typeof draft_watch_cwd !== 'undefined' && draft_watch_cwd) ? draft_watch_cwd : '').replace(/</g, '\\u003c') %>
|
|
3093
|
+
};
|
|
3094
|
+
</script>
|
|
3095
|
+
<script src="/drafts.js"></script>
|
|
3096
|
+
<% } %>
|
|
3089
3097
|
</body>
|
|
3090
3098
|
</html>
|
|
@@ -10030,5 +10030,6 @@ body.dark .swal2-popup.pinokio-diff-modal .pinokio-modal-footer--commit .pinokio
|
|
|
10030
10030
|
requestAnimationFrame(setViewport)
|
|
10031
10031
|
})()
|
|
10032
10032
|
</script>
|
|
10033
|
+
<script src="/drafts.js"></script>
|
|
10033
10034
|
</body>
|
|
10034
10035
|
</html>
|