@openforge-app/plugin-sdk 0.2.9 → 0.2.10
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/backend.d.ts +2 -2
- package/dist/collapsibleSectionState.js +30 -12
- package/dist/domain.d.ts +1 -0
- package/dist/domain.js +2 -1
- package/dist/frontend.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/manifest.d.ts +1 -0
- package/dist/manifest.js +10 -4
- package/dist/markdown.d.ts +9 -0
- package/dist/markdown.js +57 -1
- package/dist/openforgePackageMetadataSchema.json +2 -11
- package/dist/publicEntrypoints.d.mts +26 -0
- package/dist/publicEntrypoints.mjs +103 -0
- package/dist/publicUiExports.mjs +2 -0
- package/dist/taskBrowserDevToolsShortcuts.d.ts +12 -0
- package/dist/taskBrowserDevToolsShortcuts.js +20 -0
- package/dist/testing/commonApiFake.js +206 -6
- package/dist/testing/contracts.d.ts +15 -3
- package/dist/testing/frontendContributionFake.d.ts +2 -3
- package/dist/testing/frontendContributionFake.js +0 -32
- package/dist/testing/support.d.ts +5 -2
- package/dist/testing/support.js +12 -1
- package/dist/types.d.ts +80 -19
- package/dist/types.js +1 -1
- package/dist/ui/Modal.svelte +33 -3
- package/dist/ui/PluginPageHeader.svelte +11 -4
- package/dist/ui/PluginPageShell.svelte +20 -0
- package/dist/ui/ProjectFileTree.svelte +192 -0
- package/dist/vite.js +7 -17
- package/package.json +9 -2
package/dist/types.js
CHANGED
|
@@ -34,7 +34,6 @@ const OPENFORGE_PLUGIN_CAPABILITY_TYPE_MEMBERS = [
|
|
|
34
34
|
'config',
|
|
35
35
|
'projectConfig',
|
|
36
36
|
'browserSurfaces',
|
|
37
|
-
'taskLinks',
|
|
38
37
|
'appEnablement',
|
|
39
38
|
'customSidebarNavigation',
|
|
40
39
|
'reviewUI',
|
|
@@ -71,6 +70,7 @@ export class TaskFollowUpError extends Error {
|
|
|
71
70
|
this.code = code;
|
|
72
71
|
}
|
|
73
72
|
}
|
|
73
|
+
export const MAX_AGENT_SESSION_PAGE_SIZE = 250;
|
|
74
74
|
export function makePluginViewKey(pluginId, viewId) {
|
|
75
75
|
return `plugin:${pluginId}:${viewId}`;
|
|
76
76
|
}
|
package/dist/ui/Modal.svelte
CHANGED
|
@@ -4,12 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
export type ModalInitialFocus = HTMLElement | string | (() => HTMLElement | null | undefined) | null | undefined
|
|
6
6
|
|
|
7
|
+
type ModalAccessibleName =
|
|
8
|
+
| { ariaLabel: string; ariaLabelledby?: never }
|
|
9
|
+
| { ariaLabel?: never; ariaLabelledby: string }
|
|
10
|
+
|
|
7
11
|
interface Props {
|
|
8
12
|
onClose: () => void
|
|
9
13
|
maxWidth?: string
|
|
10
14
|
overflowVisible?: boolean
|
|
11
15
|
initialFocus?: ModalInitialFocus
|
|
12
|
-
ariaLabel?: string
|
|
13
16
|
showHeader?: boolean
|
|
14
17
|
closeLabel?: string
|
|
15
18
|
closeDisabled?: boolean
|
|
@@ -21,7 +24,34 @@
|
|
|
21
24
|
children: Snippet
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
let { onClose, maxWidth = '500px', overflowVisible = false, initialFocus, ariaLabel, showHeader = true, closeLabel = 'Close dialog', closeDisabled = false, onKeydown, testId, modalClass = '', boxClass = '', header, children }: Props = $props()
|
|
27
|
+
let { onClose, maxWidth = '500px', overflowVisible = false, initialFocus, ariaLabel, ariaLabelledby, showHeader = true, closeLabel = 'Close dialog', closeDisabled = false, onKeydown, testId, modalClass = '', boxClass = '', header, children }: Props & ModalAccessibleName = $props()
|
|
28
|
+
let accessibleNameAttributes = $derived.by(() => {
|
|
29
|
+
const hasAriaLabel = Boolean(ariaLabel?.trim())
|
|
30
|
+
const hasAriaLabelledby = Boolean(ariaLabelledby?.trim())
|
|
31
|
+
|
|
32
|
+
if (hasAriaLabel === hasAriaLabelledby) {
|
|
33
|
+
throw new Error('Modal requires exactly one non-empty accessible name prop: ariaLabel or ariaLabelledby')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
ariaLabel: hasAriaLabel ? ariaLabel : undefined,
|
|
38
|
+
ariaLabelledby: hasAriaLabelledby ? ariaLabelledby : undefined,
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
$effect(() => {
|
|
43
|
+
const idReferences = accessibleNameAttributes.ariaLabelledby?.split(/\s+/)
|
|
44
|
+
if (!idReferences) return
|
|
45
|
+
|
|
46
|
+
const hasNamingText = idReferences.some((id) => {
|
|
47
|
+
const labelledElement = document.getElementById(id)
|
|
48
|
+
return Boolean(labelledElement?.textContent?.trim() || labelledElement?.getAttribute('aria-label')?.trim())
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
if (!hasNamingText) {
|
|
52
|
+
throw new Error('Modal ariaLabelledby must reference at least one element with naming text')
|
|
53
|
+
}
|
|
54
|
+
})
|
|
25
55
|
|
|
26
56
|
let modalElement: HTMLDivElement | null = $state(null)
|
|
27
57
|
let hasAppliedInitialFocus = false
|
|
@@ -142,7 +172,7 @@
|
|
|
142
172
|
}
|
|
143
173
|
</script>
|
|
144
174
|
|
|
145
|
-
<div bind:this={modalElement} class="modal modal-open {modalClass}" data-testid={testId} onclick={handleOverlayClick} onkeydown={handleKeydown} role="dialog" aria-modal="true" aria-label={ariaLabel} tabindex="-1">
|
|
175
|
+
<div bind:this={modalElement} class="modal modal-open {modalClass}" data-testid={testId} onclick={handleOverlayClick} onkeydown={handleKeydown} role="dialog" aria-modal="true" aria-label={accessibleNameAttributes.ariaLabel} aria-labelledby={accessibleNameAttributes.ariaLabelledby} tabindex="-1">
|
|
146
176
|
<div class="modal-box bg-base-100 shadow-xl p-0 flex flex-col max-h-[90vh] {overflowVisible ? 'overflow-visible' : ''} {boxClass}" style="max-width: {maxWidth}">
|
|
147
177
|
{#if showHeader}
|
|
148
178
|
<div class="flex items-center justify-between px-5 py-4 border-b border-base-300">
|
|
@@ -5,17 +5,24 @@
|
|
|
5
5
|
title: string
|
|
6
6
|
subtitle?: string | null
|
|
7
7
|
surface?: 'default' | 'subtle'
|
|
8
|
+
headingLevel?: 'h1' | 'h2'
|
|
8
9
|
actions?: Snippet
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
let {
|
|
12
|
+
let {
|
|
13
|
+
title,
|
|
14
|
+
subtitle = null,
|
|
15
|
+
surface = 'default',
|
|
16
|
+
headingLevel = 'h1',
|
|
17
|
+
actions,
|
|
18
|
+
}: Props = $props()
|
|
12
19
|
</script>
|
|
13
20
|
|
|
14
|
-
<header class="flex items-center justify-between gap-4 border-b border-base-300 px-
|
|
21
|
+
<header class="flex min-h-13 shrink-0 flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-base-300 px-4 py-2 sm:px-6 {surface === 'default' ? 'bg-base-100' : 'bg-base-200'}">
|
|
15
22
|
<div class="min-w-0">
|
|
16
|
-
<
|
|
23
|
+
<svelte:element this={headingLevel} class="m-0 truncate text-base font-semibold leading-5 tracking-[-0.01em] text-base-content">{title}</svelte:element>
|
|
17
24
|
{#if subtitle}
|
|
18
|
-
<p class="text-[13px]
|
|
25
|
+
<p class="m-0 mt-0.5 truncate text-[13px] leading-5 text-base-content/60">{subtitle}</p>
|
|
19
26
|
{/if}
|
|
20
27
|
</div>
|
|
21
28
|
{#if actions}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
header: Snippet
|
|
6
|
+
children: Snippet
|
|
7
|
+
class?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { header, children, class: className = '' }: Props = $props()
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div class="flex h-full min-h-0 flex-col overflow-hidden bg-base-100 text-base-content {className}">
|
|
14
|
+
<div class="shrink-0">
|
|
15
|
+
{@render header()}
|
|
16
|
+
</div>
|
|
17
|
+
<div class="flex min-h-0 flex-1 flex-col overflow-hidden">
|
|
18
|
+
{@render children()}
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { tick } from 'svelte'
|
|
3
|
+
import FileTypeIcon from './FileTypeIcon.svelte'
|
|
4
|
+
import {
|
|
5
|
+
buildProjectFileTree,
|
|
6
|
+
flattenVisibleProjectFileTree,
|
|
7
|
+
formatProjectFileTreeSize,
|
|
8
|
+
getProjectFileTreeDepth,
|
|
9
|
+
getProjectFileTreeItemAccessibility,
|
|
10
|
+
getProjectFileTreeKeyboardAction,
|
|
11
|
+
projectFileTreePathToId,
|
|
12
|
+
type ProjectFileTreeNode,
|
|
13
|
+
} from '../projectFileTree'
|
|
14
|
+
import type { FileEntry } from '../domain'
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
entries: FileEntry[]
|
|
18
|
+
expandedDirs: Set<string>
|
|
19
|
+
selectedPath: string | null
|
|
20
|
+
onToggleDir: (path: string) => void
|
|
21
|
+
onSelectFile: (path: string) => void
|
|
22
|
+
initialScrollTop?: number
|
|
23
|
+
onScrollTopChange?: (scrollTop: number) => void
|
|
24
|
+
focusSelectedRequest?: number | null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type TreeNode = ProjectFileTreeNode<FileEntry>
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
entries,
|
|
31
|
+
expandedDirs,
|
|
32
|
+
selectedPath,
|
|
33
|
+
onToggleDir,
|
|
34
|
+
onSelectFile,
|
|
35
|
+
initialScrollTop = 0,
|
|
36
|
+
onScrollTopChange,
|
|
37
|
+
focusSelectedRequest = null,
|
|
38
|
+
}: Props = $props()
|
|
39
|
+
|
|
40
|
+
let scrollContainer = $state<HTMLDivElement | null>(null)
|
|
41
|
+
let appliedInitialScrollTop = $state<number | null>(null)
|
|
42
|
+
let focusedPath = $state<string | null>(null)
|
|
43
|
+
let lastSelectedPath = $state<string | null>(null)
|
|
44
|
+
let appliedFocusSelectedRequest = $state<number | null>(null)
|
|
45
|
+
|
|
46
|
+
const treeNodes = $derived(buildProjectFileTree(entries))
|
|
47
|
+
const visibleNodes = $derived(flattenVisibleProjectFileTree(treeNodes, expandedDirs))
|
|
48
|
+
const visiblePaths = $derived(visibleNodes.map((node) => node.entry.path))
|
|
49
|
+
|
|
50
|
+
function getTreeItemElement(path: string): HTMLElement | null {
|
|
51
|
+
const index = visiblePaths.indexOf(path)
|
|
52
|
+
if (index === -1) return null
|
|
53
|
+
return scrollContainer?.querySelector<HTMLElement>(`[data-tree-index="${index}"]`) ?? null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function focusPath(path: string) {
|
|
57
|
+
focusedPath = path
|
|
58
|
+
await tick()
|
|
59
|
+
getTreeItemElement(path)?.focus()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function activateNode(node: TreeNode) {
|
|
63
|
+
if (node.entry.isDir) {
|
|
64
|
+
void focusPath(node.entry.path)
|
|
65
|
+
onToggleDir(node.entry.path)
|
|
66
|
+
} else {
|
|
67
|
+
onSelectFile(node.entry.path)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function handleKeydown(event: KeyboardEvent, node: TreeNode) {
|
|
72
|
+
const action = getProjectFileTreeKeyboardAction(event, node, { expandedDirs, visiblePaths })
|
|
73
|
+
if (!action.handled) return
|
|
74
|
+
|
|
75
|
+
event.preventDefault()
|
|
76
|
+
event.stopPropagation()
|
|
77
|
+
|
|
78
|
+
switch (action.type) {
|
|
79
|
+
case 'activate':
|
|
80
|
+
activateNode(node)
|
|
81
|
+
break
|
|
82
|
+
case 'focus':
|
|
83
|
+
void focusPath(action.path)
|
|
84
|
+
break
|
|
85
|
+
case 'toggle':
|
|
86
|
+
onToggleDir(action.path)
|
|
87
|
+
break
|
|
88
|
+
case 'none':
|
|
89
|
+
break
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleScroll() {
|
|
94
|
+
if (scrollContainer) {
|
|
95
|
+
onScrollTopChange?.(scrollContainer.scrollTop)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
$effect(() => {
|
|
100
|
+
if (scrollContainer && appliedInitialScrollTop !== initialScrollTop) {
|
|
101
|
+
scrollContainer.scrollTop = initialScrollTop
|
|
102
|
+
appliedInitialScrollTop = initialScrollTop
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
$effect(() => {
|
|
107
|
+
const selectedChanged = selectedPath !== lastSelectedPath
|
|
108
|
+
|
|
109
|
+
if (selectedChanged && selectedPath !== null && visiblePaths.includes(selectedPath)) {
|
|
110
|
+
focusedPath = selectedPath
|
|
111
|
+
} else if (focusedPath === null || !visiblePaths.includes(focusedPath)) {
|
|
112
|
+
focusedPath = selectedPath !== null && visiblePaths.includes(selectedPath) ? selectedPath : visiblePaths[0] ?? null
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
lastSelectedPath = selectedPath
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
$effect(() => {
|
|
119
|
+
if (focusSelectedRequest === null || appliedFocusSelectedRequest === focusSelectedRequest) return
|
|
120
|
+
appliedFocusSelectedRequest = focusSelectedRequest
|
|
121
|
+
if (selectedPath !== null && visiblePaths.includes(selectedPath)) {
|
|
122
|
+
void focusPath(selectedPath)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
</script>
|
|
126
|
+
|
|
127
|
+
<div class="flex h-full flex-col border-r border-base-300 bg-base-100">
|
|
128
|
+
<div
|
|
129
|
+
class="flex-1 overflow-y-auto py-2"
|
|
130
|
+
bind:this={scrollContainer}
|
|
131
|
+
onscroll={handleScroll}
|
|
132
|
+
role="tree"
|
|
133
|
+
aria-label="Project files"
|
|
134
|
+
>
|
|
135
|
+
{#snippet renderNodes(nodes: TreeNode[])}
|
|
136
|
+
{#each nodes as node (node.entry.path)}
|
|
137
|
+
{@const entry = node.entry}
|
|
138
|
+
{@const isExpanded = expandedDirs.has(entry.path)}
|
|
139
|
+
{@const isSelected = selectedPath === entry.path}
|
|
140
|
+
{@const treeIndex = visiblePaths.indexOf(entry.path)}
|
|
141
|
+
{@const labelId = `${projectFileTreePathToId(entry.path)}-label`}
|
|
142
|
+
{@const sizeId = `${projectFileTreePathToId(entry.path)}-size`}
|
|
143
|
+
{@const a11y = getProjectFileTreeItemAccessibility(node, { expandedDirs, selectedPath, labelId, sizeId })}
|
|
144
|
+
<div
|
|
145
|
+
class="outline-none [&:focus-visible>div:first-child]:ring-2 [&:focus-visible>div:first-child]:ring-inset [&:focus-visible>div:first-child]:ring-primary/60"
|
|
146
|
+
role="treeitem"
|
|
147
|
+
tabindex={focusedPath === entry.path ? 0 : -1}
|
|
148
|
+
aria-level={a11y.level}
|
|
149
|
+
aria-setsize={a11y.setSize}
|
|
150
|
+
aria-posinset={a11y.posInSet}
|
|
151
|
+
aria-expanded={a11y.expanded}
|
|
152
|
+
aria-current={a11y.current}
|
|
153
|
+
aria-selected={a11y.selected}
|
|
154
|
+
aria-labelledby={a11y.labelledBy}
|
|
155
|
+
data-testid="tree-entry"
|
|
156
|
+
data-tree-index={treeIndex}
|
|
157
|
+
onclick={(event) => {
|
|
158
|
+
event.stopPropagation()
|
|
159
|
+
activateNode(node)
|
|
160
|
+
}}
|
|
161
|
+
onkeydown={(event) => handleKeydown(event, node)}
|
|
162
|
+
onfocus={() => {
|
|
163
|
+
focusedPath = entry.path
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
<div
|
|
167
|
+
class="w-full flex items-center gap-2 text-xs cursor-pointer transition-colors py-1.5 pr-3 {entry.isDir ? 'text-base-content hover:bg-base-content/5' : isSelected ? 'bg-primary/10 text-primary font-medium border-l-2 border-l-primary hover:bg-primary/15' : 'text-base-content hover:bg-base-content/5'}"
|
|
168
|
+
style="padding-left: {entry.isDir || !isSelected ? 12 + getProjectFileTreeDepth(entry.path) * 16 : 10 + getProjectFileTreeDepth(entry.path) * 16}px"
|
|
169
|
+
>
|
|
170
|
+
{#if entry.isDir}
|
|
171
|
+
<span class="text-[0.6rem] text-base-content/50 shrink-0" data-testid={`dir-indicator-${entry.path}`} aria-hidden="true">{isExpanded ? '▼' : '▶'}</span>
|
|
172
|
+
<FileTypeIcon folder open={isExpanded} class="w-3.5 h-3.5" />
|
|
173
|
+
<span id={labelId} class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-left" data-testid="entry-label">{entry.name}/</span>
|
|
174
|
+
{:else}
|
|
175
|
+
<FileTypeIcon filename={entry.path} class="w-3.5 h-3.5" />
|
|
176
|
+
<span id={labelId} class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-left" data-testid="entry-label">{entry.name}</span>
|
|
177
|
+
<span id={sizeId} class="text-base-content/50 text-[0.7rem] ml-auto">{formatProjectFileTreeSize(entry.size)}</span>
|
|
178
|
+
{/if}
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
{#if entry.isDir && isExpanded && node.children.length > 0}
|
|
182
|
+
<div role="group">
|
|
183
|
+
{@render renderNodes(node.children)}
|
|
184
|
+
</div>
|
|
185
|
+
{/if}
|
|
186
|
+
</div>
|
|
187
|
+
{/each}
|
|
188
|
+
{/snippet}
|
|
189
|
+
|
|
190
|
+
{@render renderNodes(treeNodes)}
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
package/dist/vite.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* plugin://host-runtime assets are derived from the same host-runtime contract.
|
|
5
5
|
*/
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
7
|
-
import {
|
|
7
|
+
import { OPENFORGE_PLUGIN_SDK_PUBLIC_ENTRYPOINTS } from './publicEntrypoints.mjs';
|
|
8
8
|
import { OPENFORGE_HOST_RUNTIME_SVELTE_SPECIFIERS as HOST_RUNTIME_SVELTE_SPECIFIERS } from './svelteHostRuntimeContract.mjs';
|
|
9
9
|
export const OPENFORGE_HOST_RUNTIME_SVELTE_SPECIFIERS = HOST_RUNTIME_SVELTE_SPECIFIERS;
|
|
10
10
|
export const OPENFORGE_HOST_SHARED_SVELTE_IMPORTS = OPENFORGE_HOST_RUNTIME_SVELTE_SPECIFIERS;
|
|
@@ -26,22 +26,12 @@ export function isOpenForgeHostRuntimeExternal(id) {
|
|
|
26
26
|
}
|
|
27
27
|
export const openforgePluginViteExternals = isOpenForgeHostRuntimeExternal;
|
|
28
28
|
const OPENFORGE_PLUGIN_SDK_SOURCE_ENTRYPOINTS = Object.freeze([
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
['@openforge-app/plugin-sdk/prStatusPresentation', 'packages/plugin-sdk/src/prStatusPresentation.ts'],
|
|
36
|
-
['@openforge-app/plugin-sdk/markdown', 'packages/plugin-sdk/src/markdown.ts'],
|
|
37
|
-
['@openforge-app/plugin-sdk/numberParsing', 'packages/plugin-sdk/src/numberParsing.ts'],
|
|
38
|
-
['@openforge-app/plugin-sdk/projectFileTree', 'packages/plugin-sdk/src/projectFileTree.ts'],
|
|
39
|
-
['@openforge-app/plugin-sdk/sanitize', 'packages/plugin-sdk/src/sanitize.ts'],
|
|
40
|
-
['@openforge-app/plugin-sdk/pluginIcons', 'packages/plugin-sdk/src/pluginIcons.ts'],
|
|
41
|
-
['@openforge-app/plugin-sdk/fileIcons', 'packages/plugin-sdk/src/fileIcons.ts'],
|
|
42
|
-
['@openforge-app/plugin-sdk/collapsibleSectionState', 'packages/plugin-sdk/src/collapsibleSectionState.ts'],
|
|
43
|
-
...OPENFORGE_PLUGIN_SDK_PUBLIC_UI_EXPORTS.map(({ importSpecifier, workspaceSourcePath }) => [importSpecifier, workspaceSourcePath]),
|
|
44
|
-
['@openforge-app/plugin-sdk', 'packages/plugin-sdk/src/index.ts'],
|
|
29
|
+
...OPENFORGE_PLUGIN_SDK_PUBLIC_ENTRYPOINTS
|
|
30
|
+
.filter(({ packageSubpath }) => packageSubpath !== '.')
|
|
31
|
+
.map(({ importSpecifier, workspaceSourcePath }) => [importSpecifier, workspaceSourcePath]),
|
|
32
|
+
...OPENFORGE_PLUGIN_SDK_PUBLIC_ENTRYPOINTS
|
|
33
|
+
.filter(({ packageSubpath }) => packageSubpath === '.')
|
|
34
|
+
.map(({ importSpecifier, workspaceSourcePath }) => [importSpecifier, workspaceSourcePath]),
|
|
45
35
|
]);
|
|
46
36
|
function repoRootUrl(repoRoot) {
|
|
47
37
|
if (repoRoot instanceof URL) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openforge-app/plugin-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -68,15 +68,21 @@
|
|
|
68
68
|
"types": "./dist/collapsibleSectionState.d.ts",
|
|
69
69
|
"default": "./dist/collapsibleSectionState.js"
|
|
70
70
|
},
|
|
71
|
+
"./taskBrowserDevToolsShortcuts": {
|
|
72
|
+
"types": "./dist/taskBrowserDevToolsShortcuts.d.ts",
|
|
73
|
+
"default": "./dist/taskBrowserDevToolsShortcuts.js"
|
|
74
|
+
},
|
|
71
75
|
"./ui/Button.svelte": "./dist/ui/Button.svelte",
|
|
72
76
|
"./ui/Checkbox.svelte": "./dist/ui/Checkbox.svelte",
|
|
73
77
|
"./ui/MarkdownContent.svelte": "./dist/ui/MarkdownContent.svelte",
|
|
74
78
|
"./ui/ResizablePanel.svelte": "./dist/ui/ResizablePanel.svelte",
|
|
75
79
|
"./ui/Modal.svelte": "./dist/ui/Modal.svelte",
|
|
76
80
|
"./ui/PluginPageHeader.svelte": "./dist/ui/PluginPageHeader.svelte",
|
|
81
|
+
"./ui/PluginPageShell.svelte": "./dist/ui/PluginPageShell.svelte",
|
|
77
82
|
"./ui/PluginViewState.svelte": "./dist/ui/PluginViewState.svelte",
|
|
78
83
|
"./ui/PluginSidebarLink.svelte": "./dist/ui/PluginSidebarLink.svelte",
|
|
79
84
|
"./ui/FileTypeIcon.svelte": "./dist/ui/FileTypeIcon.svelte",
|
|
85
|
+
"./ui/ProjectFileTree.svelte": "./dist/ui/ProjectFileTree.svelte",
|
|
80
86
|
"./ui/CollapsibleSection.svelte": "./dist/ui/CollapsibleSection.svelte"
|
|
81
87
|
},
|
|
82
88
|
"files": [
|
|
@@ -104,7 +110,8 @@
|
|
|
104
110
|
},
|
|
105
111
|
"scripts": {
|
|
106
112
|
"clean": "node -e \"import('node:fs').then(({ rmSync }) => rmSync('dist', { recursive: true, force: true }))\"",
|
|
107
|
-
"
|
|
113
|
+
"check:entrypoints": "node ./scripts/check-entrypoint-registries.mjs",
|
|
114
|
+
"build": "pnpm run check:entrypoints && pnpm run clean && tsc && pnpm run build:assets",
|
|
108
115
|
"build:assets": "node ./scripts/copy-package-assets.mjs",
|
|
109
116
|
"check:contract": "node ./scripts/check-published-contract.mjs",
|
|
110
117
|
"icons:generate": "node ./scripts/generate-file-type-icons.mjs",
|