Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
560 changes: 559 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/chrome-extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist/
*.zip
node_modules/
.DS_Store
108 changes: 108 additions & 0 deletions packages/chrome-extension/INSTALL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Installing the Chartifact Chrome Extension

This guide helps you install and test the Chartifact Chrome extension for viewing Interactive Document files.

## Quick Start

### 1. Build the Extension

From the repository root:

```bash
# Install dependencies (if not already done)
npm install

# Build the extension
npm run build --workspace=@microsoft/chartifact-chrome-extension
```

### 2. Load in Chrome

1. Open Chrome and navigate to `chrome://extensions/`
2. Enable **Developer mode** (toggle in the top-right corner)
3. Click **Load unpacked**
4. Select the folder: `packages/chrome-extension/dist`
5. The extension should now appear in your extensions list

### 3. Test the Extension

**Option A: Use the test page**
1. Open `packages/chrome-extension/test.html` in Chrome
2. Click on one of the test file links
3. Look for the "📊 View as Interactive Document" button

**Option B: Test with local files**
1. Download any `.idoc.json` or `.idoc.md` file
2. Open it in Chrome (drag and drop into browser)
3. The extension should detect it and show the view button

### 4. Using the Extension

- **Automatic Detection**: The extension automatically detects `.idoc.md` and `.idoc.json` files
- **View Button**: Look for the floating "📊 View as Interactive Document" button in the top-right
- **Extension Popup**: Click the extension icon to see status and controls
- **Secure Rendering**: All content is rendered in a sandboxed iframe for security

## Example Files to Test

You can test with these example files in the repository:
- `packages/examples/json/seattle-weather/6.idoc.json`
- `packages/chrome-extension/test.idoc.json` (simple test file)

## Troubleshooting

### Extension not detecting files
- Ensure the file has `.idoc.md` or `.idoc.json` extension
- Check that the extension is enabled in `chrome://extensions/`
- Try refreshing the page

### View button not appearing
- Make sure you're viewing an actual idoc file (not just a page that links to one)
- Check browser console for any JavaScript errors
- Verify the extension has proper permissions

### Viewer not loading
- Check browser console for errors
- Ensure the chartifact libraries are properly loaded
- Verify the file content is valid Interactive Document format

### Permission issues
- The extension needs `activeTab` permission to function
- For local files, you may need to enable "Allow access to file URLs" in the extension details

## For Developers

### Building from Source
```bash
cd packages/chrome-extension
npm run build # Build the extension
npm run package # Create distributable ZIP
npm run dev # Watch mode for development
```

### Extension Structure
- `src/manifest.json` - Extension manifest
- `src/background.ts` - Service worker
- `src/content.ts` - Content script for detection and injection
- `src/popup.ts/html` - Extension popup interface
- `dist/` - Built extension (load this folder in Chrome)

### Distribution
- Run `npm run package` to create `chartifact-chrome-extension.zip`
- This ZIP can be uploaded to Chrome Web Store or distributed manually

## Security

The extension follows security best practices:
- Minimal permissions (only `activeTab` and `storage`)
- Sandboxed iframe rendering
- No remote code execution
- Content Security Policy compliant

## Support

For issues or questions:
1. Check the browser console for error messages
2. Verify file format with the Interactive Document schema
3. Test with the provided example files first
4. Create an issue in the Chartifact repository
97 changes: 97 additions & 0 deletions packages/chrome-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Chartifact Chrome Extension

A Chrome extension for viewing Interactive Document files (*.idoc.md and *.idoc.json) with rich visualizations and charts.

## Features

- **File Detection**: Automatically detects `.idoc.md` and `.idoc.json` files in web pages
- **Secure Rendering**: Uses sandboxed iframe rendering for security
- **Rich Visualizations**: Supports charts, graphs, and interactive elements
- **Easy Access**: Simple button to open the viewer overlay

## Installation

### For Development

1. Build the extension:
```bash
cd packages/chrome-extension
npm run build
```

2. Load the extension in Chrome:
- Open Chrome and go to `chrome://extensions/`
- Enable "Developer mode" (toggle in top right)
- Click "Load unpacked"
- Select the `packages/chrome-extension/dist` folder

### For Distribution

1. Package the extension:
```bash
cd packages/chrome-extension
npm run package
```

2. This creates `chartifact-chrome-extension.zip` that can be uploaded to the Chrome Web Store.

## Usage

1. Navigate to any `.idoc.md` or `.idoc.json` file in your browser
2. The extension will automatically detect the file and show a "View as Interactive Document" button
3. Click the button to open the Chartifact viewer overlay
4. You can also use the extension popup (click the extension icon) to open the viewer

## Supported File Types

- **`.idoc.md`**: Interactive Document markdown files
- **`.idoc.json`**: Interactive Document JSON files

## Technical Details

The extension uses:
- **Manifest V3** for modern Chrome extension standards
- **Content Scripts** to detect and inject the viewer
- **Sandbox Rendering** for security using iframes
- **UMD Bundles** for the Chartifact compiler and sandbox libraries

## Security

The extension follows security best practices:
- Uses sandboxed iframe rendering to isolate document content
- Minimal permissions (only `activeTab` and `storage`)
- Content Security Policy compliance
- No remote code execution

