Primrose
A syntax-highlighting text editors that renders to an HTML5 Canvas
Install / Use
/learn @capnmidnight/PrimroseREADME
PRIMROSE TEXT EDITOR
Primrose is a syntax highlighting text editor that renders into an HTML5 Canvas element. This is particularly useful for texturing 3D objects in WebGL apps.
Features
- International keyboard support (left-to-right rendering only)
- Wide Unicode character-aware
- Line numbering
- Color theming
- Syntax highlighting for:
- JavaScript,
- HTML, and
- BASIC
Liscense
Primrose is free, open source software (MIT) and may readily be used with other FOSS projects.
<hr>Contributing
Conduct
First, please read the Conduct Policy.
Contributions
If you think you can be a polite person in accordance with the Conduct Policy, I'd be more than happy to add anyone who asks as a contributor. Just email me your profile info and a brief description of what you'd like to work on.
<hr>Getting started with Primrose
In a 2D page
Here is a basic example that creates an editor in a 2D web page.
index.html
<html>
<body>
<primrose style="width:50em;height:25em"></primrose>
</body>
<script type="module" src="node_modules/primrose/src/primrose.js"></script>
</html>
In a 3D WebGL app
Here is a basic example that creates an editor in a 3D WebGL app, using Three.js.
<em>NOTE: While Primrose can manage most input events on its own, in WebGL contexts, it's not able to figure out what the user's pointer is pointing at. Mouse or VR motion controller support requires implementing Raycast-based picking on your own. However, Primrose does offer a simple interface for implementing pointer operations.</em>
<hr>API
The documentation here represents the public API. Any properties, methods, functions, or classes not listed here are considered either internal state or deprecated features and may change or be removed at any time.
<hr>Primrose
The Primrose class extends the EventTarget class. It is a text editor control that renders to an HTML5 Canvas, using the CanvasRenderingContext2D API.
Importing
To get the Primrose class, import it from the package bundle:
import { Primrose } from "./node_modules/primrose/primrose.js";
There is also a minified version:
import { Primrose } from "./node_modules/primrose/primrose.min.js";
You can also import without package bundling, which is probably preferred if you intend to build your own bundle:
import { Primrose } from "./node_modules/primrose/src/primrose.js";
<hr>
Constructor
You create a Primrose control in one of two ways. In creating the control, there are a set of options that you can specify. The two ways are:
In HTML
Create a <primrose> tag in your document before the page has loaded.
Specify the options as a comma seperated list of key-value pairs, each separated by an equals sign (=), on an attribute on the tag named data-options.
Example
<primrose data-options="lineNumbers=false;wordWrap=false"></primrose>
In JavaScript
Create a new instance of the Primrose class, passing the options as a JavaScript object
Example
new Primrose({ lineNumbers: false, wordWrap: false });
Options
The options object has the following fields:
- element:(HTMLElement|HTMLCanvasElement|OffscreenCanvas) - Default:
null- a document element or a canvas that represents thePrimrosecontrol. This can either be:- a
<primrose>tag (which is a generic HTML tag in DOM), in which case the editor Canvas will be inserted into the<primrose>tag, or - an
HTMLCanvasElementelement orOffscreeCanvasobject, in which case the editor will take control of the canvas. null, which instructs Primrose to construct its own Canvas element. IfOffscreenCanvasis available, that will be used instead ofHTMLCanvasElement.
- a
- width:Number - Default:
undefined- the scale-independent width of the canvas used whenelementis null - height:Number - Default:
undefined- the scale-independent height of the canvas used whenelementis null - padding:Number - Default:
0- the scale-independent amount of inset for rendering the contents from the edge of the canvas. This is useful for texturing objects where the texture edge cannot be precisely controlled. - fontSize:Number - Default:
16- the scale-independent height to draw characters. - scaleFactor:Number - *Default:
window.devicePixelRatio- A multiplicative factor for how large to scale thewidth,height,fontSize, andpaddingof the canvas, to improve rendering sharpness on high-resolution displays. With THREE.js, it's best to set this value to 1 and change the width, height, and fontSize manually. - readOnly:Boolean - Default:
false- indicates whether or not the text editor should allow changes to its value. - multiLine:Boolean - Default:
true- indicates whether or not the text editor should break long lines onto new lines. - scrollBars:Boolean - Default:
true- indicates whether or not scroll bars should be rendered at the right and bottom in the control. If wordWrap is enabled, the bottom, horizontal scrollbar will not be rendered. - lineNumbers:Boolean - Default:
true- indicates whether or not line numbers should be rendered on the left side of the control. - language:String - Default:
"JavaScript"- A name for the type of syntax highlighting to perform. This value is not case-sensitive. Valid values are:"basic"for Basic,"bas"for Basic,"html"for HTML,"javascript"for JavaScript,"js"for JavaScript,"plaintext"for PlainText,"txt"for PlainText- and any case-variation thereof.
Events
The events in Primrose are all of type Event, having no other properties set on them. The only way to register the events is to call addEventListener, i.e. there are no on### properties on the object for the event handlers.
- change:Event - Fires when the text in the control has changed.
- blur:Event - Fires when the control first loses focus. Calls to
blur()while the control is not focused will not fire theblurevent. - focus:Event - Fires when the control first gains focus. Calls to
focus()while the control is focused will not fire thefocusevent. - over:Event - Fires when the control is first hovered over by a pointer.
- out:Event - Fires the first time the controller is no longer hovered over by a pointer.
- update:Event - Fires when the Primrose control finishes rendering.
Public Methods
<hr>addEventListener(type:String, handler:Function(evt:Event))
Add a listener for one of the event types listed above.
Example
const editor = new Primrose({
element: document.querySelector("canvas")
});
function onChange(){
console.log("changed!");
}
editor.addEventListener("change", onChange);
editor.value = "Something"; // 'changed!' printed out to console.
Parameters
- name:String - The name of the event to register, one of the event names listed in the Events section above.
- handler:Function(evt:Event) - A callback function to receive the event. This function will be provided an argument of type Event
