diff --git a/plugins/files/frontend/src/index.js b/plugins/files/frontend/src/index.js index 8f8e2e0..7e30d9c 100644 --- a/plugins/files/frontend/src/index.js +++ b/plugins/files/frontend/src/index.js @@ -29,7 +29,8 @@ '.files-item{display:flex;align-items:center;gap:0.6rem;padding:0.4rem 0.75rem;cursor:pointer;font-size:0.85rem}', '.files-item:hover{background:#1a1a2e}', '.files-item.selected{background:#1a2a3a}', - '.files-item-icon{font-size:1rem;width:1.2rem;text-align:center;flex-shrink:0}', + '.files-item-icon{width:1.2rem;height:1.2rem;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:#8b8ba8}', + '.files-item-icon svg{display:block;width:16px;height:16px}', '.files-item-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}', '.files-item-meta{font-size:0.7rem;color:#666;flex-shrink:0}', '.files-empty{flex:1;display:flex;align-items:center;justify-content:center;color:#666;font-size:0.9rem}', @@ -63,14 +64,26 @@ return elem; } + function svgIcon(path) { + return ''; + } + function fileIcon(entry) { - if (entry.type === 'folder') return '\uD83D\uDCC1'; + if (entry.type === 'folder') { + return svgIcon('M3 5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v1H3V5Zm0 6h18v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7Z'); + } var ext = (entry.extension || '').toLowerCase(); - if (ext === 'md' || ext === 'markdown') return '\uD83D\uDCDD'; - if (ext === 'txt' || ext === 'log') return '\uD83D\uDCC4'; + if (ext === 'md' || ext === 'markdown') { + return svgIcon('M5 3h10l4 4v14H5V3Zm9 1.5V8h3.5L14 4.5ZM8 11h8v2H8v-2Zm0 4h8v2H8v-2Z'); + } + if (ext === 'txt' || ext === 'log') { + return svgIcon('M6 2h9l5 5v15H6V2Zm8 1.5V8h4.5L14 3.5ZM8 12h8v2H8v-2Zm0 4h8v2H8v-2Z'); + } if (ext === 'json') return '{ }'; - if (ext === 'yaml' || ext === 'yml' || ext === 'toml') return '\u2699\uFE0F'; - return '\uD83D\uDCC1'; + if (ext === 'yaml' || ext === 'yml' || ext === 'toml') { + return svgIcon('M19.14 13l.57-1.43 1.79-.5-1-2.29-1.64.73-.29-.28-.73-1.64 2.29-1-1-2.29-1.79.5-.57 1.43-2.17.17-.57-1.43-1.79-.5-1 2.29 1.64.73-.29.28-.73 1.64-2.29-1-1 2.29 1.79.5.57 1.43-.57 1.43-1.79.5 1 2.29 1.64-.73.29.28.73 1.64-2.29 1 1 2.29 1.79-.5.57-1.43 2.17-.17.57 1.43 1.79.5 1-2.29-1.64-.73.29-.28.73-1.64 2.29 1 1-2.29-1.79-.5-.57-1.43ZM12 9a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z'); + } + return svgIcon('M6 2h9l5 5v15H6V2Zm8 1.5V8h4.5L14 3.5Z'); } function formatSize(bytes) { @@ -95,6 +108,7 @@ containerEl.innerHTML = ''; containerEl.className = 'files-root'; + var workspaceRoot = cleanPath(props && (props.workspaceRootPath || (props.workspaceNode && props.workspaceNode.path)) || ''); var currentPath = ''; var entries = []; var disposed = false; @@ -124,9 +138,28 @@ var createMode = ''; // 'folder' | 'file' | '' + function cleanPath(path) { + return String(path || '').split('/').filter(Boolean).join('/'); + } + + function scopedPath(localPath) { + localPath = cleanPath(localPath); + if (!workspaceRoot) return localPath; + return localPath ? workspaceRoot + '/' + localPath : workspaceRoot; + } + + function localPath(fullPath) { + fullPath = cleanPath(fullPath); + if (!workspaceRoot) return fullPath; + if (fullPath === workspaceRoot) return ''; + if (fullPath.indexOf(workspaceRoot + '/') === 0) return fullPath.slice(workspaceRoot.length + 1); + return fullPath; + } + function updateBreadcrumb() { breadcrumb.innerHTML = ''; - var rootItem = el('span', { className: 'files-breadcrumb-item', onClick: function () { navigateTo(''); } }, ['Root']); + var rootLabel = props && props.workspaceNode && props.workspaceNode.title ? props.workspaceNode.title : 'Root'; + var rootItem = el('span', { className: 'files-breadcrumb-item', onClick: function () { navigateTo(''); } }, [rootLabel]); breadcrumb.appendChild(rootItem); if (currentPath) { var parts = currentPath.split('/'); @@ -151,13 +184,13 @@ sorted.forEach(function (entry) { if (entry.isHidden || entry.isReserved) return; var item = el('div', { className: 'files-item' }, [ - el('span', { className: 'files-item-icon' }, [fileIcon(entry)]), + el('span', { className: 'files-item-icon', innerHTML: fileIcon(entry) }), el('span', { className: 'files-item-name', textContent: entry.name }), el('span', { className: 'files-item-meta', textContent: entry.type === 'folder' ? '' : formatSize(entry.size) }), ]); if (entry.type === 'folder') { item.addEventListener('dblclick', function () { - navigateTo(entry.relativePath); + navigateTo(localPath(entry.relativePath)); }); } else { item.addEventListener('dblclick', function () { @@ -177,7 +210,7 @@ function loadEntries() { listContainer.innerHTML = ''; listContainer.appendChild(el('div', { className: 'files-loading' }, ['Loading...'])); - api.files.list(currentPath).then(function (result) { + api.files.list(scopedPath(currentPath)).then(function (result) { if (disposed) return; entries = result || []; renderList(); @@ -195,7 +228,8 @@ function openFile(entry) { var ext = entry.extension ? '.' + entry.extension : ''; var isMd = ext === '.md' || ext === '.markdown'; - var isNotes = currentPath.split('/')[0] === 'Notes'; + var entryLocalPath = localPath(entry.relativePath); + var isNotes = entryLocalPath.split('/')[0] === 'Notes'; var context = { sourcePluginId: 'verstak.files', sourceView: 'files' }; if (isMd && isNotes) { context.isInsideNotesFolder = true; @@ -228,7 +262,8 @@ function confirmCreate() { var name = createInput.value.trim(); if (!name) return; - var path = currentPath ? currentPath + '/' + name : name; + var localCreatePath = currentPath ? currentPath + '/' + name : name; + var path = scopedPath(localCreatePath); var promise; if (createMode === 'folder') { promise = api.files.createFolder(path); diff --git a/scripts/build.sh b/scripts/build.sh index 810a34d..df8f7f9 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -51,6 +51,10 @@ package_plugin() { mkdir -p "$dist_dir/frontend/dist" cp -r "$plugin_dir/frontend/dist/." "$dist_dir/frontend/dist/" echo " └─ frontend/dist ($(find "$dist_dir/frontend/dist" -type f | wc -l) file(s))" + elif [ -f "$plugin_dir/frontend/src/index.js" ]; then + mkdir -p "$dist_dir/frontend/dist" + cp "$plugin_dir/frontend/src/index.js" "$dist_dir/frontend/dist/index.js" + echo " └─ frontend/dist/index.js (from frontend/src/index.js)" fi # 3. backend binary diff --git a/scripts/check.sh b/scripts/check.sh index 59079cd..c2adfb2 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -104,6 +104,9 @@ if command -v node &>/dev/null; then entry=$(node -e "const m=require('$manifest');console.log(m.frontend&&m.frontend.entry||'')" 2>/dev/null) if [ -z "$entry" ]; then continue; fi bundle="$plugin_dir$entry" + if [ ! -f "$bundle" ] && [ "$entry" = "frontend/dist/index.js" ] && [ -f "$plugin_dir/frontend/src/index.js" ]; then + bundle="$plugin_dir/frontend/src/index.js" + fi if [ ! -f "$bundle" ]; then echo " ❌ $plugin_id: bundle not found at $entry" BUNDLE_FAILED=1