mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-07 01:13:08 +02:00
Add lite web extension structure with basic functionality
Co-authored-by: estruyf <2900833+estruyf@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
dist
|
||||
out
|
||||
*.vsix
|
||||
.vscode-test/
|
||||
@@ -0,0 +1,9 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
src/**
|
||||
.gitignore
|
||||
tsconfig.json
|
||||
webpack.config.js
|
||||
node_modules/**
|
||||
*.map
|
||||
*.ts
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user