Add lite web extension structure with basic functionality

Co-authored-by: estruyf <2900833+estruyf@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-07 15:07:34 +00:00
parent 7fd0112995
commit b61d115566
8 changed files with 645 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
node_modules
dist
out
*.vsix
.vscode-test/
+9
View File
@@ -0,0 +1,9 @@
.vscode/**
.vscode-test/**
src/**
.gitignore
tsconfig.json
webpack.config.js
node_modules/**
*.map
*.ts
+113
View File
@@ -0,0 +1,113 @@
# Development Guide - Front Matter Lite
## Prerequisites
- Node.js (v18 or higher)
- npm or yarn
## Setup
```bash
cd lite
npm install
```
## Building
### Development Build
```bash
npm run dev
```
This will watch for changes and rebuild automatically.
### Production Build
```bash
npm run build
```
## Testing
### Local Testing
1. Build the extension:
```bash
npm run build
```
2. Press F5 in VS Code to open the Extension Development Host
3. Test in a virtual workspace:
- Open the Command Palette (F1)
- Run "Open Remote Repository"
- Enter a GitHub repository URL
- Test the lite version features
### Testing in github.dev
1. Package the extension:
```bash
npm install -g @vscode/vsce
vsce package
```
2. Navigate to github.dev in your browser
- Press `.` on any GitHub repository
- Install the extension manually
## Architecture
The lite version is designed to work without Node.js-specific APIs:
- **No Node.js fs module** - Uses `vscode.workspace.fs` instead
- **No Node.js path module** - Uses `vscode.Uri.joinPath` instead
- **No child_process** - No external script execution
- **Browser-compatible** - Built as a web extension (target: 'webworker')
## Key Differences from Full Extension
| Feature | Full Extension | Lite Version |
|---------|---------------|--------------|
| File Operations | Node.js `fs` | VS Code `workspace.fs` |
| Path Handling | Node.js `path` | `vscode.Uri` |
| Scripts | child_process | Not available |
| Workspace | File system only | Virtual workspaces |
| Dashboard | Full React app | Simplified (planned) |
## Contributing
When adding features to the lite version:
1. Ensure compatibility with virtual workspaces
2. Use only browser-compatible APIs
3. Test in both github.dev and vscode.dev
4. Document any limitations
## Debugging
Enable the Output Channel "Front Matter Lite" to see debug messages:
1. View > Output
2. Select "Front Matter Lite" from the dropdown
## Common Issues
### Extension not loading
- Check the Output channel for errors
- Ensure the extension is built correctly
- Verify the package.json has the correct `browser` entry point
### Features not working in virtual workspace
- Confirm the workspace scheme is not 'file'
- Check browser console for errors
- Verify you're using VS Code FileSystem API
## Resources
- [VS Code Web Extensions Guide](https://code.visualstudio.com/api/extension-guides/web-extensions)
- [Virtual Workspaces Documentation](https://code.visualstudio.com/api/extension-guides/virtual-workspaces)
- [Front Matter Documentation](https://frontmatter.codes)
+95
View File
@@ -0,0 +1,95 @@
# Front Matter CMS (Lite)
This is the lite version of Front Matter CMS designed specifically for **virtual workspaces** such as github.dev and vscode.dev.
## What is a Virtual Workspace?
Virtual workspaces allow you to work with code directly in your browser without cloning a repository locally. This includes:
- **github.dev** - Press `.` on any GitHub repository
- **vscode.dev** - Open VS Code in your browser
- **GitHub Codespaces** - Cloud-based development environments
## Features
The lite version provides core content management functionality:
### ✅ Supported Features
- **Register Content Folders** - Right-click on folders in the Explorer to register them as content folders
- **Create Content** - Create new markdown files with front matter
- **View Configuration** - Manage your content folder settings
### ❌ Limited/Unavailable Features
The following features from the full extension are not available in the lite version due to virtual workspace limitations:
- **Dashboard** - Full dashboard UI (under development)
- **Media Management** - File upload and media library
- **Local Server Preview** - Starting/stopping local dev servers
- **Git Integration** - Advanced git operations
- **Custom Scripts** - Running custom Node.js scripts
- **File System Watch** - Automatic content refresh
- **Complex Build Tools** - Framework-specific integrations
## Installation
1. Open a virtual workspace (github.dev or vscode.dev)
2. Install the "Front Matter CMS (Lite)" extension from the Extensions marketplace
3. Start managing your content!
## Usage
### Register a Content Folder
1. In the Explorer, right-click on any folder
2. Select **Front Matter Lite > Register Content Folder (Lite)**
3. Enter a title for the folder
4. The folder is now registered and can be used for content creation
### Create New Content
1. Open the Command Palette (F1 or Ctrl/Cmd+Shift+P)
2. Run **Front Matter Lite: Create Content (Lite)**
3. Select a content folder
4. Enter a file name
5. Your new content file is created with basic front matter
## Configuration
The lite version uses the same configuration as the full extension. You can configure your content folders and content types in VS Code settings:
```json
{
"frontMatter.content.pageFolders": [
{
"title": "Blog Posts",
"path": "content/blog"
}
]
}
```
## Limitations
This lite version is designed to work within the constraints of virtual workspaces:
- Uses only the VS Code FileSystem API
- No Node.js file system operations
- No external process execution
- Limited to browser-compatible APIs
## Need More Features?
For the full Front Matter CMS experience with all features, install the regular extension in VS Code Desktop:
- [Front Matter CMS on the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter)
- [Documentation](https://frontmatter.codes)
## Contributing
This is part of the Front Matter CMS project. Visit our [GitHub repository](https://github.com/estruyf/vscode-front-matter) to contribute or report issues.
## License
MIT
+141
View File
@@ -0,0 +1,141 @@
{
"name": "vscode-front-matter-lite",
"displayName": "Front Matter CMS (Lite)",
"description": "Front Matter CMS lite version for virtual workspaces (github.dev, vscode.dev). Provides basic content management features with limited functionality compared to the full extension.",
"icon": "assets/frontmatter-teal-128x128.png",
"version": "10.9.0",
"preview": true,
"publisher": "eliostruyf",
"galleryBanner": {
"color": "#0e131f",
"theme": "dark"
},
"engines": {
"vscode": "^1.90.0"
},
"categories": [
"Other"
],
"keywords": [
"Front Matter",
"CMS",
"Markdown",
"Web Extension",
"Virtual Workspace"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/estruyf/vscode-front-matter"
},
"capabilities": {
"virtualWorkspaces": true,
"untrustedWorkspaces": {
"supported": true
}
},
"browser": "./dist/extension-web.js",
"activationEvents": [
"workspaceContains:**/.frontmatter",
"workspaceContains:**/frontmatter.json"
],
"contributes": {
"commands": [
{
"command": "frontMatter.lite.dashboard",
"title": "Open Dashboard (Lite)",
"category": "Front Matter Lite"
},
{
"command": "frontMatter.lite.registerFolder",
"title": "Register Content Folder (Lite)",
"category": "Front Matter Lite"
},
{
"command": "frontMatter.lite.createContent",
"title": "Create Content (Lite)",
"category": "Front Matter Lite"
}
],
"configuration": {
"title": "Front Matter Lite",
"type": "object",
"properties": {
"frontMatter.content.pageFolders": {
"type": "array",
"default": [],
"markdownDescription": "Configure the folders that contain your content",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "The title of the folder"
},
"path": {
"type": "string",
"description": "The path to the folder"
}
},
"required": [
"title",
"path"
]
}
},
"frontMatter.taxonomy.contentTypes": {
"type": "array",
"default": [
{
"name": "default",
"fields": [
{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
}
]
}
],
"markdownDescription": "Configure your content types"
}
}
},
"menus": {
"explorer/context": [
{
"command": "frontMatter.lite.registerFolder",
"when": "explorerResourceIsFolder",
"group": "frontmatter@1"
}
]
}
},
"scripts": {
"vscode:prepublish": "npm run build",
"build": "webpack --mode production --config ./webpack.config.js",
"dev": "webpack --mode development --watch --config ./webpack.config.js"
},
"devDependencies": {
"@types/vscode": "^1.90.0",
"ts-loader": "^9.4.2",
"typescript": "^4.9.5",
"webpack": "^5.75.0",
"webpack-cli": "^4.10.0"
}
}
+213
View File
@@ -0,0 +1,213 @@
import * as vscode from 'vscode';
/**
* Lite version of Front Matter CMS for virtual workspaces
* This version provides basic content management functionality using
* the VS Code FileSystem API which works in virtual workspaces like github.dev
*/
let outputChannel: vscode.OutputChannel;
export function activate(context: vscode.ExtensionContext) {
outputChannel = vscode.window.createOutputChannel('Front Matter Lite');
outputChannel.appendLine('Front Matter Lite activated for virtual workspace');
// Register Dashboard command
context.subscriptions.push(
vscode.commands.registerCommand('frontMatter.lite.dashboard', async () => {
vscode.window.showInformationMessage(
'Front Matter Lite Dashboard: This feature is under development for virtual workspaces'
);
})
);
// Register folder registration command
context.subscriptions.push(
vscode.commands.registerCommand('frontMatter.lite.registerFolder', async (uri: vscode.Uri) => {
try {
const config = vscode.workspace.getConfiguration('frontMatter');
const pageFolders = config.get<Array<{ title: string; path: string }>>('content.pageFolders') || [];
// Get workspace folder
const workspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
if (!workspaceFolder) {
vscode.window.showErrorMessage('No workspace folder found');
return;
}
// Calculate relative path
const relativePath = vscode.workspace.asRelativePath(uri, false);
// Check if folder is already registered
const exists = pageFolders.some(f => f.path === relativePath);
if (exists) {
vscode.window.showInformationMessage(`Folder "${relativePath}" is already registered`);
return;
}
// Prompt for folder title
const title = await vscode.window.showInputBox({
prompt: 'Enter a title for this content folder',
value: relativePath
});
if (!title) {
return;
}
// Add folder to configuration
pageFolders.push({
title,
path: relativePath
});
await config.update('content.pageFolders', pageFolders, vscode.ConfigurationTarget.Workspace);
vscode.window.showInformationMessage(
`Content folder "${title}" registered successfully!`,
'View Configuration'
).then(selection => {
if (selection === 'View Configuration') {
vscode.commands.executeCommand('workbench.action.openSettings', 'frontMatter.content.pageFolders');
}
});
outputChannel.appendLine(`Registered content folder: ${title} (${relativePath})`);
} catch (error) {
vscode.window.showErrorMessage(`Failed to register folder: ${error}`);
outputChannel.appendLine(`Error registering folder: ${error}`);
}
})
);
// Register create content command
context.subscriptions.push(
vscode.commands.registerCommand('frontMatter.lite.createContent', async () => {
try {
const config = vscode.workspace.getConfiguration('frontMatter');
const pageFolders = config.get<Array<{ title: string; path: string }>>('content.pageFolders') || [];
if (pageFolders.length === 0) {
const action = await vscode.window.showWarningMessage(
'No content folders configured. Please register a content folder first.',
'Register Folder'
);
if (action === 'Register Folder') {
vscode.window.showInformationMessage(
'Please right-click on a folder in the Explorer and select "Front Matter Lite > Register Content Folder"'
);
}
return;
}
// Select a content folder
const selectedFolder = await vscode.window.showQuickPick(
pageFolders.map(f => ({ label: f.title, description: f.path, folder: f })),
{ placeHolder: 'Select a content folder' }
);
if (!selectedFolder) {
return;
}
// Prompt for file name
const fileName = await vscode.window.showInputBox({
prompt: 'Enter the file name (without extension)',
validateInput: (value) => {
if (!value) {
return 'File name is required';
}
if (!/^[a-zA-Z0-9-_]+$/.test(value)) {
return 'File name can only contain letters, numbers, hyphens, and underscores';
}
return null;
}
});
if (!fileName) {
return;
}
// Create the file
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders) {
vscode.window.showErrorMessage('No workspace folder found');
return;
}
const folderUri = vscode.Uri.joinPath(
workspaceFolders[0].uri,
selectedFolder.folder.path
);
const fileUri = vscode.Uri.joinPath(folderUri, `${fileName}.md`);
// Check if file already exists
try {
await vscode.workspace.fs.stat(fileUri);
vscode.window.showErrorMessage(`File "${fileName}.md" already exists`);
return;
} catch {
// File doesn't exist, continue
}
// Create basic front matter content
const date = new Date().toISOString();
const content = `---
title: ${fileName}
description:
date: ${date}
tags: []
---
# ${fileName}
Your content here...
`;
const encoder = new TextEncoder();
await vscode.workspace.fs.writeFile(fileUri, encoder.encode(content));
// Open the file
const doc = await vscode.workspace.openTextDocument(fileUri);
await vscode.window.showTextDocument(doc);
vscode.window.showInformationMessage(`Content "${fileName}.md" created successfully!`);
outputChannel.appendLine(`Created content: ${fileUri.fsPath}`);
} catch (error) {
vscode.window.showErrorMessage(`Failed to create content: ${error}`);
outputChannel.appendLine(`Error creating content: ${error}`);
}
})
);
// Check if running in virtual workspace
if (vscode.workspace.workspaceFolders) {
const isVirtual = vscode.workspace.workspaceFolders.some(
folder => folder.uri.scheme !== 'file'
);
if (isVirtual) {
outputChannel.appendLine('Running in virtual workspace mode');
vscode.window.showInformationMessage(
'Front Matter Lite is running in virtual workspace mode. Some features may be limited.',
'Learn More'
).then(selection => {
if (selection === 'Learn More') {
vscode.env.openExternal(
vscode.Uri.parse('https://frontmatter.codes/docs/virtual-workspaces')
);
}
});
}
}
outputChannel.appendLine('Front Matter Lite: All commands registered');
}
export function deactivate() {
if (outputChannel) {
outputChannel.dispose();
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"outDir": "out",
"lib": ["ES2020"],
"sourceMap": true,
"rootDir": "src",
"strict": true,
"strictNullChecks": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"exclude": ["node_modules", ".vscode-test"]
}
+53
View File
@@ -0,0 +1,53 @@
//@ts-check
'use strict';
const path = require('path');
/**@type {import('webpack').Configuration}*/
const config = {
target: 'webworker', // Web extension target
entry: './src/extension.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'extension-web.js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'
},
devtool: 'nosources-source-map',
externals: {
vscode: 'commonjs vscode' // The vscode-module is created on-the-fly and must be excluded
},
resolve: {
extensions: ['.ts', '.js'],
fallback: {
// Webpack 5 no longer polyfills Node.js core modules automatically
path: false,
fs: false,
os: false,
crypto: false,
stream: false,
assert: false,
buffer: false,
util: false
}
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
},
performance: {
hints: false
}
};
module.exports = config;