Source for the Serenade Chrome Extension
- Download
build.zip
and unzip - In Chrome, go to chrome://extensions and enable Developer Mode
- Click "Load unpacked" and select the unzipped
build
folder
You may need to reload any tabs that were open before the extension was loaded.
Chrome extensions generally contain three types of scripts that each have access to different parts of the browser API and page content:
- Background workers/extension code have full access to the browser APIs and handles the parts of the extension that do not depend on the content of a given page.
- Content scripts have access to some of the browser APIs and access to the page DOM, but do not have access to any of the
window
properties or the page's global namespace. - Injected content scripts are embedded script tags that are added by the content script, and have full access to the page content as well as the
window
properties and the page's global namespace.
Each of these script types can communicate between each other with browser events. The source for this extension falls into these categories as follows:
- Extension code
extension.ts
: Entry-point for the extensionipc.ts
: Handles communication between the Serenade app and the Chrome extension. Also determines which command handler to send each incoming command to.extension-command-handler.ts
: Handles commands that do not need page content/require access to the browser APIs (e.g. tab management)
- Content scripts
content-script.ts
: Adds the tag containing the injected scripts and sets up communication betweenipc.ts
and the injected code
- Injected scripts
injected.ts
: Sets up injected code and handles communication between injected code and the content scriptinjected-command-handler.ts
: Handles commands that need access to the page content or objects in the page's global namespaceeditors.ts
: Defines interactions with text editors using a common API
Most of the extensions functionality is in three files: extension-command-handler.ts
, injected-command-handler.ts
, and editors.ts
.
Both command handlers contain functions named for the various command types in the Serenade Protocol. These functions take a data
object as a parameter and return a promise to the relevant response data (if any).
We currently support editing text in textarea
and input
tags, as well as a few third-party browser editors (Ace, CodeMirror, and Monaco). Each of these editor types are extensions of the Editor
class that implement these functions:
active()
: Returns whether the current active DOM element is of the object typegetEditorState()
: Returns an object containing the source, cursor offset, file name, and a boolean to indicate the source was availablesetSelection(cursor: number, cursorEnd: number)
: Sets the selection to be betweencursor
andcursorEnd
setSourceAndCursor(source: string, cursor: number)
: Sets the content of the editor tosource
and moves the cursor tocursor
undo
/redo
: Undo/redo edits
Supporting a new editor is a matter of implementing these functions.
The Editor
class also contains some helper functions to determine a suitable file name from a language name and to calculate a cursor position from the cursor row and column and vice versa. Third-party editors also have a private editor()
method to capture the Javascript object corresponding to the editor from the page's global namespace, making the third-party API available.
- Clone this repository
- Run
npm install
to get dependencies - Run
npm run build
(ornpm run watch
to automatically update while iterating)
- This creates
build/extension.js
,build/content-script.js
, andbuild/injected.js
- In Chrome, go to chrome://extensions and enable Developer Mode
- Click "Load unpacked" and select the
chrome
repository - Test the extension
- When iterating, make sure you update the extension by clicking "Update" on the Chrome Extensions page and refreshing the page you are using to test
- Running
npm run test
will serve a simple page atlocalhost:8001
with instances of the various inputs/code editors we support - The source for this test page can be found in
src/test
- Update the version number in
manifest.json
- Run
npm run dist
- Upload the new
build.zip
file to the Chrome Web Store