@pfmcodes/caret
v0.1.5
Published
The official code editor engine for lexius
Maintainers
Readme
Caret
A lightweight, feature-rich code editor with real-time syntax highlighting and custom caret rendering. Built with vanilla JavaScript and powered by Highlight.js, caret delivers a smooth coding experience with professional-grade features.
✨ Features
- 🎨 Live Syntax Highlighting - Real-time code highlighting powered by Highlight.js
- 🖱️ Custom Caret - Smooth, pixel-perfect Caret positioning and rendering
- 🔢 Line Numbers - Built-in line counter with dynamic updates
- ⌨️ Smart Indentation - Tab/Shift+Tab support for indenting/unindenting code blocks
- 🎭 Theme Support - Multiple syntax highlighting themes (light/dark modes)
- 📜 Smooth Scrolling - Synchronized scrolling for code, highlights, and line numbers
- 📦 ES Modules - Modern ESM architecture for easy integration
- 🎯 TypeScript Ready - Full TypeScript definitions included
- ⚡ Lightweight - Pure JavaScript, no heavy frameworks required
📋 Table of Contents
What's-New?
New fresh package directory, now the heavy work is done in the cloud while minimizing package size to just a few Kilo Bytes.
🚀 Installation
NPM
npm install @pfmcodes/caretYarn
yarn add @pfmcodes/caretPNPM
pnpm add @pfmcodes/caret🏁 Quick Start
Basic Usage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Caret</title>
<link rel="stylesheet" href="node_modules/caret/index.css">
</head>
<body>
<div id="editor"></div>
<script type="module">
import editor from './node_modules/@pfmcodes/caret/esm/index.js';
const instance = await editor.editor.createEditor(
document.getElementById('editor'),
{
value: 'console.log("Hello, World!");',
language: 'javascript',
theme: 'hybrid'
}
);
</script>
</body>
</html>ES Module Import
import editor from '@pfmcodes/caret';
// Create editor instance
const editorInstance = await editor.editor.createEditor(
document.getElementById('editor'),
{
value: '', // Initial code
language: 'python', // Programming language
theme: 'monokai' // Highlight.js theme
}
);📁 Project Structure
caret/
├── esm/ # ES Module builds
├── highlight.js/ # Syntax highlighting support
├── types/ # TypeScript type definitions
├── index.css # Core styles
├── package.json # Package configuration
├── .gitignore # Git ignore rules
├── .npmignore # NPM ignore rules
└── LICENSE # MIT License💡 Usage
JavaScript Editor
import editor from '@pfmcodes/caret'; // auto link to commonjs version
const jsEditor = await editor.editor.createEditor(
document.getElementById('js-editor'),
{
value: `function greet(name) {
return \`Hello, \${name}!\`;
}
console.log(greet('World'));`,
language: 'javascript',
theme: 'atom-one-dark'
}
);Python Editor
const pyEditor = await editor.createEditor(
document.getElementById('py-editor'),
{
value: `def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print([fibonacci(i) for i in range(10)])`,
language: 'python',
theme: 'github-dark'
}
);Empty Editor (Start from Scratch)
const emptyEditor = await editor.createEditor(
document.getElementById('empty-editor'),
{
value: '',
language: 'javascript',
theme: 'hybrid'
}
);🎨 Customization
Custom Styling
The editor comes with default styles that you can override:
/* Custom editor styling */
#editor {
width: 800px !important;
height: 500px !important;
font-size: 16px !important;
}
/* Customize line numbers */
.Caret-lineCounter {
background: #1e1e1e;
}
.Caret-lineCounter-number {
font-size: 12px;
padding: 0 8px;
}
/* Customize the textarea */
#Caret-textarea {
font-family: 'Fira Code', 'Consolas', monospace;
line-height: 1.6;
}
/* Customize the Caret */
#Caret-caret {
background: #00ff00 !important;
width: 3px !important;
}🎯 Advanced Features
Multi-Language Support
Caret supports all languages available in Highlight.js:
// JavaScript
await editor.createEditor(el, { language: 'javascript', ... });
// Python
await editor.createEditor(el, { language: 'python', ... });
// TypeScript
await editor.createEditor(el, { language: 'typescript', ... });
// HTML
await editor.createEditor(el, { language: 'html', ... });
// CSS
await editor.createEditor(el, { language: 'css', ... });
// And many more...Dynamic Language Switching
const editorInstance = await editor.createEditor(el, {
value: 'console.log("Hello");',
language: 'javascript',
theme: 'hybrid'
});
// Later, switch to Python
editorInstance.setValue('print("Hello")');
editorInstance.setLanguage('python');Real-Time Code Editing
The editor automatically:
- Updates syntax highlighting as you type
- Adjusts line numbers dynamically
- Maintains Caret position accurately
- Synchronizes all visual components
Configuration Options
const editorInstance = await editor.createEditor(
containerElement,
{
// Initial code content
value: 'const x = 42;',
// Programming language for syntax highlighting
// Supports: javascript, python, java, cpp, html, css, json, etc.
language: 'javascript',
// Highlight.js theme name
// Examples: 'hybrid', 'monokai', 'atom-one-dark', 'github', 'vs2015'
theme: 'hybrid'
}
);Available Themes
Caret supports all Highlight.js themes. Popular options include:
Dark Themes:
atom-one-darkmonokainight-owlnordtokyo-night-darkvs2015
Light Themes:
githubatom-one-lightstackoverflow-lightxcode
🛠️ API Reference
createEditor(container, options)
Creates a new editor instance.
Parameters:
container(HTMLElement) - The DOM element to attach the editor tooptions(Object) - Configuration optionsvalue(string) - Initial code contentlanguage(string) - Programming language for syntax highlightingtheme(string) - Highlight.js theme name
Returns: Promise
EditorInstance Methods
// Get current editor content
const code = editorInstance.getValue();
// Set editor content programmatically
editorInstance.setValue('console.log("New code");');
// Focus the editor
editorInstance.focus();
// Change the programming language
editorInstance.setLanguage('python');
// Destroy the editor instance
editorInstance.destroy();Editor Features
Automatic Line Numbering
Line numbers are automatically generated and synchronized with your code.
Smart Tab Handling
- Tab - Indent selected lines or insert 4 spaces
- Shift + Tab - Unindent selected lines
Custom Caret
The editor features a custom-rendered Caret that adapts to your theme (light/dark).
Synchronized Scrolling
All editor components (code, highlights, line numbers) scroll together smoothly.
📖 Complete Example
Here's a complete working example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Caret Demo</title>
<link rel="stylesheet" href="./node_modules/caret/index.css">
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
padding: 20px;
background: #f5f5f5;
}
#editor {
width: 900px;
height: 600px;
margin: 20px auto;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
}
.controls {
max-width: 900px;
margin: 0 auto 20px;
}
button {
padding: 8px 16px;
margin-right: 8px;
border: none;
background: #7116d8;
color: white;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #5a11ab;
}
</style>
</head>
<body>
<h1 style="text-align: center;">Caret Demo</h1>
<div class="controls">
<button onclick="changeLanguage('javascript')">JavaScript</button>
<button onclick="changeLanguage('python')">Python</button>
<button onclick="changeLanguage('html')">HTML</button>
<button onclick="changeTheme('monokai')">Monokai</button>
<button onclick="changeTheme('github')">GitHub</button>
<button onclick="getCode()">Get Code</button>
</div>
<div id="editor"></div>
<script type="module">
import editor from './node_modules/caret/esm/index.js';
// Initialize editor
const editorInstance = await editor.createEditor(
document.getElementById('editor'),
{
value: `// Welcome to Caret!
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// Calculate first 10 Fibonacci numbers
for (let i = 0; i < 10; i++) {
console.log(\`F(\${i}) = \${fibonacci(i)}\`);
}`,
language: 'javascript',
theme: 'atom-one-dark'
}
);
// Make it globally accessible for demo buttons
window.editorInstance = editorInstance;
window.changeLanguage = (lang) => {
editorInstance.setLanguage(lang);
};
window.changeTheme = (theme) => {
// Recreate editor with new theme
const currentCode = editorInstance.getValue();
editorInstance.destroy();
editor.createEditor(
document.getElementById('editor'),
{
value: currentCode,
language: 'javascript',
theme: theme
}
).then(instance => {
window.editorInstance = instance;
});
};
window.getCode = () => {
const code = editorInstance.getValue();
console.log(code);
alert('Code copied to console!');
};
</script>
</body>
</html>⚙️ Technical Details
How It Works
Caret uses a clever layering technique:
- Textarea Layer - Handles user input and cursor management
- Pre/Code Layer - Displays syntax-highlighted code (overlay)
- Custom Caret - Renders a styled Caret in the correct position
- Line Numbers - Dynamically generated and synchronized
The editor synchronizes all layers during:
- Typing (input events)
- Scrolling (scroll events)
- Navigation (click, keyup events)
Performance
- Real-time Highlighting: Uses Highlight.js for fast, accurate syntax highlighting
- Canvas Measurement: Employs HTML5 Canvas API for precise text width calculations
- Event Optimization: Efficiently updates only what's necessary on each interaction
Browser Support
- Modern browsers with ES6+ support
- Chrome, Firefox, Safari, Edge (latest versions)
- Requires JavaScript modules support
🤝 Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Clone the repository
git clone https://github.com/pfmcodes/lexius-editor.git
# Navigate to the directory
cd lexius-editor
# Install dependencies
npm install
# Run development server (if applicable)
npm run dev
# Build the project
npm run build📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Built with modern JavaScript/TypeScript
- Syntax highlighting powered by Highlight.js
- Inspired by various text editor projects in the JavaScript ecosystem
📞 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
🔗 Links
- GitHub Repository
- NPM Package (if published)
Made with ❤️ by PFMCODES
