This guide provides detailed documentation for developers using SquibView in their applications.
- Installation
- Build Formats
- Basic Usage
- Configuration Options
- Content Types
- API Reference
- React Integration
- Plugin System
- Event System
- Examples
- Development and Testing
npm install squibview<!-- Autoload build (recommended) - libraries load automatically when needed -->
<script type="module">
import SquibView from 'https://unpkg.com/squibview/dist/squibview.autoload.esm.min.js';
const editor = new SquibView('#editor');
</script>
<link rel="stylesheet" href="https://unpkg.com/squibview/dist/squibview.min.css">SquibView is available in multiple formats:
The autoload build provides zero-configuration setup with automatic loading of libraries from CDN when content requires them.
<link rel="stylesheet" href="https://unpkg.com/squibview/dist/squibview.min.css">
<script type="module">
import SquibView from 'https://unpkg.com/squibview/dist/squibview.autoload.esm.min.js';
const editor = new SquibView('#editor', {
initialContent: '# Hello\n\n```mermaid\ngraph TD\n A --> B\n```'
// Mermaid loads automatically when needed!
});
</script>What loads automatically:
- Mermaid (377KB) - When using
```mermaidblocks - Highlight.js (45KB) - When using code blocks
- MathJax (1.3MB) - When using
$$math$$or```mathblocks - Leaflet (142KB) - When using
```geojsonor```topojson - Three.js (1.1MB) - When using
```stl3d
<!-- Optional dependencies for advanced features -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
<!-- SquibView (markdown-it is now bundled!) -->
<link rel="stylesheet" href="../dist/squibview.min.css">
<script type="module">
import SquibView from '../dist/squibview.esm.min.js';
const editor = new SquibView('#editor');
</script><!-- Import map for external dependencies -->
<script type="importmap">
{
"imports": {
"markdown-it": "https://esm.sh/markdown-it@14.1.0",
"tiny-emitter": "https://esm.sh/tiny-emitter@2.1.0",
"diff-match-patch": "https://esm.sh/diff-match-patch@1.0.5"
}
}
</script>
<!-- Optional dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<!-- SquibView lean build -->
<script type="module">
import SquibView from '../dist/squibview.esm-lean.min.js';
const editor = new SquibView('#editor');
</script><!-- Optional dependencies for advanced features -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
<!-- SquibView (markdown-it is now bundled!) -->
<link rel="stylesheet" href="../dist/squibview.min.css">
<script src="../dist/squibview.umd.min.js"></script>
<script>
const editor = new SquibView('#editor');
</script><!-- Required dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/14.1.0/markdown-it.min.js"></script>
<script src="https://unpkg.com/tiny-emitter@2.1.0/dist/tinyemitter.min.js"></script>
<script src="https://unpkg.com/diff-match-patch@1.0.5/index.js"></script>
<!-- Optional dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<!-- SquibView lean build -->
<script src="../dist/squibview.umd-lean.min.js"></script>
<script>
const editor = new SquibView('#editor');
</script><!-- SquibView -->
<link rel="stylesheet" href="../dist/squibview.min.css">
<script src="../dist/squibview.standalone.min.js"></script>
<script>
const editor = new SquibView('#editor');
</script>const editor = new SquibView('#editorContainer', {
// Configuration options
});// Set Markdown content
editor.setContent('# Hello World\n\nThis is a test.', 'md');
// Set HTML content
editor.setContent('<h1>Hello World</h1><p>This is a test.</p>', 'html');
// Set CSV content
editor.setContent('name,age\nJohn,30\nJane,25', 'csv');// Switch to source view
editor.setView('src');
// Switch to rendered view
editor.setView('html');
// Switch to split view
editor.setView('split');const editor = new SquibView('#editorContainer', {
initialContent: '', // Initial content to load
inputContentType: 'md', // Type of content ('md', 'html', 'reveal', 'csv', 'tsv')
showControls: true, // Whether to show control buttons
titleShow: false, // Whether to show the title section
titleContent: '', // Content for the title section
initialView: 'split', // Initial view mode ('src', 'html', 'split')
baseClass: 'squibview', // Base CSS class for styling
});const editor = new SquibView('#editor', {
autoload: {
// Loading strategies: 'auto' | 'ondemand' | 'none' | function
mermaid: 'ondemand', // Load when mermaid blocks detected (default)
hljs: 'ondemand', // Load when code blocks detected (default)
mathjax: 'ondemand', // Load when math detected (default)
leaflet: 'ondemand', // Load when map blocks detected (default)
three: 'ondemand', // Load when STL blocks detected (default)
// Use custom CDN URLs
cdnUrls: {
mermaid: {
script: 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js'
}
},
// Enable debug logging (silent by default)
debug: false
}
});const editor = new SquibView('#editorContainer', {
preserveImageTags: true, // Whether to keep original image URLs in source view
// When true: images remain as <img> tags with original URLs
// When false: images are converted to data URLs
// Note: Images are always converted to data URLs when copying
});Detailed Explanation of preserveImageTags:
The preserveImageTags option (boolean, defaults to true) controls how SquibView handles <img> tags when processing and displaying Markdown content, particularly in the source view and during copy operations.
-
preserveImageTags: true(Default Behavior):- Source View: When SquibView renders Markdown,
<img>tags will retain their originalsrcattributes (e.g.,https://example.com/image.pngor../images/local.jpg). This is generally preferred for maintaining a clean and readable Markdown source, as it keeps image references as links rather than embedding large data strings. - Rendered View: Images are displayed as usual by the browser fetching them from their
srcURLs. - Implications: Requires the image URLs to be accessible by the browser. If images are on a local filesystem or a private network not accessible to the user viewing the rendered output, they may appear broken.
- Source View: When SquibView renders Markdown,
-
preserveImageTags: false:- Source View & Rendered View: When SquibView renders Markdown, it will attempt to fetch each image, convert it to a base64 data URL, and embed this data URL directly into the
srcattribute of the<img>tag. Both the source view (if you were to inspect the HTML generated byrenderMarkdownbefore it's placed in the DOM) and the live rendered view will use these data URLs. - Implications:
- Portability: Makes the HTML output more self-contained, as images are embedded. This is useful if the HTML needs to be displayed in environments where the original image URLs might not be accessible.
- Performance: Can increase the initial size of the HTML content significantly if there are many or large images. Fetching and converting images to data URLs can also add a small delay to the rendering process.
- Security: Images are fetched by the SquibView instance. Ensure that the environment running SquibView has access to the image URLs. Cross-origin restrictions might apply if images are on different domains and the server doesn't set appropriate CORS headers (though SquibView attempts to use
crossOrigin = 'anonymous'for images, which helps for CORS-enabled servers).
- Source View & Rendered View: When SquibView renders Markdown, it will attempt to fetch each image, convert it to a base64 data URL, and embed this data URL directly into the
-
Behavior during
copyHTML()(Copy Rendered):- Regardless of the
preserveImageTagssetting, when the user clicks the "Copy Rendered" button (which calls thecopyHTML()method), SquibView will always attempt to convert all images within the copied content to data URLs. - Rationale: This ensures maximum portability of the copied HTML. If the user pastes this HTML into an email client, another document, or a different web page, the images will be embedded and should display correctly without relying on external links that might break or be inaccessible in the new context.
- Regardless of the
When to Use Which Setting:
- Use
preserveImageTags: true(default) if:- You prefer your Markdown source to remain clean with linked images.
- All image URLs are expected to be accessible by the end-user's browser.
- You are primarily concerned with the live view and not necessarily with generating fully self-contained HTML snippets directly from the source view rendering.
- Use
preserveImageTags: falseif:- You need the rendered output in the SquibView panel to use embedded data URLs by default (e.g., for immediate display in a restricted environment or for a specific type of export where data URLs are preferred from the live view itself).
- You understand the potential performance and size implications.
const editor = new SquibView('#editorContainer', {
onReplaceSelectedText: (selectionData) => {
// Handle text selection
return 'replacement text'; // Return string to replace selection
}
});- Supports GitHub-flavored Markdown
- Renders Mermaid diagrams
- Syntax highlighting for code blocks
- Table formatting
- Inline SVG graphics
- Renders complete HTML pages
- Supports embedded iframes
- Preserves HTML structure
- Converts markdown to RevealJS slides
- Splits content on '---' delimiters
- Supports Mermaid diagrams in slides
- Renders tabular data
- Converts to markdown tables
- Supports different delimiters (comma, tab, semicolon, space)
// Content Management
editor.setContent(content, contentType) // Set content
editor.getContent() // Get current content
editor.getMarkdownSource() // Get markdown source
editor.getHTMLSource() // Get HTML source
// View Management
editor.setView(view) // Set view mode
editor.toggleView() // Toggle between views
editor.controlsShow(show) // Show/hide controls
editor.titleShow(show) // Show/hide title
editor.titleSetContent(content) // Set title content
editor.titleGetContent() // Get title content
// Copy Operations
editor.copySource() // Copy source content
editor.copyHTML() // Copy rendered HTML
// Revision History
editor.revisionUndo() // Undo last change
editor.revisionRedo() // Redo last change
editor.revisionSet(index) // Set to specific revision
editor.revisionNumRevsions() // Get number of revisions
editor.revisionGetCurrentIndex() // Get current revision index
// Diff Viewing (New in v1.0.13)
editor.getSourceDiff(options) // Get diff data between revisions
editor.getSourceDiffHTML(options) // Get side-by-side diff HTML
editor.getSourceDiffInline(options) // Get inline diff HTML (blue/red)Compare different revisions of your content with visual diff displays.
Returns raw diff data between two revisions.
// Get diff between current and previous revision
const diffData = editor.getSourceDiff();
// Get diff between specific revisions
const diffData = editor.getSourceDiff({
fromIndex: 0, // Starting revision (-1 for initial state)
toIndex: 3 // Ending revision
});
// Returns: { added, removed, changed, stats, patches }Returns side-by-side diff visualization as HTML.
// Compare current vs previous
const diffHTML = editor.getSourceDiffHTML();
// Compare specific revisions
const diffHTML = editor.getSourceDiffHTML({
fromIndex: 1,
toIndex: 5,
showLineNumbers: true // Optional
});
// Insert into page
document.getElementById('diff-view').innerHTML = diffHTML;Returns inline diff with blue additions and red strikethrough deletions.
// Get inline diff
const inlineHTML = editor.getSourceDiffInline({
fromIndex: 0,
toIndex: -1 // Compare against current
});
// Styling: additions in blue, deletions in red with strikethrough// Get current selection
const selection = editor.getCurrentSelection();
// Replace selected text
editor.replaceSelectedText('new text', selection);
// Make selection editable/non-editable
editor.setSelectionEditable(true, selection);
// Toggle selection lock
editor.toggleSelectionLock(selection);
// Register selection callback
const unsubscribe = editor.onTextSelected((selectionData) => {
console.log('Selected:', selectionData.text);
});import { SquibViewReact } from 'squibview/react';
function App() {
return (
<SquibViewReact
initialContent="# Hello World"
inputContentType="md"
showControls={true}
/>
);
}<SquibViewReact
// Basic props
initialContent=""
inputContentType="md"
showControls={true}
titleShow={false}
titleContent=""
initialView="split"
// Image handling
preserveImageTags={true}
// Event handlers
onContentChange={(content, type) => {}}
onViewChange={(view) => {}}
onTextSelected={(selectionData) => {}}
/>const myPlugin = {
name: 'myPlugin',
init: (editor) => {
// Plugin initialization
},
destroy: () => {
// Cleanup
}
};
// Register plugin
editor.registerPlugin(myPlugin);editor.registerRenderer('custom', {
render: (source) => {
// Render source to HTML
return html;
},
sourceToOutput: (source) => {
// Convert source to output format
return output;
},
outputToSource: (output) => {
// Convert output back to source
return source;
},
operations: {
customOp: (source) => {
// Custom operation
return modifiedSource;
}
},
buttons: [
{
label: 'Custom',
action: 'customOp',
title: 'Custom operation'
}
]
});editor.events.on('content:change', (content, type) => {});
editor.events.on('view:change', (view) => {});
editor.events.on('text:selected', (selectionData) => {});
editor.events.on('markdown:rendered', (markdown, html) => {});
editor.events.on('html:rendered', (html) => {});
editor.events.on('revision:undo', (content, type) => {});
editor.events.on('revision:redo', (content, type) => {});
editor.events.on('revision:set', (index, content, type) => {});
editor.events.on('controls:visibility', (show) => {});
editor.events.on('title:visibility', (show) => {});
editor.events.on('title:content', (content) => {});
editor.events.on('layout:change', (view, dimensions) => {});
editor.events.on('renderer:registered', (type, config) => {});const editor = new SquibView('#editor', {
initialContent: '# Hello World\n\nThis is a test.',
inputContentType: 'md',
showControls: true,
initialView: 'split'
});const editor = new SquibView('#editor', {
initialContent: 'name,age\nJohn,30\nJane,25',
inputContentType: 'csv',
showControls: true,
initialView: 'html'
});const editor = new SquibView('#editor', {
initialContent: '# Slide 1\n\nContent\n\n---\n\n# Slide 2\n\nMore content',
inputContentType: 'reveal',
showControls: true,
initialView: 'html'
});import { SquibViewReact } from 'squibview/react';
function App() {
return (
<SquibViewReact
initialContent="# Image Example\n\n"
inputContentType="md"
preserveImageTags={true}
onContentChange={(content, type) => {
console.log('Content changed:', content);
}}
/>
);
}This section provides information for developers contributing to SquibView or setting up a local development environment.
For local development, a convenient script dev-bump-build-test.sh is provided in the root of the repository. This script automates several common tasks:
- Bumps the Patch Version: It increments the patch version number of the library (e.g., from
0.0.38to0.0.39). - Sets a Prerelease Identifier: It then sets a development prerelease identifier (e.g.,
0.0.39-dev.0). This usesnpm version prepatch --preid devinternally. - Updates
src/version.js: The script runstools/updateVersion.jsto propagate the new version frompackage.jsontosrc/version.js, ensuring the library reports the correct version at runtime. - Builds the Library: It performs a full build of SquibView.
- Runs Tests: It executes all unit and integration tests.
- Logs Output: All output from the script (build and test logs) is displayed in the terminal and also saved to
tests/log.outfor easier debugging.
Usage:
To run the script, navigate to the root of the SquibView repository in your terminal and execute:
./dev-bump-build-test.shThis script is particularly useful for quickly testing changes with an updated version number in a development context without creating git tags.
For more comprehensive information on the development workflow, versioning strategy, running tests, and debugging, please refer to the CONTRIBUTING.md file.
For browser environments, you can use a <script> tag pointing to a CDN:
<script src="https://unpkg.com/squibview/dist/squibview.standalone.umd.min.js"></script>Or, if you have it locally:
<script src="../dist/squibview.standalone.umd.min.js"></script>const editor = new SquibView('#editorContainer', {
// Configuration options
});