@lemonriver/core 0.1.1 → 0.2.0
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/dist/{build-f-fM2ZY4.js → build-Df_xwIpg.js} +1 -1
- package/dist/cli/bin.js +4 -4
- package/dist/{config-DO45GU3e.js → config-BjWCLoMQ.js} +2343 -363
- package/dist/{config-B6JaKJM4.d.ts → config-rMGCkz6i.d.ts} +6 -2
- package/dist/{dev-CqS2xpgE.js → dev-Ctsx9IeO.js} +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -3
- package/dist/locale/index.d.ts +5 -2
- package/dist/locale/index.js +2 -2
- package/dist/{preview-BihgMlEl.js → preview-CJgcqsPk.js} +1 -1
- package/dist/{types-BjW4glip.d.ts → types-8VUyA2bu.d.ts} +133 -5
- package/dist/{update-C_R0ycVC.js → update-BKOA3Z6o.js} +153 -21
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +1 -1
- package/dist/{zh-tw-Ci0jK8eg.js → zh-tw-CeLrYwRE.js} +1178 -25
- package/package.json +13 -6
- package/skills/apply-comments/SKILL.md +10 -6
- package/skills/create-slide/SKILL.md +2 -0
- package/skills/current-slide/SKILL.md +1 -0
- package/skills/slide-authoring/SKILL.md +31 -1
- package/src/agent/prompt.ts +141 -0
- package/src/agent/provider.ts +123 -0
- package/src/agent/types.ts +151 -0
- package/src/app/app.tsx +2 -0
- package/src/app/assets/open-slide.svg +39 -0
- package/src/app/components/agent/agent-dock.tsx +35 -0
- package/src/app/components/agent/agent-markdown.tsx +45 -0
- package/src/app/components/agent/agent-panel.tsx +692 -0
- package/src/app/components/agent/agent-presence.tsx +74 -0
- package/src/app/components/agent/composer.tsx +120 -0
- package/src/app/components/agent/connect-view.tsx +184 -0
- package/src/app/components/agent/history-view.tsx +135 -0
- package/src/app/components/agent/provider-logo.tsx +34 -0
- package/src/app/components/agent/transcript.tsx +609 -0
- package/src/app/components/board/board-canvas.tsx +143 -12
- package/src/app/components/board/board.css +51 -0
- package/src/app/components/board/layout.test.ts +53 -1
- package/src/app/components/board/layout.ts +50 -2
- package/src/app/components/board/page-node.tsx +287 -13
- package/src/app/components/board/use-board-cards.ts +210 -0
- package/src/app/components/board/use-page-order.ts +17 -9
- package/src/app/components/command/slide-command-menu.tsx +10 -0
- package/src/app/components/icon-switcher-indicator.tsx +1 -1
- package/src/app/components/inspector/comment-layer.tsx +1011 -0
- package/src/app/components/inspector/image-crop-dialog.tsx +1 -5
- package/src/app/components/inspector/inspect-overlay.tsx +2 -39
- package/src/app/components/inspector/inspector-panel.tsx +10 -93
- package/src/app/components/inspector/inspector-provider.tsx +121 -47
- package/src/app/components/panel/editor-sidebar.tsx +85 -16
- package/src/app/components/panel/panel-shell.tsx +2 -2
- package/src/app/components/panel/resize-handle.tsx +129 -0
- package/src/app/components/player.tsx +0 -1
- package/src/app/components/preview-step-host.tsx +16 -0
- package/src/app/components/sidebar/sidebar.tsx +2 -2
- package/src/app/components/style-panel/style-panel.tsx +3 -2
- package/src/app/components/thumbnail-rail.tsx +76 -1
- package/src/app/favicon.ico +0 -0
- package/src/app/favicon.svg +39 -0
- package/src/app/index.html +2 -1
- package/src/app/lib/agent/use-agent.ts +543 -0
- package/src/app/lib/inspector/freeze-motion.ts +61 -0
- package/src/app/lib/inspector/use-comments.ts +32 -3
- package/src/app/lib/locale-store.ts +6 -1
- package/src/app/lib/print-ready.ts +9 -6
- package/src/app/lib/use-auto-grow.ts +15 -0
- package/src/app/lib/utils.ts +4 -0
- package/src/app/routes/board.tsx +48 -11
- package/src/app/routes/home.tsx +43 -7
- package/src/app/routes/presenter.tsx +1 -16
- package/src/app/routes/preview.tsx +169 -0
- package/src/app/routes/slide.tsx +221 -173
- package/src/app/styles.css +234 -80
- package/src/editing/placeholder-id.ts +1 -0
- package/src/locale/en.ts +127 -5
- package/src/locale/es.ts +692 -0
- package/src/locale/index.ts +1 -0
- package/src/locale/ja.ts +120 -6
- package/src/locale/types.ts +132 -5
- package/src/locale/zh-cn.ts +117 -5
- package/src/locale/zh-tw.ts +117 -5
- package/src/app/assets/open-slide.png +0 -0
- package/src/app/components/inspector/comment-widget.tsx +0 -119
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { t as Locale } from "./types-
|
|
1
|
+
import { t as Locale } from "./types-8VUyA2bu.js";
|
|
2
2
|
//#region src/config.d.ts
|
|
3
3
|
type LemonRiverBuildConfig = {
|
|
4
4
|
showSlideBrowser?: boolean;
|
|
5
5
|
showSlideUi?: boolean;
|
|
6
6
|
allowHtmlDownload?: boolean;
|
|
7
7
|
};
|
|
8
|
+
type LemonRiverAgentConfig = {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
};
|
|
8
11
|
type LemonRiverConfig = {
|
|
9
12
|
base?: string;
|
|
10
13
|
slidesDir?: string;
|
|
@@ -19,8 +22,9 @@ type LemonRiverConfig = {
|
|
|
19
22
|
*/
|
|
20
23
|
locale?: Locale;
|
|
21
24
|
build?: LemonRiverBuildConfig;
|
|
25
|
+
agent?: LemonRiverAgentConfig;
|
|
22
26
|
};
|
|
23
27
|
/** @deprecated Renamed to {@link LemonRiverConfig}; kept for config files written before the rename. */
|
|
24
28
|
type OpenSlideConfig = LemonRiverConfig;
|
|
25
29
|
//#endregion
|
|
26
|
-
export {
|
|
30
|
+
export { OpenSlideConfig as i, LemonRiverBuildConfig as n, LemonRiverConfig as r, LemonRiverAgentConfig as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { U as PKG_NAMES } from "./update-BKOA3Z6o.js";
|
|
2
2
|
import { a as printUrls, i as printShortcutsHint, n as formatError, o as shortcutsEnabled, r as printHeader, s as startupDuration, t as createCliLogger } from "./cli/bin.js";
|
|
3
|
-
import { n as DEV_SUPERVISED_ENV, t as createViteConfig } from "./config-
|
|
3
|
+
import { n as DEV_SUPERVISED_ENV, t as createViteConfig } from "./config-BjWCLoMQ.js";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import { fork } from "node:child_process";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Plural, t as Locale } from "./types-
|
|
2
|
-
import { n as
|
|
1
|
+
import { n as Plural, t as Locale } from "./types-8VUyA2bu.js";
|
|
2
|
+
import { i as OpenSlideConfig, n as LemonRiverBuildConfig, r as LemonRiverConfig, t as LemonRiverAgentConfig } from "./config-rMGCkz6i.js";
|
|
3
3
|
import { CSSProperties, ComponentType, HTMLAttributes, PropsWithChildren, ReactNode } from "react";
|
|
4
4
|
//#region src/app/components/image-placeholder.d.ts
|
|
5
5
|
type ImagePlaceholderProps = {
|
|
@@ -103,4 +103,4 @@ type InternalStepProps = StepProps & {
|
|
|
103
103
|
};
|
|
104
104
|
declare function Step({ children, duration, _revealed }: InternalStepProps): import("react").JSX.Element;
|
|
105
105
|
//#endregion
|
|
106
|
-
export { CANVAS_HEIGHT, CANVAS_WIDTH, type DesignFonts, type DesignPalette, type DesignSystem, type DesignTypeScale, ImagePlaceholder, type ImagePlaceholderProps, type LemonRiverBuildConfig, type LemonRiverConfig, type Locale, MorphElement, type MorphElementProps, type MorphTransition, type OpenSlideConfig, type Page, type Plural, type SlideMeta, type SlideModule, type SlideTransition, Step, type StepProps, Steps, type StepsProps, type TransitionPhase, cssVarsToString, defaultDesign, designToCssVars, useIsActivePage, useSlidePageNumber };
|
|
106
|
+
export { CANVAS_HEIGHT, CANVAS_WIDTH, type DesignFonts, type DesignPalette, type DesignSystem, type DesignTypeScale, ImagePlaceholder, type ImagePlaceholderProps, type LemonRiverAgentConfig, type LemonRiverBuildConfig, type LemonRiverConfig, type Locale, MorphElement, type MorphElementProps, type MorphTransition, type OpenSlideConfig, type Page, type Plural, type SlideMeta, type SlideModule, type SlideTransition, Step, type StepProps, Steps, type StepsProps, type TransitionPhase, cssVarsToString, defaultDesign, designToCssVars, useIsActivePage, useSlidePageNumber };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as en, i as es, n as zhCN, r as ja, t as zhTW } from "./zh-tw-CeLrYwRE.js";
|
|
2
2
|
import { n as defaultDesign, r as designToCssVars, t as cssVarsToString } from "./design-Cpqx7SJs.js";
|
|
3
3
|
import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { toast } from "sonner";
|
|
@@ -85,12 +85,13 @@ const LOCALES = {
|
|
|
85
85
|
en,
|
|
86
86
|
"zh-TW": zhTW,
|
|
87
87
|
"zh-CN": zhCN,
|
|
88
|
-
ja
|
|
88
|
+
ja,
|
|
89
|
+
es
|
|
89
90
|
};
|
|
90
91
|
const STORAGE_KEY = "open-slide:locale";
|
|
91
92
|
const configLocale = config.locale;
|
|
92
93
|
function isLocaleId(value) {
|
|
93
|
-
return value === "en" || value === "zh-TW" || value === "zh-CN" || value === "ja";
|
|
94
|
+
return value === "en" || value === "zh-TW" || value === "zh-CN" || value === "ja" || value === "es";
|
|
94
95
|
}
|
|
95
96
|
function readStored() {
|
|
96
97
|
try {
|
package/dist/locale/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { n as Plural, t as Locale } from "../types-
|
|
1
|
+
import { n as Plural, t as Locale } from "../types-8VUyA2bu.js";
|
|
2
2
|
//#region src/locale/en.d.ts
|
|
3
3
|
declare const en: Locale;
|
|
4
4
|
//#endregion
|
|
5
|
+
//#region src/locale/es.d.ts
|
|
6
|
+
declare const es: Locale;
|
|
7
|
+
//#endregion
|
|
5
8
|
//#region src/locale/format.d.ts
|
|
6
9
|
declare function format(template: string, vars: Record<string, string | number>): string;
|
|
7
10
|
declare function plural(count: number, forms: Plural): string;
|
|
@@ -15,4 +18,4 @@ declare const zhCN: Locale;
|
|
|
15
18
|
//#region src/locale/zh-tw.d.ts
|
|
16
19
|
declare const zhTW: Locale;
|
|
17
20
|
//#endregion
|
|
18
|
-
export { type Locale, type Plural, en, format, ja, plural, zhCN, zhTW };
|
|
21
|
+
export { type Locale, type Plural, en, es, format, ja, plural, zhCN, zhTW };
|
package/dist/locale/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as en, i as es, n as zhCN, r as ja, t as zhTW } from "../zh-tw-CeLrYwRE.js";
|
|
2
2
|
//#region src/locale/format.ts
|
|
3
3
|
function format(template, vars) {
|
|
4
4
|
return template.replace(/\{(\w+)\}/g, (m, key) => {
|
|
@@ -10,4 +10,4 @@ function plural(count, forms) {
|
|
|
10
10
|
return count === 1 ? forms.one : forms.other;
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
|
-
export { en, format, ja, plural, zhCN, zhTW };
|
|
13
|
+
export { en, es, format, ja, plural, zhCN, zhTW };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as printUrls, i as printShortcutsHint, o as shortcutsEnabled, r as printHeader, s as startupDuration, t as createCliLogger } from "./cli/bin.js";
|
|
2
|
-
import { t as createViteConfig } from "./config-
|
|
2
|
+
import { t as createViteConfig } from "./config-BjWCLoMQ.js";
|
|
3
3
|
import { mergeConfig, preview as preview$1 } from "vite";
|
|
4
4
|
//#region src/cli/preview.ts
|
|
5
5
|
async function preview(opts = {}) {
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
//#region src/agent/types.d.ts
|
|
2
|
+
declare const AGENT_EFFORTS: readonly ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
3
|
+
type AgentEffort = (typeof AGENT_EFFORTS)[number];
|
|
4
|
+
//#endregion
|
|
1
5
|
//#region src/locale/types.d.ts
|
|
2
6
|
type Plural = {
|
|
3
7
|
one: string;
|
|
4
8
|
other: string;
|
|
5
9
|
};
|
|
6
10
|
type Locale = {
|
|
7
|
-
id: 'en' | 'zh-TW' | 'zh-CN' | 'ja';
|
|
11
|
+
id: 'en' | 'zh-TW' | 'zh-CN' | 'ja' | 'es';
|
|
8
12
|
common: {
|
|
9
13
|
cancel: string;
|
|
10
14
|
save: string;
|
|
@@ -99,6 +103,7 @@ type Locale = {
|
|
|
99
103
|
pickIcon: string;
|
|
100
104
|
};
|
|
101
105
|
slide: {
|
|
106
|
+
resizeSidePanel: string;
|
|
102
107
|
home: string;
|
|
103
108
|
backToHome: string;
|
|
104
109
|
agentConnected: string;
|
|
@@ -283,20 +288,25 @@ type Locale = {
|
|
|
283
288
|
cropFitCover: string;
|
|
284
289
|
cropFitContain: string;
|
|
285
290
|
cropApply: string;
|
|
286
|
-
|
|
291
|
+
commentMode: string;
|
|
287
292
|
commentPlaceholder: string;
|
|
288
|
-
|
|
289
|
-
addComment: string;
|
|
293
|
+
commentPost: string;
|
|
290
294
|
/** templates: "{count} unsaved change" / "{count} unsaved changes" */
|
|
291
295
|
unsavedChanges: Plural;
|
|
292
296
|
/** templates: "{count} comment" / "{count} comments" */
|
|
293
297
|
commentsCount: Plural;
|
|
294
298
|
/** template: "line {n}" */
|
|
295
299
|
commentLineLabel: string;
|
|
296
|
-
|
|
300
|
+
commentRegionLabel: string;
|
|
301
|
+
commentEmptyHint: string;
|
|
297
302
|
commentsApplyHintPrefix: string;
|
|
298
303
|
commentsApplyHintSuffix: string;
|
|
299
304
|
commentDeleteAria: string;
|
|
305
|
+
/** Prefix for the toast shown when a comment edit fails to write to disk. */
|
|
306
|
+
commentUpdateFailed: string;
|
|
307
|
+
/** Prefix for the toast shown when a comment fails to write to disk. */
|
|
308
|
+
commentAddFailed: string;
|
|
309
|
+
commentRegionNoTarget: string;
|
|
300
310
|
/** Prefix for the toast shown when one or more buffered edits fail to write to disk. */
|
|
301
311
|
saveFailed: string;
|
|
302
312
|
decreaseFontSize: string;
|
|
@@ -487,6 +497,19 @@ type Locale = {
|
|
|
487
497
|
/** template: "Added a blank page at {n}" */
|
|
488
498
|
toastInserted: string;
|
|
489
499
|
insertFailed: string;
|
|
500
|
+
cardTitlePlaceholder: string;
|
|
501
|
+
renameCard: string;
|
|
502
|
+
status: string;
|
|
503
|
+
statusNone: string;
|
|
504
|
+
statusTodo: string;
|
|
505
|
+
statusDoing: string;
|
|
506
|
+
statusReview: string;
|
|
507
|
+
statusDone: string;
|
|
508
|
+
memoPlaceholder: string;
|
|
509
|
+
linkHandle: string;
|
|
510
|
+
showLinks: string;
|
|
511
|
+
hideLinks: string;
|
|
512
|
+
removeLink: string;
|
|
490
513
|
};
|
|
491
514
|
pdfToast: {
|
|
492
515
|
title: string;
|
|
@@ -577,6 +600,111 @@ type Locale = {
|
|
|
577
600
|
expandPromptAria: string;
|
|
578
601
|
collapsePromptAria: string;
|
|
579
602
|
};
|
|
603
|
+
agent: {
|
|
604
|
+
title: string;
|
|
605
|
+
beta: string;
|
|
606
|
+
betaTitle: string;
|
|
607
|
+
betaHint: string;
|
|
608
|
+
open: string;
|
|
609
|
+
openTitle: string;
|
|
610
|
+
close: string;
|
|
611
|
+
newSession: string;
|
|
612
|
+
sessions: string;
|
|
613
|
+
noSessions: string;
|
|
614
|
+
deleteSession: string;
|
|
615
|
+
historyThisDeck: string;
|
|
616
|
+
historyOtherDecks: string;
|
|
617
|
+
historyEmptyHint: string;
|
|
618
|
+
sessionRunning: string;
|
|
619
|
+
/** template: "Ask {provider} to create or edit slides…" */
|
|
620
|
+
composerPlaceholder: string;
|
|
621
|
+
send: string;
|
|
622
|
+
stop: string;
|
|
623
|
+
working: string;
|
|
624
|
+
/** template: "Page {n}" */
|
|
625
|
+
contextPage: string;
|
|
626
|
+
contextSelection: string;
|
|
627
|
+
/** plural, template: "{count} comments" */
|
|
628
|
+
pendingComments: Plural;
|
|
629
|
+
applyComments: string;
|
|
630
|
+
/** template: "Apply with {provider}" */
|
|
631
|
+
applyCommentsWith: string;
|
|
632
|
+
createDeck: string;
|
|
633
|
+
/** template: "Create a deck with {provider}" */
|
|
634
|
+
createDeckWith: string;
|
|
635
|
+
quickCreate: string;
|
|
636
|
+
quickCreateHint: string;
|
|
637
|
+
quickApply: string;
|
|
638
|
+
quickApplyHint: string;
|
|
639
|
+
quickTheme: string;
|
|
640
|
+
quickThemeHint: string;
|
|
641
|
+
quickEdit: string;
|
|
642
|
+
quickEditHint: string;
|
|
643
|
+
emptyTitle: string;
|
|
644
|
+
emptyHint: string;
|
|
645
|
+
questionSubmit: string;
|
|
646
|
+
questionOther: string;
|
|
647
|
+
questionOtherPlaceholder: string;
|
|
648
|
+
questionCancelled: string;
|
|
649
|
+
permissionTitle: string;
|
|
650
|
+
allow: string;
|
|
651
|
+
deny: string;
|
|
652
|
+
allowed: string;
|
|
653
|
+
denied: string;
|
|
654
|
+
autoApprove: string;
|
|
655
|
+
autoApproveHint: string;
|
|
656
|
+
resultDone: string;
|
|
657
|
+
resultStopped: string;
|
|
658
|
+
/** template: "{seconds}s" */
|
|
659
|
+
resultSeconds: string;
|
|
660
|
+
errorEyebrow: string;
|
|
661
|
+
statusLoading: string;
|
|
662
|
+
disabled: string;
|
|
663
|
+
connectTitle: string;
|
|
664
|
+
connectDescription: string;
|
|
665
|
+
connect: string;
|
|
666
|
+
connecting: string;
|
|
667
|
+
connected: string;
|
|
668
|
+
/** template: "Adds {pkg} to this workspace with {pm}." */
|
|
669
|
+
connectInstallHint: string;
|
|
670
|
+
/** template: "CLI found · v{version}" */
|
|
671
|
+
cliFound: string;
|
|
672
|
+
cliFoundNoVersion: string;
|
|
673
|
+
cliMissing: string;
|
|
674
|
+
/** template: "Install the {name} CLI and sign in once; the panel reuses its login." */
|
|
675
|
+
cliHint: string;
|
|
676
|
+
needCliTitle: string;
|
|
677
|
+
needCliDescription: string;
|
|
678
|
+
checkAgain: string;
|
|
679
|
+
retry: string;
|
|
680
|
+
/** template: "{name} connected" */
|
|
681
|
+
toastConnected: string;
|
|
682
|
+
/** template: "Could not install {pkg}" */
|
|
683
|
+
toastConnectFailed: string;
|
|
684
|
+
manageConnections: string;
|
|
685
|
+
backToChat: string;
|
|
686
|
+
toastSendFailed: string;
|
|
687
|
+
newDeckTitle: string;
|
|
688
|
+
newDeckHint: string;
|
|
689
|
+
newDeckPlaceholder: string;
|
|
690
|
+
toastCreateDeckFailed: string;
|
|
691
|
+
steps: Plural;
|
|
692
|
+
questionSkip: string;
|
|
693
|
+
copyMessage: string;
|
|
694
|
+
copied: string;
|
|
695
|
+
editMessage: string;
|
|
696
|
+
cancelEdit: string;
|
|
697
|
+
sendEdit: string;
|
|
698
|
+
editHint: string;
|
|
699
|
+
modelDefault: string;
|
|
700
|
+
reasoning: string;
|
|
701
|
+
effortAuto: string;
|
|
702
|
+
efforts: Record<AgentEffort, string>;
|
|
703
|
+
/** template: "{provider} is editing" */
|
|
704
|
+
presenceEditing: string;
|
|
705
|
+
presenceThinking: string;
|
|
706
|
+
presenceWaiting: string;
|
|
707
|
+
};
|
|
580
708
|
};
|
|
581
709
|
//#endregion
|
|
582
710
|
export { Plural as n, Locale as t };
|
|
@@ -76,6 +76,10 @@ function validateMutationRequest(req, opts = {}) {
|
|
|
76
76
|
};
|
|
77
77
|
return { ok: true };
|
|
78
78
|
}
|
|
79
|
+
function isLoopbackRequest(req) {
|
|
80
|
+
const address = req.socket.remoteAddress ?? "";
|
|
81
|
+
return address === "::1" || address.startsWith("127.") || address.startsWith("::ffff:127.");
|
|
82
|
+
}
|
|
79
83
|
//#endregion
|
|
80
84
|
//#region src/workspace-specifier.ts
|
|
81
85
|
function readDeps(userCwd) {
|
|
@@ -122,6 +126,21 @@ function readFrameworkDependency(userCwd) {
|
|
|
122
126
|
//#endregion
|
|
123
127
|
//#region src/editing/slide-ops.ts
|
|
124
128
|
const SLIDE_ID_RE = /^[a-z0-9_-]+$/i;
|
|
129
|
+
/**
|
|
130
|
+
* True when a directory under root already uses this id, including a
|
|
131
|
+
* different case. ext4 keeps `Cover` and `cover` as two folders; macOS
|
|
132
|
+
* and Windows usually collapse them. Listing names catches both.
|
|
133
|
+
*/
|
|
134
|
+
async function slideIdTaken(root, slideId) {
|
|
135
|
+
let names;
|
|
136
|
+
try {
|
|
137
|
+
names = await fs.readdir(root);
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const want = slideId.toLowerCase();
|
|
142
|
+
return names.some((name) => name.toLowerCase() === want);
|
|
143
|
+
}
|
|
125
144
|
function validateSlideName(v) {
|
|
126
145
|
if (typeof v !== "string") return null;
|
|
127
146
|
const trimmed = v.trim();
|
|
@@ -226,30 +245,25 @@ async function duplicateSlideDir(slidesRoot, slideId, desiredId) {
|
|
|
226
245
|
error: "invalid newId"
|
|
227
246
|
};
|
|
228
247
|
newId = desiredId;
|
|
229
|
-
|
|
230
|
-
if (!dstDir.startsWith(root + path.sep)) return {
|
|
248
|
+
if (!path.resolve(root, newId).startsWith(root + path.sep)) return {
|
|
231
249
|
ok: false,
|
|
232
250
|
status: 400,
|
|
233
251
|
error: "invalid newId"
|
|
234
252
|
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
error: "slide already exists"
|
|
241
|
-
};
|
|
242
|
-
} catch {}
|
|
253
|
+
if (await slideIdTaken(root, newId)) return {
|
|
254
|
+
ok: false,
|
|
255
|
+
status: 409,
|
|
256
|
+
error: "slide already exists"
|
|
257
|
+
};
|
|
243
258
|
} else {
|
|
244
259
|
let suffix = 1;
|
|
245
260
|
while (true) {
|
|
246
261
|
newId = suffix === 1 ? `${slideId}-copy` : `${slideId}-copy-${suffix}`;
|
|
247
|
-
|
|
248
|
-
await fs.access(path.resolve(root, newId));
|
|
262
|
+
if (await slideIdTaken(root, newId)) {
|
|
249
263
|
suffix++;
|
|
250
|
-
|
|
251
|
-
break;
|
|
264
|
+
continue;
|
|
252
265
|
}
|
|
266
|
+
break;
|
|
253
267
|
}
|
|
254
268
|
}
|
|
255
269
|
const dstDir = path.resolve(root, newId);
|
|
@@ -306,6 +320,107 @@ async function duplicateSlideDir(slidesRoot, slideId, desiredId) {
|
|
|
306
320
|
};
|
|
307
321
|
}
|
|
308
322
|
}
|
|
323
|
+
const BLANK_SLIDE_TITLE = "Untitled";
|
|
324
|
+
function blankSlideSource(createdAt, specifier) {
|
|
325
|
+
const q = (value) => `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
326
|
+
return `import type { Page, SlideMeta } from '${specifier}';
|
|
327
|
+
|
|
328
|
+
export const meta: SlideMeta = { title: ${q(BLANK_SLIDE_TITLE)}, createdAt: ${q(createdAt)} };
|
|
329
|
+
|
|
330
|
+
const Blank: Page = () => <div style={{ width: '100%', height: '100%', background: '#ffffff' }} />;
|
|
331
|
+
|
|
332
|
+
export default [Blank] satisfies Page[];
|
|
333
|
+
`;
|
|
334
|
+
}
|
|
335
|
+
async function createBlankSlideDir(slidesRoot, specifier = PKG_NAME) {
|
|
336
|
+
const root = path.resolve(slidesRoot);
|
|
337
|
+
await fs.mkdir(root, { recursive: true });
|
|
338
|
+
for (let suffix = 1; suffix < 1e3; suffix++) {
|
|
339
|
+
const slideId = suffix === 1 ? "untitled" : `untitled-${suffix}`;
|
|
340
|
+
if (await slideIdTaken(root, slideId)) continue;
|
|
341
|
+
const dir = path.join(root, slideId);
|
|
342
|
+
try {
|
|
343
|
+
await fs.mkdir(dir);
|
|
344
|
+
} catch (err) {
|
|
345
|
+
if (err.code === "EEXIST") continue;
|
|
346
|
+
return {
|
|
347
|
+
ok: false,
|
|
348
|
+
status: 500,
|
|
349
|
+
error: String(err.message ?? err)
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const file = path.join(dir, "index.tsx");
|
|
353
|
+
await fs.writeFile(file, blankSlideSource((/* @__PURE__ */ new Date()).toISOString(), specifier), "utf8");
|
|
354
|
+
return {
|
|
355
|
+
ok: true,
|
|
356
|
+
slideId,
|
|
357
|
+
file
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
return {
|
|
361
|
+
ok: false,
|
|
362
|
+
status: 409,
|
|
363
|
+
error: "no free slide id"
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function slugifyTitle(title) {
|
|
367
|
+
return title.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+/, "").slice(0, 48).replace(/-+$/, "");
|
|
368
|
+
}
|
|
369
|
+
async function renameSlideDir(slidesRoot, slideId, desiredId) {
|
|
370
|
+
if (!SLIDE_ID_RE.test(slideId) || !SLIDE_ID_RE.test(desiredId)) return {
|
|
371
|
+
ok: false,
|
|
372
|
+
status: 400,
|
|
373
|
+
error: "invalid slideId"
|
|
374
|
+
};
|
|
375
|
+
const root = path.resolve(slidesRoot);
|
|
376
|
+
const from = path.resolve(root, slideId);
|
|
377
|
+
if (!from.startsWith(root + path.sep)) return {
|
|
378
|
+
ok: false,
|
|
379
|
+
status: 400,
|
|
380
|
+
error: "invalid slideId"
|
|
381
|
+
};
|
|
382
|
+
try {
|
|
383
|
+
await fs.access(path.join(from, "index.tsx"));
|
|
384
|
+
} catch {
|
|
385
|
+
return {
|
|
386
|
+
ok: false,
|
|
387
|
+
status: 404,
|
|
388
|
+
error: "slide not found"
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
for (let suffix = 1; suffix < 1e3; suffix++) {
|
|
392
|
+
const candidate = suffix === 1 ? desiredId : `${desiredId}-${suffix}`;
|
|
393
|
+
if (candidate === slideId) return {
|
|
394
|
+
ok: false,
|
|
395
|
+
status: 409,
|
|
396
|
+
error: "slide id unchanged"
|
|
397
|
+
};
|
|
398
|
+
if (await slideIdTaken(root, candidate)) continue;
|
|
399
|
+
const to = path.join(root, candidate);
|
|
400
|
+
try {
|
|
401
|
+
await fs.rename(from, to);
|
|
402
|
+
} catch (err) {
|
|
403
|
+
const code = err.code;
|
|
404
|
+
if (code === "EEXIST" || code === "ENOTEMPTY") continue;
|
|
405
|
+
return {
|
|
406
|
+
ok: false,
|
|
407
|
+
status: 500,
|
|
408
|
+
error: String(err.message ?? err)
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
return {
|
|
412
|
+
ok: true,
|
|
413
|
+
slideId: candidate,
|
|
414
|
+
from,
|
|
415
|
+
to
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
ok: false,
|
|
420
|
+
status: 409,
|
|
421
|
+
error: "no free slide id"
|
|
422
|
+
};
|
|
423
|
+
}
|
|
309
424
|
function resolveSlideEntry(slidesRoot, slideId) {
|
|
310
425
|
if (!SLIDE_ID_RE.test(slideId)) return null;
|
|
311
426
|
const dir = path.resolve(slidesRoot, slideId);
|
|
@@ -798,13 +913,29 @@ function makeContext(opts) {
|
|
|
798
913
|
globalAssetsRoot: path.resolve(userCwd, assetsDir),
|
|
799
914
|
manifestPath: foldersManifestPath(slidesRoot),
|
|
800
915
|
coreVersion: opts.coreVersion,
|
|
801
|
-
frameworkSpecifier: declaredFrameworkSpecifier(userCwd)
|
|
916
|
+
frameworkSpecifier: declaredFrameworkSpecifier(userCwd),
|
|
917
|
+
agentEnabled: opts.agentEnabled
|
|
802
918
|
};
|
|
803
919
|
}
|
|
804
|
-
|
|
920
|
+
var BodyTooLargeError = class extends Error {
|
|
921
|
+
constructor() {
|
|
922
|
+
super("request body too large");
|
|
923
|
+
this.name = "BodyTooLargeError";
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
async function readBody(req, limit = Number.POSITIVE_INFINITY) {
|
|
805
927
|
return await new Promise((resolve, reject) => {
|
|
806
928
|
const chunks = [];
|
|
807
|
-
|
|
929
|
+
let size = 0;
|
|
930
|
+
req.on("data", (c) => {
|
|
931
|
+
size += c.length;
|
|
932
|
+
if (size > limit) {
|
|
933
|
+
req.destroy();
|
|
934
|
+
reject(new BodyTooLargeError());
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
chunks.push(c);
|
|
938
|
+
});
|
|
808
939
|
req.on("end", () => {
|
|
809
940
|
const raw = Buffer.concat(chunks).toString("utf8");
|
|
810
941
|
if (!raw) return resolve({});
|
|
@@ -944,7 +1075,7 @@ async function localSyncCommand(cwd) {
|
|
|
944
1075
|
function formatCommand(spec) {
|
|
945
1076
|
return [spec.cmd, ...spec.args].join(" ");
|
|
946
1077
|
}
|
|
947
|
-
async function runCommand(spec, cwd) {
|
|
1078
|
+
async function runCommand(spec, cwd, timeoutMs = COMMAND_TIMEOUT_MS) {
|
|
948
1079
|
await new Promise((resolve, reject) => {
|
|
949
1080
|
const child = spawn(spec.cmd, spec.args, {
|
|
950
1081
|
cwd,
|
|
@@ -954,13 +1085,14 @@ async function runCommand(spec, cwd) {
|
|
|
954
1085
|
"ignore",
|
|
955
1086
|
"ignore",
|
|
956
1087
|
"pipe"
|
|
957
|
-
]
|
|
1088
|
+
],
|
|
1089
|
+
windowsHide: true
|
|
958
1090
|
});
|
|
959
1091
|
let stderr = "";
|
|
960
1092
|
const timer = setTimeout(() => {
|
|
961
1093
|
child.kill();
|
|
962
1094
|
reject(/* @__PURE__ */ new Error(`${formatCommand(spec)} timed out`));
|
|
963
|
-
},
|
|
1095
|
+
}, timeoutMs);
|
|
964
1096
|
child.stderr.on("data", (chunk) => {
|
|
965
1097
|
stderr += chunk.toString("utf8");
|
|
966
1098
|
if (stderr.length > 2e3) stderr = stderr.slice(-2e3);
|
|
@@ -1023,4 +1155,4 @@ function registerUpdateRoutes(server, ctx) {
|
|
|
1023
1155
|
});
|
|
1024
1156
|
}
|
|
1025
1157
|
//#endregion
|
|
1026
|
-
export {
|
|
1158
|
+
export { renameSlideDir as A, validateMutationRequest as B, duplicatePageInDefaultExportInSource as C, readMetaTitleInSource as D, insertNotesElementInSource as E, slugifyTitle as F, CONFIG_FILES as H, updateMetaTitleInSource as I, validateSlideName as L, reorderNotesArrayInSource as M, resolveSlideEntry as N, removeNotesElementInSource as O, rmSlideDir as P, declaredFrameworkSpecifier as R, duplicateNotesElementInSource as S, insertBlankPageInDefaultExportInSource as T, PKG_NAMES as U, BIN_NAME as V, isFrameworkSpecifier as W, writeManifest as _, json as a, SLIDE_ID_RE as b, readSlideSource as c, foldersManifestPath as d, newFolderId as f, validateReorder as g, validateName as h, BodyTooLargeError as i, reorderDefaultExportPagesInSource as j, removePageFromDefaultExportInSource as k, resolveSlideEntryPath as l, validateIcon as m, registerUpdateRoutes as n, makeContext as o, readManifest as p, runCommand as r, readBody as s, detectPackageManager as t, FOLDER_ID_RE as u, shortId as v, duplicateSlideDir as w, createBlankSlideDir as x, BLANK_SLIDE_TITLE as y, isLoopbackRequest as z };
|
package/dist/vite/index.d.ts
CHANGED
package/dist/vite/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createViteConfig } from "../config-
|
|
1
|
+
import { t as createViteConfig } from "../config-BjWCLoMQ.js";
|
|
2
2
|
export { createViteConfig };
|