Skip to content
Merged
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
174 changes: 174 additions & 0 deletions docs/dist/v1/chartifact.html-wrapper.umd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.Chartifact = global.Chartifact || {}));
})(this, (function(exports2) {
"use strict";
const htmlMarkdown = `<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TITLE}}</title>
<link rel="stylesheet" href="https://microsoft.github.io/chartifact/dist/v1/chartifact-toolbar.css" />
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.toolbar.umd.js"><\/script>
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.sandbox.umd.js"><\/script>
</head>

<body class="chartifact-body">

<header class="chartifact-toolbar"></header>

<main class="chartifact-main">
<textarea class="chartifact-source" id="source" spellcheck="false"
placeholder="Type your Chartifact markdown here...">{{TEXTAREA_CONTENT}}</textarea>

<div class="chartifact-preview" id="preview"></div>

</main>

{{HTML_MARKDOWN_JS}}

</body>

</html>`;
const htmlMarkdownJs = `/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
window.addEventListener('DOMContentLoaded', () => {
const textarea = document.querySelector('#source');
const sandbox = new Chartifact.sandbox.Sandbox('#preview', textarea.value, {
onApprove: (message) => {
//Here you can approve unapproved specs per your own policy
const { specs } = message;
return specs;
},
onError: (error) => {
console.error('Sandbox error:', error);
},
});
textarea.addEventListener('input', () => {
sandbox.send(textarea.value);
});
const toolbar = Chartifact.toolbar.create('.chartifact-toolbar', { tweakButton: true, textarea });
toolbar.manageTextareaVisibilityForAgents();
});
`;
const htmlJson = `<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TITLE}}</title>
<link rel="stylesheet" href="https://microsoft.github.io/chartifact/dist/v1/chartifact-toolbar.css" />
<script src="https://unpkg.com/js-yaml/dist/js-yaml.min.js"><\/script>
<script src="https://cdn.jsdelivr.net/npm/vega@5.29.0"><\/script>
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.toolbar.umd.js"><\/script>
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.compiler.umd.js"><\/script>
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.sandbox.umd.js"><\/script>
</head>

<body class="chartifact-body">

<header class="chartifact-toolbar"></header>

<main class="chartifact-main">
<textarea class="chartifact-source" id="source" spellcheck="false"
placeholder="Type your Chartifact json here...">{{TEXTAREA_CONTENT}}</textarea>

<div class="chartifact-preview" id="preview"></div>

</main>

{{HTML_JSON_JS}}

</body>

</html>`;
const htmlJsonJs = `/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
window.addEventListener('DOMContentLoaded', () => {
const textarea = document.querySelector('#source');
let sandbox;
const render = () => {
const json = textarea.value;
let markdown;
try {
const interactiveDocument = JSON.parse(json);
if (typeof interactiveDocument !== 'object') {
markdown = 'Invalid Interactive Document JSON';
}
else {
markdown = Chartifact.compiler.targetMarkdown(interactiveDocument);
}
}
catch (error) {
markdown = 'Failed to parse Interactive Document JSON';
}
if (!sandbox) {
sandbox = new Chartifact.sandbox.Sandbox('#preview', markdown, {
onApprove: (message) => {
//Here you can approve unapproved specs per your own policy
const { specs } = message;
return specs;
},
onError: (error) => {
console.error('Sandbox error:', error);
},
});
}
else {
sandbox.send(markdown);
}
};
textarea.addEventListener('input', render);
render();
const toolbar = Chartifact.toolbar.create('.chartifact-toolbar', { tweakButton: true, textarea, mode: 'json' });
toolbar.manageTextareaVisibilityForAgents();
});
`;
function htmlMarkdownWrapper(title, markdown) {
const template = htmlMarkdown;
const result = template.replace("{{TITLE}}", () => escapeHtml(title)).replace("{{HTML_MARKDOWN_JS}}", () => `<script>
${htmlMarkdownJs}
<\/script>`).replace("{{TEXTAREA_CONTENT}}", () => escapeTextareaContent(markdown));
return result;
}
function htmlJsonWrapper(title, json) {
const template = htmlJson;
const result = template.replace("{{TITLE}}", () => escapeHtml(title)).replace("{{HTML_JSON_JS}}", () => `<script>
${htmlJsonJs}
<\/script>`).replace("{{TEXTAREA_CONTENT}}", () => escapeTextareaContent(json));
return result;
}
function escapeTextareaContent(text) {
return text.replace(/<\/textarea>/gi, "&lt;/textarea&gt;").replace(/<script/gi, "&lt;script").replace(/<\/script>/gi, "&lt;/script&gt;");
}
function escapeHtml(text) {
return text.replace(/[&<>"']/g, (char) => {
switch (char) {
case "&":
return "&amp;";
case "<":
return "&lt;";
case ">":
return "&gt;";
case '"':
return "&quot;";
case "'":
return "&#39;";
default:
return char;
}
});
}
const index = {
htmlMarkdownWrapper,
htmlJsonWrapper
};
exports2.htmlWrapper = index;
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
}));
1 change: 1 addition & 0 deletions packages/html-wrapper/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ js
!dist
dist/html**.*
dist/index.mjs
dist/umd
1 change: 1 addition & 0 deletions packages/html-wrapper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"clean": "rimraf dist && rimraf js",
"tsc-client": "tsc -p ./tsconfig.json",
"tsc-server": "tsc -p ./tsconfig-server.json",
"bundle": "vite build --config vite.bundle.config.js",
"build": "npm run clean && npm run tsc-server && npm run tsc-client && npm run resources",
"build:05": "npm run build"
},
Expand Down
142 changes: 142 additions & 0 deletions packages/html-wrapper/test/test-umd.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML Wrapper UMD Test</title>
<link rel="stylesheet" href="https://microsoft.github.io/chartifact/dist/v1/chartifact-toolbar.css" />
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
.test-section {
margin-bottom: 40px;
border: 1px solid #ddd;
padding: 20px;
border-radius: 5px;
}
h1 {
color: #333;
}
h2 {
color: #666;
margin-top: 0;
}
textarea {
width: 100%;
min-height: 150px;
padding: 10px;
font-family: monospace;
border: 1px solid #ccc;
border-radius: 4px;
margin-bottom: 10px;
}
#preview-md, #preview-json {
border: 1px solid #ccc;
padding: 10px;
min-height: 200px;
background: #f9f9f9;
border-radius: 4px;
}
.success {
color: green;
font-weight: bold;
}
.error {
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<h1>HTML Wrapper UMD Bundle Test</h1>

<div class="test-section">
<h2>Test 1: Check if UMD bundle loads</h2>
<div id="load-test"></div>
</div>

<div class="test-section">
<h2>Test 2: Markdown Viewer</h2>
<div class="chartifact-toolbar-md"></div>
<textarea id="source-md" spellcheck="false"># Hello Chartifact

This is a test of the markdown viewer.</textarea>
<div id="preview-md"></div>
<div id="md-test"></div>
</div>

<div class="test-section">
<h2>Test 3: JSON Viewer</h2>
<div class="chartifact-toolbar-json"></div>
<textarea id="source-json" spellcheck="false">{
"title": "Test Document",
"components": [
{
"type": "text",
"content": "# Hello from JSON\n\nThis is a test."
}
]
}</textarea>
<div id="preview-json"></div>
<div id="json-test"></div>
</div>

<!-- Load dependencies first -->
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.toolbar.umd.js"></script>
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.sandbox.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vega@5.29.0"></script>
<script src="https://unpkg.com/js-yaml/dist/js-yaml.min.js"></script>
<script src="https://microsoft.github.io/chartifact/dist/v1/chartifact.compiler.umd.js"></script>

<!-- Load html-wrapper UMD bundle -->
<script src="../../docs/dist/v1/chartifact.html-wrapper.umd.js"></script>

<script>
// Test 1: Check if the module loaded
const loadTestDiv = document.getElementById('load-test');
if (typeof Chartifact !== 'undefined' && Chartifact.htmlWrapper) {
loadTestDiv.innerHTML = '<span class="success">✓ UMD bundle loaded successfully!</span>';
loadTestDiv.innerHTML += '<br>Available functions: ' + Object.keys(Chartifact.htmlWrapper).join(', ');
} else {
loadTestDiv.innerHTML = '<span class="error">✗ Failed to load UMD bundle</span>';
}

// Test 2: Markdown Viewer and Test 3: JSON Viewer
function initializeViewers() {
const mdTestDiv = document.getElementById('md-test');
try {
const result = Chartifact.htmlWrapper.initMarkdownViewer('#source-md', '#preview-md', '.chartifact-toolbar-md');
if (result && result.sandbox && result.toolbar) {
mdTestDiv.innerHTML = '<span class="success">✓ Markdown viewer initialized successfully!</span>';
} else {
mdTestDiv.innerHTML = '<span class="error">✗ Markdown viewer initialization returned unexpected result</span>';
}
} catch (error) {
mdTestDiv.innerHTML = '<span class="error">✗ Error initializing markdown viewer: ' + error.message + '</span>';
}

const jsonTestDiv = document.getElementById('json-test');
try {
const result = Chartifact.htmlWrapper.initJsonViewer('#source-json', '#preview-json', '.chartifact-toolbar-json');
if (result && result.sandbox && result.toolbar) {
jsonTestDiv.innerHTML = '<span class="success">✓ JSON viewer initialized successfully!</span>';
} else {
jsonTestDiv.innerHTML = '<span class="error">✗ JSON viewer initialization returned unexpected result</span>';
}
} catch (error) {
jsonTestDiv.innerHTML = '<span class="error">✗ Error initializing JSON viewer: ' + error.message + '</span>';
}
}

// Handle case where DOMContentLoaded may have already fired
if (document.readyState === 'loading') {
window.addEventListener('DOMContentLoaded', initializeViewers);
} else {
initializeViewers();
}
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions packages/html-wrapper/umd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/
export { default as htmlWrapper } from './dist/index.mjs';
42 changes: 42 additions & 0 deletions packages/html-wrapper/vite.bundle.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { defineConfig } from 'vite';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

const commonOutputConfig = {
format: 'umd',
name: 'Chartifact',
extend: true,
globals: {
'vega': 'vega',
'vega-lite': 'vegaLite',
},
entryFileNames: 'chartifact.html-wrapper.umd.js',
};

export default defineConfig({
build: {
lib: {
entry: './umd.ts',
},
minify: false,
emptyOutDir: false,
rollupOptions: {
// External dependencies that the library expects consumers to provide
external: ['vega', 'vega-lite'],
output: [
{
...commonOutputConfig,
dir: './dist/umd',
},
{
...commonOutputConfig,
dir: '../../docs/dist/v1',
},
],
plugins: [
resolve(), // Resolves Node modules
commonjs(), // Converts CommonJS to ES6
],
},
},
});