## Development

### Build Process

1. TypeScript compilation (`npm run tsc`)
2. Vite bundling (`npm run bundle`)
3. Resource copying (`npm run resources`)

### File Structure

```
src/
├── manifest.json # Extension manifest
├── background.ts # Service worker
├── content.ts # Content script
├── popup.ts # Popup script
└── popup.html # Popup HTML

dist/ # Built extension
├── manifest.json
├── background.js
├── content.js
├── popup.js
├── popup.html
├── chartifact.sandbox.js
├── chartifact.compiler.js
└── icons/
```

## License

MIT License - see LICENSE file for details.
30 changes: 30 additions & 0 deletions packages/chrome-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@microsoft/chartifact-chrome-extension",
"version": "1.0.0",
"description": "Chrome extension for viewing Interactive Document files (*.idoc.md and *.idoc.json)",
"type": "module",
"private": true,
"main": "dist/background.js",
"scripts": {
"clean": "rimraf dist",
"resources": "node scripts/resources.mjs",
"prebuild": "npm run resources",
"tsc": "tsc -p .",
"build": "npm run tsc && npm run bundle",
"bundle": "vite build",
"build:08": "npm run build",
"package": "cd dist && zip -r ../chartifact-chrome-extension.zip .",
"dev": "vite build --watch"
},
"dependencies": {
"@microsoft/chartifact-sandbox": "1.0.0",
"@microsoft/chartifact-compiler": "1.0.0",
"@microsoft/chartifact-schema": "1.0.0"
},
"devDependencies": {
"@types/chrome": "^0.0.280",
"vite": "^5.0.0"
},
"author": "Dan Marshall",
"license": "MIT"
}
84 changes: 84 additions & 0 deletions packages/chrome-extension/scripts/resources.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const distDir = path.join(__dirname, '..', 'dist');
const srcDir = path.join(__dirname, '..', 'src');

// Ensure dist directory exists
if (!fs.existsSync(distDir)) {
fs.mkdirSync(distDir, { recursive: true });
}

// Copy static files
const staticFiles = [
'manifest.json',
'popup.html'
];

for (const file of staticFiles) {
const srcFile = path.join(srcDir, file);
const destFile = path.join(distDir, file);

if (fs.existsSync(srcFile)) {
fs.copyFileSync(srcFile, destFile);
console.log(`Copied ${file}`);
}
}

// Copy toolbar CSS
const toolbarCssSource = path.join(__dirname, '..', '..', 'toolbar', 'chartifact-toolbar.css');
const toolbarCssDest = path.join(distDir, 'chartifact-toolbar.css');
if (fs.existsSync(toolbarCssSource)) {
fs.copyFileSync(toolbarCssSource, toolbarCssDest);
console.log('Copied chartifact-toolbar.css');
}

// Copy UMD bundles for use in content script
const docsDir = path.join(__dirname, '..', '..', '..', 'docs', 'dist', 'v1');
const bundleFiles = [
'chartifact.sandbox.umd.js',
'chartifact.compiler.umd.js',
'chartifact.host.umd.js'
];

for (const file of bundleFiles) {
const srcFile = path.join(docsDir, file);
const destFile = path.join(distDir, file.replace('.umd.js', '.js'));

if (fs.existsSync(srcFile)) {
fs.copyFileSync(srcFile, destFile);
console.log(`Copied ${file} as ${path.basename(destFile)}`);
} else {
console.warn(`Bundle file not found: ${srcFile}`);
}
}

// Create icons directory and placeholder icons
const iconsDir = path.join(distDir, 'icons');
if (!fs.existsSync(iconsDir)) {
fs.mkdirSync(iconsDir, { recursive: true });
}

// Create simple text-based placeholder icons (in production, use actual PNG files)
const iconSizes = [16, 32, 48, 128];
for (const size of iconSizes) {
const iconFile = path.join(iconsDir, `icon-${size}.png`);

// Create a minimal fake PNG-like file to make Chrome happy
// In production, these should be proper PNG icon files
const header = `PNG ICON ${size}x${size}`;
const padding = Buffer.alloc(Math.max(0, 100 - header.length), 0);
const iconBuffer = Buffer.concat([Buffer.from(header), padding]);
fs.writeFileSync(iconFile, iconBuffer);
}

console.log('Resources copied successfully');
26 changes: 26 additions & 0 deletions packages/chrome-extension/src/background.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/

// Background service worker for the Chrome extension
chrome.runtime.onInstalled.addListener(() => {
console.log('Chartifact Interactive Document Viewer installed');
});

// Handle content script messages
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'IDOC_FILE_DETECTED') {
// Could show notification or update badge
console.log('Interactive Document file detected:', request.url);
sendResponse({ success: true });
}
});

// Handle action button clicks
chrome.action.onClicked.addListener((tab) => {
// Open the viewer for the current tab if it's an idoc file
if (tab.url && (tab.url.includes('.idoc.md') || tab.url.includes('.idoc.json'))) {
chrome.tabs.sendMessage(tab.id!, { type: 'OPEN_VIEWER' });
}
});
Loading