The code editor
Where a real editor replaces a text area, what it knows about ServiceNow, the widget toolbar, and the four traps that cost a day each.
The extension carries a full editor and uses it in several places. It is the same editor the platform itself uses, but this copy is ours: it is in the package, it loads from disk, and nothing is fetched to make it work.
Where it appears
On the extension's own pages: the body and the front-end half of a script you are composing, and the free CSS field of a theme.
On the instance: the field editor you get by double-clicking a technical-name pill, which edits the form and never saves the record, and the HTML template and CSS fields of a Service Portal widget, which can be turned off in settings.
On the background script page the platform builds its own editor, and the panel attaches to that one rather than replacing it.
What it knows about ServiceNow
In the panel's script editor, completion knows gs., current., g_form., GlideRecord,
GlideAggregate, GlideQuery and their neighbours, with signatures and a line on each. Type a table
in the Table field of a triggered script and that table's fields, parents included, join the list:
they are read from the instance's dictionary, the way the platform's own editor does it.
ShiftAltF formats the document.
On a Service Portal widget
On the classic sp_widget form, Server Script and Client Controller already have the platform's
editor, and the HTML template and CSS were bare text areas. The extension mounts an editor over
those two, with HTML completion that knows AngularJS directives, and CSS with SCSS syntax.
They carry the Script field's own toolbar, copied from the same form, so the platform's stylesheet draws it and the chords are the ones you already know:
| Chord | Does |
|---|---|
| CtrlAlt/ | Comment |
| CtrlAltL | Format |
| CtrlAltK or CtrlAltR | Replace |
| CtrlG, CtrlShiftG | Find next, find previous |
| CtrlAltEnter | Full screen |
| CtrlH | The platform's editor key map |
Save goes through the platform's own submit, the syntax button switches to the plain field and back, and Check Syntax turns CSS validation on and off. Script Debugger is left out, because it is for server script. The editors line up with the Server Script editor instead of filling the whole row.
The right-click menu
ServiceNow builds its script editors with the editor's own context menu turned off, so a right-click there gets the browser's menu. Editor right-click menu, on by default, turns the editor's menu back on wherever the instance turned it off: business rules, script includes, widgets. Switch it off and the editors it touched go back, without a reload. It is in the widget settings, and follows the profile.
The property tooltip
Point anywhere on a line that calls gs.getProperty, not only at the word, and a note answers for
the call under the pointer or the nearest one: the property, its type, its value (hidden for a
password), its description, and an Open record link. A property that does not exist names the
default the call falls back to. It works in the extension's editor and in the platform's.
The text area stays the value
Where a text area is upgraded, the text area is still what the form reads. It keeps its id and its value. If the editor never arrives, what you have is the working text area you started with, rather than a page with a hole in it.
Everything is local
An extension page runs under a policy that refuses any script it did not ship, so a CDN is not an option even if we wanted one. The editor, its workers, its font, the formatter and the ServiceNow type definitions are downloaded when the package is built, and loaded from inside it. At runtime the only requests are to the extension's own files.
It is about three and a half megabytes, so it loads the first time you open something that needs it rather than on every page.
Four traps, each paid for once
These are written down because each one costs an afternoon to rediscover.
The stylesheet loader must be stubbed before the editor's main file runs, or each of its per-module style dependencies 404s.
The icon font is named by a relative path inside the editor's own stylesheet. Loaded from anywhere else, every icon in the editor becomes an empty box.
There is no TypeScript worker. The editor's main bundle ships the TypeScript language service, which is worker-driven, but not the syntax grammars. Given only its own editor worker it logs could not create web worker and freezes the interface the first time something asks for one. So the language service is put to sleep and the grammars are vendored: two private languages registered under private ids, precisely so they do not drag the worker-backed providers back in.
Colours come from the page. The editor reads the host page's own CSS variables and resolves whatever colour syntax it finds through a canvas, so it matches both the settings page and the widget without being told where it is.
