feat: milestones 6b-fix through 6e — default-editor, files plugin, workspace host, workspaceItems contribution
- Fix PluginCard openProviders display - Add default-editor plugin (text/markdown/notes-context) - Add files plugin with workspaceItems placement - Add workspaceItems contribution point (Go + API + mock + SDK) - Add WorkspaceHost component for workspace area - WorkspaceTree dispatches selection event - Fix default-editor layout to fill container - Fix PluginCard unsafe .length access - Add E2E tests: 34/34 pass - Add bundle execution check to official-plugins check.sh - Update docs: PLUGIN_RUNTIME, DEV_PLUGINS, MILESTONE_6B/6C/6D plans
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
import ViewContainer from './lib/shell/ViewContainer.svelte';
|
||||
import VaultSelection from './lib/shell/VaultSelection.svelte';
|
||||
import WorkbenchHost from './lib/shell/WorkbenchHost.svelte';
|
||||
import WorkspaceHost from './lib/shell/WorkspaceHost.svelte';
|
||||
import * as App from '../wailsjs/go/api/App';
|
||||
import { debug } from './lib/log/debug.js';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -20,6 +21,9 @@
|
||||
let activeSettingsPanelId = '';
|
||||
let openedResource = null;
|
||||
|
||||
let workspaceNodes = [];
|
||||
let currentWorkspaceNodeId = '';
|
||||
|
||||
function flog(msg) {
|
||||
App.WriteFrontendLog('App', msg);
|
||||
}
|
||||
@@ -91,6 +95,15 @@
|
||||
currentView = 'workbench';
|
||||
}
|
||||
|
||||
function onWorkspaceNodeSelected(e) {
|
||||
debug.log('[App] onWorkspaceNodeSelected:', e.detail?.nodeId);
|
||||
currentWorkspaceNodeId = e.detail?.nodeId || '';
|
||||
workspaceNodes = e.detail?.nodes || workspaceNodes;
|
||||
if (currentWorkspaceNodeId) {
|
||||
currentView = 'workspace';
|
||||
}
|
||||
}
|
||||
|
||||
function onCloseSettings() {
|
||||
debug.log('[App] onCloseSettings');
|
||||
activeSettingsPluginId = '';
|
||||
@@ -105,6 +118,7 @@
|
||||
window.addEventListener('verstak:open-settings', onOpenSettings);
|
||||
window.addEventListener('verstak:close-settings', onCloseSettings);
|
||||
window.addEventListener('verstak:workbench-opened', onWorkbenchOpened);
|
||||
window.addEventListener('verstak:workspace-node-selected', onWorkspaceNodeSelected);
|
||||
}
|
||||
|
||||
onMount(() => { checkVault(); });
|
||||
@@ -125,6 +139,8 @@
|
||||
<PluginManager {activeSettingsPluginId} {activeSettingsPanelId} />
|
||||
{:else if currentView === 'workbench'}
|
||||
<WorkbenchHost {openedResource} />
|
||||
{:else if currentView === 'workspace'}
|
||||
<WorkspaceHost currentNodeId={currentWorkspaceNodeId} nodes={workspaceNodes} />
|
||||
{:else}
|
||||
<ViewContainer {activeView} {activeViewPluginId} />
|
||||
{/if}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
commands: (contributions.commands || []).filter(c => c.pluginId === pluginId).length,
|
||||
sidebar: (contributions.sidebarItems || []).filter(s => s.pluginId === pluginId).length,
|
||||
statusbar: (contributions.statusBarItems || []).filter(s => s.pluginId === pluginId).length,
|
||||
openProviders: (contributions.openProviders || []).filter(o => o.pluginId === pluginId).length,
|
||||
};
|
||||
|
||||
$: contribSummary = (() => {
|
||||
@@ -40,6 +41,7 @@
|
||||
if (contribCounts.commands > 0) parts.push(contribCounts.commands + ' command' + (contribCounts.commands !== 1 ? 's' : ''));
|
||||
if (contribCounts.sidebar > 0) parts.push(contribCounts.sidebar + ' sidebar' + (contribCounts.sidebar !== 1 ? 's' : ''));
|
||||
if (contribCounts.statusbar > 0) parts.push(contribCounts.statusbar + ' statusbar' + (contribCounts.statusbar !== 1 ? 's' : ''));
|
||||
if (contribCounts.openProviders > 0) parts.push(contribCounts.openProviders + ' openProvider' + (contribCounts.openProviders !== 1 ? 's' : ''));
|
||||
return parts.length > 0 ? parts.join(', ') : 'none';
|
||||
})();
|
||||
|
||||
@@ -200,7 +202,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Permission warnings -->
|
||||
{#if !hasUIPermission && (m.contributes && (m.contributes.views || m.contributes.sidebarItems || m.contributes.settingsPanels).length > 0)}
|
||||
{#if !hasUIPermission && m.contributes && ((m.contributes.views || []).length > 0 || (m.contributes.sidebarItems || []).length > 0 || (m.contributes.settingsPanels || []).length > 0)}
|
||||
<p class="warning"><Icon name="warning" size={12} /> Plugin has UI contributions but lacks ui.register permission</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -89,8 +89,11 @@
|
||||
.workbench-content {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.workbench-empty {
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
<script>
|
||||
import PluginBundleHost from '../plugin-host/PluginBundleHost.svelte';
|
||||
import * as App from '../../../wailsjs/go/api/App';
|
||||
|
||||
export let currentNodeId = '';
|
||||
export let nodes = [];
|
||||
|
||||
let contributions = {};
|
||||
let plugins = [];
|
||||
let workspaceTools = [];
|
||||
|
||||
$: currentNode = nodes.find(n => n.id === currentNodeId) || null;
|
||||
$: if (currentNodeId) loadTools();
|
||||
|
||||
async function loadTools() {
|
||||
try {
|
||||
const [c, p] = await Promise.all([
|
||||
App.GetContributions().catch(() => ({})),
|
||||
App.GetPlugins().catch(() => []),
|
||||
]);
|
||||
contributions = c || {};
|
||||
plugins = p || [];
|
||||
|
||||
const enabledIds = new Set(
|
||||
plugins.filter(pl => pl.enabled && (pl.status === 'loaded' || pl.status === 'degraded')).map(pl => pl.manifest?.id)
|
||||
);
|
||||
|
||||
workspaceTools = (contributions.workspaceItems || []).filter(tool => enabledIds.has(tool.pluginId));
|
||||
} catch (e) {
|
||||
console.error('[WorkspaceHost] loadTools error:', e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="workspace-host">
|
||||
{#if currentNode}
|
||||
<div class="workspace-header">
|
||||
<span class="workspace-title">{currentNode.title}</span>
|
||||
<span class="workspace-type">{currentNode.type}</span>
|
||||
</div>
|
||||
|
||||
{#if workspaceTools.length > 0}
|
||||
<div class="workspace-tools">
|
||||
{#each workspaceTools as tool (tool.id + tool.pluginId)}
|
||||
<div class="workspace-tool">
|
||||
<div class="tool-header">
|
||||
<span class="tool-title">{tool.title || tool.id}</span>
|
||||
<span class="tool-plugin">{tool.pluginId}</span>
|
||||
</div>
|
||||
<div class="tool-content">
|
||||
<PluginBundleHost
|
||||
pluginId={tool.pluginId}
|
||||
componentId={tool.component}
|
||||
componentProps={{ workspaceNodeId: currentNodeId, workspaceNode: currentNode }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="workspace-empty">
|
||||
<p>No workspace tools available</p>
|
||||
<p class="workspace-hint">Install plugins that contribute workspaceItems to see tools here.</p>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="workspace-empty">
|
||||
<p>Select a workspace node from the sidebar</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.workspace-host {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: #1a1a2e;
|
||||
}
|
||||
|
||||
.workspace-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid #16213e;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.workspace-title {
|
||||
color: #e0e0f0;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.workspace-type {
|
||||
color: #4ecca3;
|
||||
font-size: 0.75rem;
|
||||
padding: 0.1rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
background: #1a2a3a;
|
||||
}
|
||||
|
||||
.workspace-tools {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.workspace-tool {
|
||||
border: 1px solid #16213e;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 0.5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tool-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.4rem 0.75rem;
|
||||
background: #12122a;
|
||||
border-bottom: 1px solid #16213e;
|
||||
}
|
||||
|
||||
.tool-title {
|
||||
color: #e0e0f0;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tool-plugin {
|
||||
color: #666;
|
||||
font-size: 0.65rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.tool-content {
|
||||
min-height: 300px;
|
||||
max-height: 60vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.workspace-empty {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #666;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.workspace-hint {
|
||||
font-size: 0.8rem;
|
||||
color: #555;
|
||||
max-width: 300px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -78,6 +78,9 @@
|
||||
if (err) { localError = err; return; }
|
||||
currentNodeId = id;
|
||||
activeWorkspaceNodeId.set(id);
|
||||
window.dispatchEvent(new CustomEvent('verstak:workspace-node-selected', {
|
||||
detail: { nodeId: id, nodes: nodes }
|
||||
}));
|
||||
}
|
||||
|
||||
function openCreate(parentId, type) {
|
||||
|
||||
@@ -47,11 +47,10 @@
|
||||
{
|
||||
id: 'verstak.platform-test.markdown-diagnostic',
|
||||
title: 'Platform Test Markdown Diagnostic',
|
||||
priority: 100,
|
||||
priority: 10,
|
||||
component: 'MarkdownDiagnosticProvider',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['generic-markdown', 'notes-markdown'] },
|
||||
{ kind: 'vault-file', extensions: ['.txt', '.log'], mime: ['text/plain'], contexts: ['generic-text'] }
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['generic-markdown', 'notes-markdown'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -59,11 +58,86 @@
|
||||
},
|
||||
rootPath: '/tmp/verstak-test/plugins/platform-test',
|
||||
error: ''
|
||||
},
|
||||
'verstak.default-editor': {
|
||||
status: 'loaded',
|
||||
enabled: true,
|
||||
manifest: {
|
||||
schemaVersion: 1,
|
||||
id: 'verstak.default-editor',
|
||||
name: 'Default Editor',
|
||||
version: '0.1.0',
|
||||
apiVersion: '0.1.0',
|
||||
description: 'Built-in text and markdown editor/viewer.',
|
||||
source: 'official',
|
||||
icon: 'edit',
|
||||
provides: ['verstak/default-editor/v1'],
|
||||
requires: ['verstak/core/files/v1', 'verstak/core/workbench/v1'],
|
||||
permissions: ['files.read', 'files.write', 'workbench.open'],
|
||||
frontend: { entry: 'frontend/dist/index.js' },
|
||||
contributes: {
|
||||
openProviders: [
|
||||
{
|
||||
id: 'verstak.default-editor.text',
|
||||
title: 'Default Text Editor',
|
||||
priority: 50,
|
||||
component: 'DefaultEditor',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.txt', '.log', '.conf', '.ini', '.toml', '.yaml', '.yml', '.json', '.csv'], mime: ['text/plain', 'application/json'], contexts: ['generic-text'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'verstak.default-editor.markdown',
|
||||
title: 'Default Markdown Editor',
|
||||
priority: 50,
|
||||
component: 'DefaultEditor',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['generic-markdown'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'verstak.default-editor.notes-markdown',
|
||||
title: 'Default Notes Markdown Editor',
|
||||
priority: 50,
|
||||
component: 'DefaultEditor',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['notes-markdown'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
rootPath: '/tmp/verstak-test/plugins/default-editor',
|
||||
error: ''
|
||||
},
|
||||
'verstak.files': {
|
||||
status: 'loaded',
|
||||
enabled: true,
|
||||
manifest: {
|
||||
schemaVersion: 1,
|
||||
id: 'verstak.files',
|
||||
name: 'Files',
|
||||
version: '0.1.0',
|
||||
apiVersion: '0.1.0',
|
||||
description: 'Minimal vault file navigator.',
|
||||
source: 'official',
|
||||
icon: 'folder',
|
||||
provides: ['verstak/files/v1'],
|
||||
requires: ['verstak/core/files/v1', 'verstak/core/workbench/v1'],
|
||||
permissions: ['files.read', 'files.write', 'workbench.open', 'ui.register'],
|
||||
frontend: { entry: 'frontend/dist/index.js' },
|
||||
contributes: {
|
||||
views: [{ id: 'verstak.files.view', title: 'Files', icon: 'folder', component: 'FilesView' }],
|
||||
workspaceItems: [{ id: 'verstak.files.workspace', title: 'Files', icon: 'folder', component: 'FilesView' }]
|
||||
}
|
||||
},
|
||||
rootPath: '/tmp/verstak-test/plugins/files',
|
||||
error: ''
|
||||
}
|
||||
};
|
||||
|
||||
var vaultStatus = { status: 'open', path: '/tmp/verstak-test/vault', vaultId: 'test-vault-001' };
|
||||
var vaultPluginState = { enabledPlugins: ['verstak.platform-test'], disabledPlugins: [], desiredPlugins: [{ id: 'verstak.platform-test', version: '0.1.0', source: 'official' }] };
|
||||
var vaultPluginState = { enabledPlugins: ['verstak.platform-test', 'verstak.default-editor', 'verstak.files'], disabledPlugins: [], desiredPlugins: [{ id: 'verstak.platform-test', version: '0.1.0', source: 'official' }, { id: 'verstak.default-editor', version: '0.1.0', source: 'official' }, { id: 'verstak.files', version: '0.1.0', source: 'official' }] };
|
||||
var appSettings = { currentVaultPath: '/tmp/verstak-test/vault', recentVaults: [] };
|
||||
var workbenchPreferences = {};
|
||||
var openedResources = [];
|
||||
@@ -97,7 +171,12 @@
|
||||
|
||||
function makeDefaultVaultFiles() {
|
||||
return {
|
||||
'': { type: 'folder', modifiedAt: new Date().toISOString() }
|
||||
'': { type: 'folder', modifiedAt: new Date().toISOString() },
|
||||
'Docs': { type: 'folder', modifiedAt: new Date().toISOString() },
|
||||
'Docs/todo.txt': { type: 'file', content: 'Buy groceries\nWrite tests', modifiedAt: new Date().toISOString() },
|
||||
'Docs/readme.md': { type: 'file', content: '# Hello World\n\nThis is a **test** document.\n\n- item 1\n- item 2', modifiedAt: new Date().toISOString() },
|
||||
'Notes': { type: 'folder', modifiedAt: new Date().toISOString() },
|
||||
'Notes/Overview.md': { type: 'file', content: '# Notes Overview\n\nMy notes content here.', modifiedAt: new Date().toISOString() }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -204,7 +283,7 @@
|
||||
}
|
||||
|
||||
function allContributions() {
|
||||
var views = [], commands = [], sidebarItems = [], statusBarItems = [], settingsPanels = [], openProviders = [];
|
||||
var views = [], commands = [], sidebarItems = [], statusBarItems = [], settingsPanels = [], openProviders = [], workspaceItems = [];
|
||||
for (var id in pluginStates) {
|
||||
var s = pluginStates[id];
|
||||
var c = (s.manifest && s.manifest.contributes) || {};
|
||||
@@ -214,8 +293,9 @@
|
||||
if (c.statusBarItems) c.statusBarItems.forEach(function (st) { statusBarItems.push(Object.assign({}, st, { pluginId: id })); });
|
||||
if (c.settingsPanels) c.settingsPanels.forEach(function (sp) { settingsPanels.push(Object.assign({}, sp, { pluginId: id })); });
|
||||
if (c.openProviders) c.openProviders.forEach(function (op) { openProviders.push(Object.assign({}, op, { pluginId: id })); });
|
||||
if (c.workspaceItems) c.workspaceItems.forEach(function (wi) { workspaceItems.push(Object.assign({}, wi, { pluginId: id })); });
|
||||
}
|
||||
return { views: views, commands: commands, sidebarItems: sidebarItems, statusBarItems: statusBarItems, settingsPanels: settingsPanels, openProviders: openProviders };
|
||||
return { views: views, commands: commands, sidebarItems: sidebarItems, statusBarItems: statusBarItems, settingsPanels: settingsPanels, openProviders: openProviders, workspaceItems: workspaceItems };
|
||||
}
|
||||
|
||||
function requestExtension(request) {
|
||||
@@ -294,6 +374,118 @@
|
||||
return Promise.resolve([result, '']);
|
||||
}
|
||||
|
||||
function defaultEditorBundle() {
|
||||
return [
|
||||
'(function(){',
|
||||
'var DefaultEditor={',
|
||||
'mount:function(c,p,api){',
|
||||
'c.innerHTML="";',
|
||||
'c.className="de-root";',
|
||||
'var req=p.request||{};',
|
||||
'var path=req.path||"";',
|
||||
'var mode=req.mode||"view";',
|
||||
'var ctx=req.context||{};',
|
||||
'var isNotes=ctx.notesMode||ctx.isInsideNotesFolder;',
|
||||
'var ext=(req.extension||"").toLowerCase();',
|
||||
'var isMd=ext===".md"||ext===".markdown";',
|
||||
'var editorMode=isNotes?"notes-markdown":isMd?"generic-markdown":"text";',
|
||||
'c.setAttribute("data-editor-mode",editorMode);',
|
||||
'c.setAttribute("data-resource-path",path);',
|
||||
'c.setAttribute("data-request-mode",mode);',
|
||||
'var toolbar=document.createElement("div");',
|
||||
'toolbar.className="de-toolbar";',
|
||||
'var modeLabel=document.createElement("span");',
|
||||
'modeLabel.className="de-toolbar-mode";',
|
||||
'modeLabel.textContent=editorMode;',
|
||||
'toolbar.appendChild(modeLabel);',
|
||||
'var pathLabel=document.createElement("span");',
|
||||
'pathLabel.className="de-toolbar-context";',
|
||||
'pathLabel.textContent=path;',
|
||||
'toolbar.appendChild(pathLabel);',
|
||||
'if(isNotes){var badge=document.createElement("span");badge.className="de-notes-badge";badge.textContent="notes context";badge.setAttribute("data-notes-badge","");toolbar.appendChild(badge);}',
|
||||
'c.appendChild(toolbar);',
|
||||
'var content=document.createElement("div");',
|
||||
'content.className="de-editor-wrap";',
|
||||
'content.textContent="Loading...";',
|
||||
'c.appendChild(content);',
|
||||
'api.files.readText(path).then(function(text){',
|
||||
'content.textContent="";',
|
||||
'if(isMd){',
|
||||
'var preview=document.createElement("div");',
|
||||
'preview.className="de-preview";',
|
||||
'preview.setAttribute("data-preview","");',
|
||||
'preview.textContent=text;',
|
||||
'content.appendChild(preview);',
|
||||
'}else{',
|
||||
'var ta=document.createElement("textarea");',
|
||||
'ta.className="de-textarea";',
|
||||
'ta.value=text;',
|
||||
'ta.setAttribute("data-editor-textarea","");',
|
||||
'content.appendChild(ta);',
|
||||
'}',
|
||||
'}).catch(function(err){',
|
||||
'content.textContent="Error: "+(err.message||err);',
|
||||
'});',
|
||||
'},',
|
||||
'unmount:function(c){c.innerHTML="";}',
|
||||
'};',
|
||||
'window.VerstakPluginRegister("verstak.default-editor",{components:{DefaultEditor:DefaultEditor}});',
|
||||
'})();'
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
function filesPluginBundle() {
|
||||
return [
|
||||
"(function(){",
|
||||
"var FilesView={",
|
||||
"mount:function(c,p,api){",
|
||||
"c.innerHTML='';",
|
||||
"c.className='files-root';",
|
||||
"c.setAttribute('data-plugin-id','verstak.files');",
|
||||
"var list=document.createElement('div');",
|
||||
"list.className='files-list';",
|
||||
"list.setAttribute('data-files-list','');",
|
||||
"c.appendChild(list);",
|
||||
"function load(){",
|
||||
"list.textContent='Loading...';",
|
||||
"api.files.list('').then(function(entries){",
|
||||
"list.innerHTML='';",
|
||||
"if(!entries||!entries.length){list.textContent='Empty folder';return;}",
|
||||
"entries.forEach(function(e){",
|
||||
"if(e.isHidden||e.isReserved)return;",
|
||||
"var item=document.createElement('div');",
|
||||
"item.className='files-item';",
|
||||
"item.setAttribute('data-file-name',e.name);",
|
||||
"item.setAttribute('data-file-type',e.type);",
|
||||
"item.setAttribute('data-file-path',e.relativePath);",
|
||||
"var icon=document.createElement('span');",
|
||||
"icon.className='files-item-icon';",
|
||||
"icon.textContent=e.type==='folder'?'[D]':'[F]';",
|
||||
"var name=document.createElement('span');",
|
||||
"name.className='files-item-name';",
|
||||
"name.textContent=e.name;",
|
||||
"item.appendChild(icon);",
|
||||
"item.appendChild(name);",
|
||||
"if(e.type!=='folder'){",
|
||||
"item.addEventListener('dblclick',function(){",
|
||||
"var ext=e.extension?'.'+e.extension:'';",
|
||||
"var ctx={sourcePluginId:'verstak.files',sourceView:'files'};",
|
||||
"api.workbench.openResource({kind:'vault-file',path:e.relativePath,mode:'view',extension:ext,context:ctx});",
|
||||
"});",
|
||||
"}",
|
||||
"list.appendChild(item);",
|
||||
"});",
|
||||
"}).catch(function(err){list.textContent='Error: '+(err.message||err);});",
|
||||
"}",
|
||||
"load();",
|
||||
"},",
|
||||
"unmount:function(c){c.innerHTML='';}",
|
||||
"};",
|
||||
"window.VerstakPluginRegister('verstak.files',{components:{FilesView:FilesView}});",
|
||||
"})();"
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
function platformTestBundle() {
|
||||
return [
|
||||
"(function(){",
|
||||
@@ -448,6 +640,12 @@
|
||||
if (pluginId === 'verstak.platform-test' && assetPath === 'frontend/dist/index.js') {
|
||||
return Promise.resolve(platformTestBundle());
|
||||
}
|
||||
if (pluginId === 'verstak.default-editor' && assetPath === 'frontend/dist/index.js') {
|
||||
return Promise.resolve(defaultEditorBundle());
|
||||
}
|
||||
if (pluginId === 'verstak.files' && assetPath === 'frontend/dist/index.js') {
|
||||
return Promise.resolve(filesPluginBundle());
|
||||
}
|
||||
return Promise.resolve('');
|
||||
},
|
||||
GetPluginCapability: function (pluginId, capId) {
|
||||
@@ -675,11 +873,10 @@
|
||||
{
|
||||
id: 'verstak.platform-test.markdown-diagnostic',
|
||||
title: 'Platform Test Markdown Diagnostic',
|
||||
priority: 100,
|
||||
priority: 10,
|
||||
component: 'MarkdownDiagnosticProvider',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['generic-markdown', 'notes-markdown'] },
|
||||
{ kind: 'vault-file', extensions: ['.txt', '.log'], mime: ['text/plain'], contexts: ['generic-text'] }
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['generic-markdown', 'notes-markdown'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -687,10 +884,85 @@
|
||||
},
|
||||
rootPath: '/tmp/verstak-test/plugins/platform-test',
|
||||
error: ''
|
||||
},
|
||||
'verstak.default-editor': {
|
||||
status: 'loaded',
|
||||
enabled: true,
|
||||
manifest: {
|
||||
schemaVersion: 1,
|
||||
id: 'verstak.default-editor',
|
||||
name: 'Default Editor',
|
||||
version: '0.1.0',
|
||||
apiVersion: '0.1.0',
|
||||
description: 'Built-in text and markdown editor/viewer.',
|
||||
source: 'official',
|
||||
icon: 'edit',
|
||||
provides: ['verstak/default-editor/v1'],
|
||||
requires: ['verstak/core/files/v1', 'verstak/core/workbench/v1'],
|
||||
permissions: ['files.read', 'files.write', 'workbench.open'],
|
||||
frontend: { entry: 'frontend/dist/index.js' },
|
||||
contributes: {
|
||||
openProviders: [
|
||||
{
|
||||
id: 'verstak.default-editor.text',
|
||||
title: 'Default Text Editor',
|
||||
priority: 50,
|
||||
component: 'DefaultEditor',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.txt', '.log', '.conf', '.ini', '.toml', '.yaml', '.yml', '.json', '.csv'], mime: ['text/plain', 'application/json'], contexts: ['generic-text'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'verstak.default-editor.markdown',
|
||||
title: 'Default Markdown Editor',
|
||||
priority: 50,
|
||||
component: 'DefaultEditor',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['generic-markdown'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'verstak.default-editor.notes-markdown',
|
||||
title: 'Default Notes Markdown Editor',
|
||||
priority: 50,
|
||||
component: 'DefaultEditor',
|
||||
supports: [
|
||||
{ kind: 'vault-file', extensions: ['.md', '.markdown'], contexts: ['notes-markdown'] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
rootPath: '/tmp/verstak-test/plugins/default-editor',
|
||||
error: ''
|
||||
},
|
||||
'verstak.files': {
|
||||
status: 'loaded',
|
||||
enabled: true,
|
||||
manifest: {
|
||||
schemaVersion: 1,
|
||||
id: 'verstak.files',
|
||||
name: 'Files',
|
||||
version: '0.1.0',
|
||||
apiVersion: '0.1.0',
|
||||
description: 'Minimal vault file navigator.',
|
||||
source: 'official',
|
||||
icon: 'folder',
|
||||
provides: ['verstak/files/v1'],
|
||||
requires: ['verstak/core/files/v1', 'verstak/core/workbench/v1'],
|
||||
permissions: ['files.read', 'files.write', 'workbench.open', 'ui.register'],
|
||||
frontend: { entry: 'frontend/dist/index.js' },
|
||||
contributes: {
|
||||
views: [{ id: 'verstak.files.view', title: 'Files', icon: 'folder', component: 'FilesView' }],
|
||||
workspaceItems: [{ id: 'verstak.files.workspace', title: 'Files', icon: 'folder', component: 'FilesView' }]
|
||||
}
|
||||
},
|
||||
rootPath: '/tmp/verstak-test/plugins/files',
|
||||
error: ''
|
||||
}
|
||||
};
|
||||
vaultStatus = { status: 'open', path: '/tmp/verstak-test/vault', vaultId: 'test-vault-001' };
|
||||
vaultPluginState = { enabledPlugins: ['verstak.platform-test'], disabledPlugins: [], desiredPlugins: [{ id: 'verstak.platform-test', version: '0.1.0', source: 'official' }] };
|
||||
vaultPluginState = { enabledPlugins: ['verstak.platform-test', 'verstak.default-editor', 'verstak.files'], disabledPlugins: [], desiredPlugins: [{ id: 'verstak.platform-test', version: '0.1.0', source: 'official' }, { id: 'verstak.default-editor', version: '0.1.0', source: 'official' }, { id: 'verstak.files', version: '0.1.0', source: 'official' }] };
|
||||
appSettings = { currentVaultPath: '/tmp/verstak-test/vault', recentVaults: [] };
|
||||
workbenchPreferences = {};
|
||||
openedResources = [];
|
||||
|
||||
Reference in New Issue
Block a user