pinokiod 7.2.8 → 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 +26 -0
- package/kernel/index.js +2 -0
- 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/{routes/draft_import.js → features/drafts/registry_import.js} +35 -77
- 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 +25 -36
- package/server/views/app.ejs +159 -14
- package/server/views/terminal.ejs +8 -6
- package/server/lib/drafts.js +0 -376
- package/server/public/drafts.js +0 -632
package/server/index.js
CHANGED
|
@@ -29,7 +29,7 @@ const serveIndex = require('./serveIndex')
|
|
|
29
29
|
const registerFileRoutes = require('./routes/files')
|
|
30
30
|
const registerAppRoutes = require('./routes/apps')
|
|
31
31
|
const registerWorkspacesRoutes = require('./routes/workspaces')
|
|
32
|
-
const
|
|
32
|
+
const { mountFeatures } = require('./features')
|
|
33
33
|
const Git = require("../kernel/git")
|
|
34
34
|
const TerminalApi = require('../kernel/api/terminal')
|
|
35
35
|
|
|
@@ -80,7 +80,6 @@ const { createDesktopEventRouter } = require("./lib/desktop_event_router")
|
|
|
80
80
|
const { createInjectRouter, resolveInjectList } = require("./lib/inject_router")
|
|
81
81
|
const { createTaskPackageService } = require("./lib/task_packages")
|
|
82
82
|
const { createTaskWorkspaceLinkService } = require("./lib/task_workspace_links")
|
|
83
|
-
const { createDraftService } = require("./lib/drafts")
|
|
84
83
|
const { createWorkspaceRuntimeService } = require("./lib/workspace_runtime")
|
|
85
84
|
const { createWorkspaceCatalogService } = require("./lib/workspace_catalog")
|
|
86
85
|
const { createContentValidationService } = require("./lib/content_validation")
|
|
@@ -2870,11 +2869,19 @@ class Server {
|
|
|
2870
2869
|
const protectionPreference = protectionAppId && this.appPreferences && typeof this.appPreferences.getPreference === "function"
|
|
2871
2870
|
? await this.appPreferences.getPreference(protectionAppId)
|
|
2872
2871
|
: null
|
|
2872
|
+
const draftWatchEnabled = this.kernel.watch && typeof this.kernel.watch.hasHandler === "function"
|
|
2873
|
+
? this.kernel.watch.hasHandler(resolved, "draft")
|
|
2874
|
+
: false
|
|
2875
|
+
const draftWatchCwd = draftWatchEnabled
|
|
2876
|
+
? (req.query.cwd || path.dirname(filepath))
|
|
2877
|
+
: ""
|
|
2873
2878
|
const result = {
|
|
2874
2879
|
portal: this.portal,
|
|
2875
2880
|
projectName: (pathComponents.length > 0 ? pathComponents[0] : ''),
|
|
2876
2881
|
protection_app_id: protectionAppId,
|
|
2877
2882
|
protection_enabled: protectionPreference ? protectionPreference.protection_enabled !== false : false,
|
|
2883
|
+
draft_watch_enabled: draftWatchEnabled,
|
|
2884
|
+
draft_watch_cwd: draftWatchCwd,
|
|
2878
2885
|
kill_message,
|
|
2879
2886
|
callback,
|
|
2880
2887
|
callback_target,
|
|
@@ -8412,23 +8419,20 @@ class Server {
|
|
|
8412
8419
|
kernel: this.kernel
|
|
8413
8420
|
})
|
|
8414
8421
|
this.workspaceRuntime = workspaceRuntime
|
|
8415
|
-
const
|
|
8422
|
+
const features = await mountFeatures({
|
|
8423
|
+
app: this.app,
|
|
8416
8424
|
kernel: this.kernel,
|
|
8417
|
-
taskWorkspaceLinks
|
|
8425
|
+
taskWorkspaceLinks,
|
|
8426
|
+
defaultRegistryUrl: DEFAULT_REGISTRY_URL
|
|
8418
8427
|
})
|
|
8428
|
+
this.features = features
|
|
8429
|
+
const drafts = features.drafts.service
|
|
8419
8430
|
this.drafts = drafts
|
|
8420
8431
|
const workspaceCatalog = createWorkspaceCatalogService({
|
|
8421
8432
|
kernel: this.kernel,
|
|
8422
8433
|
workspaceRuntime,
|
|
8423
8434
|
drafts
|
|
8424
8435
|
})
|
|
8425
|
-
drafts.start().catch((error) => {
|
|
8426
|
-
console.warn("[drafts] failed to start", error && error.message ? error.message : error)
|
|
8427
|
-
})
|
|
8428
|
-
registerDraftImportRoutes(this.app, {
|
|
8429
|
-
drafts,
|
|
8430
|
-
defaultRegistryUrl: DEFAULT_REGISTRY_URL
|
|
8431
|
-
})
|
|
8432
8436
|
registerWorkspacesRoutes(this.app, {
|
|
8433
8437
|
workspaceCatalog,
|
|
8434
8438
|
composePeerAccessPayload: () => this.composePeerAccessPayload(),
|
|
@@ -9870,9 +9874,6 @@ class Server {
|
|
|
9870
9874
|
}
|
|
9871
9875
|
try {
|
|
9872
9876
|
await taskWorkspaceLinks.touchTaskWorkspace(task.id, workspaceRef)
|
|
9873
|
-
drafts.trackWorkspace({ taskId: task.id, ref: workspaceRef }).catch((error) => {
|
|
9874
|
-
console.warn("[drafts] failed to track workspace", error && error.message ? error.message : error)
|
|
9875
|
-
})
|
|
9876
9877
|
} catch (error) {
|
|
9877
9878
|
await taskPackages.deleteTaskPackage(task.id).catch(() => {})
|
|
9878
9879
|
throw error
|
|
@@ -10110,7 +10111,8 @@ class Server {
|
|
|
10110
10111
|
}
|
|
10111
10112
|
}
|
|
10112
10113
|
|
|
10113
|
-
const
|
|
10114
|
+
const filledInputValues = filterFilledTaskInputValues(inputValues)
|
|
10115
|
+
const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
|
|
10114
10116
|
if (!prompt) {
|
|
10115
10117
|
await renderTaskLaunchPage(req, res, task, {
|
|
10116
10118
|
selectedTool,
|
|
@@ -10216,9 +10218,6 @@ class Server {
|
|
|
10216
10218
|
}
|
|
10217
10219
|
try {
|
|
10218
10220
|
await taskWorkspaceLinks.touchTaskWorkspace(task.id, workspaceRef)
|
|
10219
|
-
drafts.trackWorkspace({ taskId: task.id, ref: workspaceRef }).catch((error) => {
|
|
10220
|
-
console.warn("[drafts] failed to track workspace", error && error.message ? error.message : error)
|
|
10221
|
-
})
|
|
10222
10221
|
} catch (error) {
|
|
10223
10222
|
await renderTaskLaunchPage(req, res, task, {
|
|
10224
10223
|
selectedTool,
|
|
@@ -10234,24 +10233,13 @@ class Server {
|
|
|
10234
10233
|
params.set("cwd", targetPath)
|
|
10235
10234
|
params.set("chrome", "full")
|
|
10236
10235
|
params.set("prompt", prompt)
|
|
10236
|
+
if (filledInputValues.url) {
|
|
10237
|
+
params.set("url", filledInputValues.url)
|
|
10238
|
+
}
|
|
10237
10239
|
res.redirect(`${pluginHref}?${params.toString()}`)
|
|
10238
10240
|
})
|
|
10239
10241
|
this.app.post("/task/start", handleTaskStartRequest)
|
|
10240
10242
|
|
|
10241
|
-
this.app.get("/drafts", ex(async (req, res) => {
|
|
10242
|
-
const cwd = typeof req.query.cwd === "string" ? req.query.cwd : ""
|
|
10243
|
-
const items = await drafts.listPending({ cwd })
|
|
10244
|
-
res.json({
|
|
10245
|
-
ok: true,
|
|
10246
|
-
items
|
|
10247
|
-
})
|
|
10248
|
-
}))
|
|
10249
|
-
|
|
10250
|
-
this.app.post("/drafts/:id/dismiss", ex(async (req, res) => {
|
|
10251
|
-
const ok = await drafts.dismiss(req.params.id)
|
|
10252
|
-
res.json({ ok })
|
|
10253
|
-
}))
|
|
10254
|
-
|
|
10255
10243
|
this.app.get("/home", renderHomePage)
|
|
10256
10244
|
|
|
10257
10245
|
const normalizePathForComparison = (value) => {
|
|
@@ -10554,7 +10542,8 @@ class Server {
|
|
|
10554
10542
|
return
|
|
10555
10543
|
}
|
|
10556
10544
|
|
|
10557
|
-
const
|
|
10545
|
+
const filledInputValues = filterFilledTaskInputValues(inputValues)
|
|
10546
|
+
const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
|
|
10558
10547
|
if (!prompt) {
|
|
10559
10548
|
res.status(400).json({
|
|
10560
10549
|
ok: false,
|
|
@@ -10648,15 +10637,15 @@ class Server {
|
|
|
10648
10637
|
}
|
|
10649
10638
|
|
|
10650
10639
|
await taskWorkspaceLinks.touchTaskWorkspace(task.id, workspaceRef)
|
|
10651
|
-
drafts.trackWorkspace({ taskId: task.id, ref: workspaceRef }).catch((error) => {
|
|
10652
|
-
console.warn("[drafts] failed to track workspace", error && error.message ? error.message : error)
|
|
10653
|
-
})
|
|
10654
10640
|
|
|
10655
10641
|
const params = new URLSearchParams()
|
|
10656
10642
|
params.set("cwd", targetPath)
|
|
10657
10643
|
params.set("chrome", "full")
|
|
10658
10644
|
params.set("session", createUniversalLauncherSessionId())
|
|
10659
10645
|
params.set("prompt", prompt)
|
|
10646
|
+
if (filledInputValues.url) {
|
|
10647
|
+
params.set("url", filledInputValues.url)
|
|
10648
|
+
}
|
|
10660
10649
|
|
|
10661
10650
|
res.json({
|
|
10662
10651
|
ok: true,
|
package/server/views/app.ejs
CHANGED
|
@@ -5222,9 +5222,6 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5222
5222
|
<a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
|
|
5223
5223
|
<i class="fa-solid fa-house"></i>
|
|
5224
5224
|
</a>
|
|
5225
|
-
<a class='btn mobile-sheet-action' href="/workspaces" aria-label="Workspaces" title="Workspaces">
|
|
5226
|
-
<i class="fa-solid fa-folder-tree"></i>
|
|
5227
|
-
</a>
|
|
5228
5225
|
<button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
|
|
5229
5226
|
<i class="fa-solid fa-rotate-right"></i>
|
|
5230
5227
|
</button>
|
|
@@ -5291,15 +5288,9 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5291
5288
|
</a>
|
|
5292
5289
|
<%})%>
|
|
5293
5290
|
</div>
|
|
5291
|
+
<div class='active-nested-path hidden' id='active-nested-path'></div>
|
|
5294
5292
|
</div>
|
|
5295
5293
|
<div class='menu-actions'>
|
|
5296
|
-
<a id='workspaces-tab' href="/workspaces" class="btn header-item" data-tippy-content="Workspaces">
|
|
5297
|
-
<div class='tab'>
|
|
5298
|
-
<i class="fa-solid fa-folder-tree menu-action-leading-icon"></i>
|
|
5299
|
-
<div class='display'>Workspaces</div>
|
|
5300
|
-
<div class='flexible'></div>
|
|
5301
|
-
</div>
|
|
5302
|
-
</a>
|
|
5303
5294
|
<% if (type === 'run') { %>
|
|
5304
5295
|
<button type='button' id='ask-ai-tab' class="btn header-item" data-static="ask-ai" data-workspace="<%=name%>" data-workspace-cwd="<%=path%>" data-ask-ai-trigger="true" data-tippy-content="Ask AI">
|
|
5305
5296
|
<div class='tab'>
|
|
@@ -5615,9 +5606,6 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5615
5606
|
<a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
|
|
5616
5607
|
<i class="fa-solid fa-house"></i>
|
|
5617
5608
|
</a>
|
|
5618
|
-
<a class='btn mobile-sheet-action' href="/workspaces" aria-label="Workspaces" title="Workspaces">
|
|
5619
|
-
<i class="fa-solid fa-folder-tree"></i>
|
|
5620
|
-
</a>
|
|
5621
5609
|
<button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
|
|
5622
5610
|
<i class="fa-solid fa-rotate-right"></i>
|
|
5623
5611
|
</button>
|
|
@@ -7197,6 +7185,7 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7197
7185
|
}
|
|
7198
7186
|
|
|
7199
7187
|
if (!target) {
|
|
7188
|
+
activeNestedFocusMenu = null
|
|
7200
7189
|
syncActiveNestedPath()
|
|
7201
7190
|
browserPopoutSurface.hide()
|
|
7202
7191
|
document.querySelector(".container").classList.remove("active")
|
|
@@ -7230,6 +7219,7 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7230
7219
|
el.classList.remove("selected")
|
|
7231
7220
|
})
|
|
7232
7221
|
target.classList.add("selected")
|
|
7222
|
+
activeNestedFocusMenu = null
|
|
7233
7223
|
syncActiveNestedPath({ selectedLink: target })
|
|
7234
7224
|
if (skipPersistedSelection && target.hasAttribute('data-default')) {
|
|
7235
7225
|
ignorePersistedSelection = false
|
|
@@ -8065,7 +8055,162 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8065
8055
|
|
|
8066
8056
|
const getSubmenu = (menu) => getDirectChild(menu, ".submenu")
|
|
8067
8057
|
const getToggle = (menu) => getDirectChild(menu, ".reveal")
|
|
8068
|
-
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
|
+
}
|
|
8069
8214
|
|
|
8070
8215
|
renderSelection()
|
|
8071
8216
|
|
|
@@ -3086,11 +3086,13 @@ const reloadMemory = async () => {
|
|
|
3086
3086
|
</a>
|
|
3087
3087
|
</div>
|
|
3088
3088
|
</div>
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
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
|
+
<% } %>
|
|
3095
3097
|
</body>
|
|
3096
3098
|
</html>
|