💋

parslips

Template editor for Parsley templates, forked from WOOgnl

Version
v5.11.0
Updated
Oct 18

One API format: `.apiext`

v5.11.0 Oct 18 on GitHub ↗

One API format: .apiext

An element's API (its bindings, their types and directions, what's required, which combinations are allowed) now lives in one place: its .apiext. Everything else is written from that file or falls back to something older.

  • The component editor's API tab edits the .apiext. A component that doesn't have one yet gets a Generate API button, not an empty editor.
  • Generate API writes the .apiext from the component's class: a binding for every key a parent can set, with its type, and the push direction too when the component synchronizes its bindings. It works on standalone templates as well as .wo folders, reports what it did, and never touches a binding the file already has.
  • A hand-written .api carries over. A component's first .apiext starts from its .api: bindings, defaults presets, required and must-be-settable bindings, and the validation rules, as typed constraints. Of wonder-slim's 107 .api files, 106 convert completely. A rule with no .apiext form stops the conversion and is named, rather than being dropped.
  • WebObjects tools keep their .api. Saving the .apiext of a WebObjects element writes the .api beside it: bindings, presets, and validation rules for required bindings, settable ones and the constraints, with the messages the editor shows. ng elements get none, since ng-objects doesn't read .api.
  • ng's own element definitions come from ng. ng 0.1.6 ships its elements' .apiext files alongside its components, the way WebObjects keeps .api files in Resources/, and the editor reads them there. The copies the editor used to bundle are gone, so docs and bindings always match the ng version a project uses.

The old .api form editor is gone. An element with only an .api still validates and completes from it, so nothing has to be converted before it works.

A dev server that's there after every start

  • Restarting Eclipse on macOS no longer leaves the dev server dead. After a restart (File → Restart, or the restart Eclipse offers after installing updates), requests to the dev server hung for the whole session. The macOS launcher starts the new Eclipse from the old one's process, and the new one inherited a port nothing listened on. The dev server now shuts down with Eclipse.
  • A port that's still taken at startup is tried again for a minute, so an Eclipse that was quit just before doesn't leave the new one without a dev server. A server that can't start frees its port and logs why.
  • Template problems are right from the first build. While Maven was still resolving classpaths at startup, ng projects could be validated without their tag aliases, and errors like "the class for 'script' is either missing" stayed until a file changed. Templates are now re-validated when a project's classpath changes.
  • No more "Duplicate located" dialogs. Two classes with the same name in one project (legal Java, in different packages) opened an error dialog on every lookup, which also blocked agents. That now goes to the log, once, and the dev server explains the ambiguity instead of failing.

Smaller things

  • New ng-objects projects use ng 0.1.6; WebObjects projects keep wonder-slim 8.1.2.

From the changelog, October 18, 2026.

Route links, understood

v5.10.0 Oct 14 on GitHub ↗

wonder-slim 8.1.0 brings routing, and templates link to routes by name: <wo:route to="$routes.book" :book="$book">. The editor now knows these links as well as it knows any other binding.

  • Route names complete after $routes., and a misspelled one is an error with a did you mean and a quick fix. The constants a template reaches through RouteKeys.of( Routes.class ) are resolved like any other key, hop by hop, and /keypath shows them.
  • Typing : offers the route's parameters, read from your source, with no running app needed: a typed route's record components, or the {placeholders} of the pattern a plain route is mapped under, including those of the groups it's mapped in. Parameters the link already binds aren't offered again.
  • Route links validate clean. A routes() method inherited from an interface is a key like any other, :id is a route parameter rather than an attribute in an unknown namespace (the formatter keeps its colon), and binding a component to a private field no longer gets a false "can't be set" warning: values are pushed back the way key-value coding does it.

Launching without stepping on anyone

Development apps share a port, and the app on it is often one somebody else is working on: the developer, or another agent. /launch no longer stops it. Your app runs on the next free port instead, and the answer says which, listing the app that holds the dev port with how long ago it was last worked on (lastTouchedSeconds, also in /status). Taking the port is the developer's call: stopOthers=true, which stops the holder and kills it if it won't stop.

A launch also stops waiting on apps that will never come up. An app whose JVM has died is reported dead at once, even when Eclipse's debugger hasn't noticed yet. An app that neither opens its port nor prints anything for 15 seconds is reported as stalled, with the last lines it printed and its thread state, instead of being waited out.

When an app is started outside the dev server, say from Eclipse's Run button, and finds its port taken, ng-objects and wonder-slim now handle it the same way, through one shared stopper: whatever ng or WebObjects app holds the port is asked to stop, and killed if it hangs. A process that isn't an ng or WebObjects app is never touched.

Smaller things

  • /refreshProject catches a second edit to the same file within a second of the first. Eclipse saw no change and compiled nothing, while the call answered ok.
  • New WebObjects projects reference wonder-slim 8.0.17, where a component created while the app runs is found without a restart.
  • /quickfix's create action generates code that compiles, a component name that several open projects have is refused instead of resolved against the first one, and keypaths of $true, $false and $null no longer make a project-wide rename skip a template.

From the changelog, October 14, 2026.

Ask the editor, don't reconstruct

v5.9.0 Oct 2 on GitHub ↗

Ask the editor, don't reconstruct

The editor knows what a component takes, what a keypath resolves to at every hop, where a key is declared and everywhere it's used. Until now an agent rebuilt all of that from Java files and grep. The dev server now answers it directly.

  • /context loads everything about a component before an edit: its files, what it takes, its current problems, the elements its template uses (with their bindings) and who uses it.
  • /keypath resolves game.homeTeam.rating segment by segment, with types and declarations, and for a broken one the failing key and the validator's suggestions.
  • /find and /callers locate a key's declaration and every use, including a model class's key reached through template keypaths. They match by resolution, not text: $team.name counts as Team.name, and $team.captain.name doesn't.
  • /componentApi and /elementRegistry describe a project's own components and every element available to it.

Refactoring and fixes, as calls

/rename renames a component, a key (a component's, or a model class's) or a WOD element through the editor's refactorings: Java, HTML, WOD and every call site in one step, with a preview, and undoable from Eclipse's Edit menu. /quickfix applies the fixes Cmd+1 offers on a template problem: replace a misspelled key, or create the missing key or action.

No more silent hangs

Apps run under Eclipse's debugger, and by default it stops a thread that reaches code that didn't compile, or an uncaught exception, without a word. To an agent that's a request that never answers. Apps launched through the dev server now fail fast instead, and /threads shows anything that is stopped, where and why. /restart builds before it stops anything, so a broken build leaves the running app up rather than taking it down. A launch is only reported ready once the app has survived its startup: an app that fails in its constructor used to look ready for a moment.

Validation that catches what used to fail at render

  • Binding a component that synchronizes its bindings to a keypath with no setter is flagged. The value gets pushed back after rendering, and that fails.
  • KVC operators such as @count on a java.util collection are an error: in WebObjects they only work on an NSArray.
  • Components that read their bindings with valueForBinding("…") have those bindings offered in completion, and renamed along with the key.
  • An element's documentation comes from the element that actually runs. For example, <wo:str> is described by wonder-slim's ERXWOString, which formats java.time values.
  • A component class that moved to another package is no longer reported missing.
  • The definitions of WebObjects' own elements were checked against WebObjects 5.4.3 itself.

Smaller things

  • Every dev-server endpoint says no the same way: error when the call is wrong, reason (often with a hint, the call that fixes it) when it was fine but nothing happened. No more ok for requests nothing was done for.
  • /where tells an agent whether its directory is one Eclipse sees. Edits in a git worktree are invisible to Eclipse, and the developer can't follow them.
  • New WebObjects projects start with Main extending ERXComponent, and the templates reference wonder-slim 8.0.16 and vermilingua 1.1.11.

From the changelog, October 2, 2026.

Hybrid projects: every template knows its runtime

v5.8.0 Sep 25 on GitHub ↗

Hybrid projects: every template knows its runtime

A WebObjects application can serve ng-objects components alongside its own — a hybrid project, with WebObjects templates and ng templates side by side. The editor used to judge every template by the project's type, so in a WebObjects project an ng component's template was checked as WebObjects: ng-only tags like `` were unknown, and ng elements such as AjaxUpdateLink were reported missing.

Now each template has its own runtime, decided the way ng-objects finds its components: a template under ng//components/ (or anywhere in an ng project) is an ng template, everything else is WebObjects. Validation, completion, hover and the Element Reference follow it — `` is NGString in the ng page and WOString in the WebObjects page next to it, each checked against the element it really is.

Smaller things

  • ng projects read their tag names from ng-tag-aliases.properties, ng-objects' renamed registry — the rename keeps a classpath with both frameworks from mixing the two vocabularies.
  • The dev server's /elementApi takes runtime=ng|wo for hybrid projects, and debug=true shows exactly how an element's class was looked up; /validate finds components of either runtime.
  • The new-project templates reference vermilingua 1.1.10.

From the changelog, September 25, 2026.

From nothing to a running app

v5.7.0 Sep 19 on GitHub ↗

From nothing to a running app

An agent could already edit, build, launch and observe a project through the dev server — but it couldn't begin one. New projects were written to disk and then imported into Eclipse by hand. That last manual step is gone: /createProject generates a project from the bundled templates (ng-objects-app, wonder-slim-app, or a new plain maven library for supporting logic), imports it through m2e, waits for the workspace to settle, reports compile errors, gives an application a launch configuration — and with launch=true starts it. One call, a few seconds, and there is a running app in Eclipse ready for the edit loop, hot code replacement included. /importProject does the same for a project that already exists on disk. Both refuse rather than overwrite anything.

One dev port, decided out loud

Development apps share a port by convention, so starting one while another runs used to end with the frameworks quietly stopping the earlier app — which an agent only ever saw as an app mysteriously dying. /launch now decides it explicitly: a held port is a refusal that names the holder, stopOthers=true takes the port, and port=1201 runs alongside instead — the argument is injected into an unsaved copy of the launch configuration, so yours is never edited. When an app does get stopped by a second instance, /console now says so instead of showing a clean log and an unexplained exit code.

ng-objects elements, described by ng-objects

In ng-objects projects the editor used to borrow its knowledge of each element from the WebObjects element of the same name — right often enough to be convincing, wrong wherever the two differ. ng-objects now declares its own tag names and ships its own element definitions, and the editor reads those: completion offers ng's tags and nothing from the WebObjects world, bindings validate against the real contract (`` has checked, not WebObjects' value/selection pair), and binding completion and validation finally agree with each other. Projects on an ng-objects release that predates these files get the same definitions from a copy bundled with the editor.

Smaller things

  • /validate says why a component wasn't found — closed project, unknown project, or no such component — and /problems says why a project's list is empty.
  • A launch is no longer refused for compile errors that vanish a moment later: the preflight waits for Maven's classpath work after a project is opened.
  • Apps launched through the dev server get their console in Eclipse even in a freshly started session.
  • /openProject?project=all is gone; opening a project brings its workspace dependencies along, which is the useful thing.
  • The new-project templates reference wonder-slim 8.0.4 and vermilingua 1.1.7.

From the changelog, September 19, 2026.

The dev server grows up

v5.6.0 Sep 2 on GitHub ↗

The dev server grows up

A summer of work on the built-in dev server (localhost:9485) — the HTTP surface that lets external tools and AI agents drive Eclipse. It now reports what actually happened, not just that a command was relayed: /status (what's running, per launch config), /console (a launch's output, kept after the process dies), /launch with preflight refusals and waitForPort, /restart, /openProject (a project plus its workspace dependencies), /problems, /breakpoints, and a self-describing index at /. /refreshProject returns a build report instead of ok when the build produced errors.

Ask the editor what a tag can do

/elementApi returns any element's resolved binding API as JSON — types, direction, required, defaults, cross-binding rules with their plain-English messages — the editor's hover, as data. Validation also gained a check for the $-on-a-plain-tag trap. Paired with runtime-side eval and problems endpoints in ng-objects and wonder-slim.

Trustworthy markers

Revalidate All Templates (a preference-page button and /revalidate) re-runs template validation over a project or the whole workspace, and Purge Stale Markers (/purgeMarkers) deletes orphaned markers left by validators that no longer exist. /problems labels every marker with its source. Along the way: the standalone JS/CSS editors and their ancient validation engines are gone (Eclipse owns those files; inline blocks in templates keep highlighting and completion), and the plugin's embedded libraries were brought current.

Watch your agent work, live

The dev server records every request it handles, and /watch turns that into a live, narrated feed (“Validated Main — clean”, “Launched MyApp — ready in 4.2s”) with a running tally. /activity serves the same record as JSON — an audit trail of what an agent actually did to your workspace.

Launches that can't stop the world

Eclipse's “Errors exist in required project(s). Proceed?” dialog can no longer strand an agent: /launch checks the app and every project it depends on, refuses with the broken projects and the fix, and launches with Eclipse's prompting switched off. For every other modal, /dialogs lists them and can press a button — and a launch that's waiting for the app returns at once if one appears.

From the changelog, August 29, 2026.

Every standard WebObjects element, richly described

v5.5.1 Jul 4 on GitHub ↗

Every standard WebObjects element, richly described

The template editor now ships a full .apiext description for every one of the standard WebObjects dynamic elements — all 39 of them, from WOString and WORepetition to WOForm, WOPopUpButton and the rest. Until now these built-in elements were described by the old, thin .api files, which knew a binding’s name but little else. The new descriptions are far richer, and they light up everywhere the editor already helps you.

For each element and each of its bindings you now get:

  • Real documentation — a written description of what the element does and what every binding is for, shown in the hover and the Element Reference.
  • Typed bindings with direction — each binding declares the Java type it accepts, and whether the element reads it (pull ↓), writes it back (push ↑), or both. So you can see at a glance that a checkbox’s checked reads any value by truthiness but pushes back a real Boolean.
  • Cross-binding rules — the “exactly one of these” and “if you bind this, you must bind that” constraints are now typed and checked, so the editor flags a mis-bound element as you write it.
  • Sensible defaults and deprecations — default values are shown where they exist, and genuinely obsolete elements (WOApplet, WOVBScript, WOQuickTime…) are marked deprecated and struck through in the Element Reference, so it’s obvious what not to reach for.

The descriptions are grounded in the published WebObjects element reference and the elements’ documented binding behavior, so what the editor tells you matches what the framework actually does. This is also the largest body of real .apiext yet — a solid, practical proving ground for the format as it grows toward a full tag library.

From the changelog, July 4, 2026.

Jump to any part of a keypath

v5.5.0 Jul 1 on GitHub ↗

Jump to any part of a keypath

Editing a template and want to jump to the Java behind a binding? Put your cursor in a keypath and hit F3 — the same “Open Declaration” shortcut you already use in Java code. It now works in the template editor too, on element tags, binding names, and binding values, so you can navigate without reaching for the mouse.

The nice part is how it treats a keypath. Eclipse normally sees $activeUser.address.city as one thing and, on Cmd+click, jumps to the very end — the city method. But often you want a segment in the middle. Now both F3 and Cmd+click open the segment your cursor is actually on:

  • On activeUser → opens activeUser
  • On address → opens address
  • On city → opens city

And when you hold Cmd and hover, the underline now highlights just the segment you’re pointing at — so what lights up is exactly what a click will open.

From the changelog, July 1, 2026.

One source of truth for what a tag means

v5.4.4 Jun 26 on GitHub ↗

One source of truth for what a tag means

Phew. I've wanted this for so long: Eclipse/the template editor and the WO runtime now share a single, declarative tag registry — so the editor and the application will interpret tags through a single mechanism.

Until now, the template editor carried its own built-in "tag shortcut" registry for tags like and really had no idea whether it matched what WO would actually render at runtime. It usually did — but “usually” is where subtle, maddening mismatches live. The classic example: WebObjects frameworks *substitute* elements at runtime. Bind a and ERExtensions quietly swaps in its own ERXWOString when the page renders. That substitution lived only in framework code that ran at startup — completely invisible to the editor.

Now element tags are declared by frameworks and applications. A framework or application drops a simple parsley-tag-aliases.properties file on its classpath:

A tag shortcut and an element replacement are pretty much the same thing — an alias from one name to another — so they share one mechanism. Resolution is recursive: str → WOString → ERXWOString, following the chain to whatever your app really renders. The Parsley runtime reads this file to build pages; the editor reads the very same files from your project’s classpath.

What you get, across the whole editor:

  • Autocomplete offers the tags your project actually defines.

  • Hover and binding completion resolve the full chain. Hovering `` shows str → WOString → ERXWOString — the truth of what renders.

  • The Element Reference marks overridden elements in orange and a dedicated “Overridden by” column, so you can see at a glance which built-in elements are replaced in your project, and with what.

It is opt-in and per-project: a project that contains no alias files behaves exactly as before. And it’s the first step and foundation for something larger — a proper tag library, where a framework fully describes its own tags to the tooling.

From the changelog, June 26, 2026.

Added element reference view

v5.4.3 Jun 24 on GitHub ↗

Added element reference view

A new Element Reference view (Window → Show View → Parsley) lists every element available to your project — searchable, sortable, with each one’s full API documentation a click away. The Origin column shows which framework an element comes from, and a double-click opens it.

From the template editor, Cmd+Opt+9 reveals the element under your cursor in the view — without moving focus, so your editing flow isn’t interrupted.

Hide wod editor if wod is empty

When a component’s .wod file is empty — as it always is for inline-binding templates — the WOD editor no longer takes up half the editor. It collapses to a thin bar, giving the template the full height; click the bar any time you want the WOD editor back.

From the changelog, June 24, 2026.

Detailed element documentation on hover

v5.4.2 Jun 23 on GitHub ↗

Detailed element documentation on hover

Hovering a `` tag now shows detailed information about an element’s API — some documentation, its bindings, which bindings are required, and so on.

  • A real description. Elements and individual bindings can carry Markdown documentation (a role summary up top, a note per binding), rendered inline — so the hover explains what a binding is for, not just its name.
  • Binding direction and type. Each binding shows whether the element reads it (a grey ↓ “pull”), writes it back (an orange ↑ “push”), or both (a red ↔ two-way), along with the accepted Java type. When a binding reads one type and writes another — like a checkbox that reads any value by truthiness but writes back a Boolean — the two are shown separately.
  • Status badges. Container elements and binding-passthrough elements are flagged with a badge in the header, and a small marker shows whether the documentation came from a project’s own definition or a richer bundled one.
  • Read it comfortably. The popup opens at a generous size, scrolls when an element has a lot of bindings, and stays open when you move into it so you can select and copy text.

This richer documentation is driven by an experimental .apiext format. The editor uses it when a parsable definition is available (today for a small set of built-in elements and for AjaxSlim’s components) and falls back to the classic definition otherwise — so existing projects keep working unchanged while the format settles.

From the changelog, June 23, 2026.

A full dev loop for AI-assisted work on a running app

v5.4.1 Jun 8 on GitHub ↗

A full dev loop for AI-assisted work on a running app

Building on /refreshProject, the dev server gained a handful of endpoints that together let an external tool — most usefully an AI coding assistant working in your repo — drive the whole edit→build→run loop on a live WebObjects/Parsley application, without you relaying anything by hand. Everything is localhost-only, with no setup.

  • Validate a template without rendering it — /validate?component=NAME runs Parsley’s template validator on a component and returns the problems (line, position, message) as JSON. Templates are long, error-prone strings whose mistakes usually don’t surface until the page renders; now they can be caught up front. (Eclipse’s own validation is editor-driven, so a plain refresh never checked templates — this fills that gap.)
  • Read the running app’s console over HTTP — the app (via wonder-slim’s ERExtensions, in development) serves its recent log at …/App.woa/log, with contains= and tail= filters. No more copy-pasting the Eclipse console to share what the app printed.
  • Discover what’s running — apps announce themselves at startup, so /apps lists each running app, its port, and which of its dependencies have source open in your workspace (with paths). A tool can find an app by name — no guessing ports — and knows which libraries it can actually read and edit versus jar-only ones.
  • Start and stop apps — /launch starts a launch configuration (listing them, and deliberately preferring a local/dev config so it never accidentally fires Production), and /stop shuts one down (cleanly, or with force=true for a JVM that a big hot-reload has wedged).

Why this matters. Each piece removes a manual hand-off. The result is that an assistant can launch your app, edit source and templates, validate them, refresh the running instance, read back the console to confirm, and restart when a change needs it — closing the loop end to end. There’s a short guide for setting this up with an agent in the repo’s AGENTS.md.

From the changelog, June 5, 2026.

Dev server can now refresh & rebuild a whole project on demand

v5.4.0 Jun 1 on GitHub ↗

Dev server can now refresh & rebuild a whole project on demand

The dev server has a new endpoint — /refreshProject?project=NAME — that refreshes a project from disk and rebuilds it, all in one call. It’s the programmatic equivalent of closing and reopening the project in Eclipse: it picks up file changes made outside the Eclipse editor and recompiles them. Add &build=false to refresh without building, or omit project to refresh every open project.

Why this matters: Eclipse only notices edits it made itself. When something else changes your source on disk — a code generator, a script, or an AI coding assistant working in the repo — Eclipse doesn’t know, so your running app keeps using the old compiled classes and the change seems to do nothing. You’d normally fix that by manually closing and reopening the project. Now a single HTTP call does it.

Why this is useful. It turns out to be the missing piece for working with an AI assistant on a live WebObjects/Parsley app. The assistant edits your source, calls /refreshProject, and the running app hot-swaps the change in immediately — so it can load a page and actually see the result of what it just wrote. No build/redeploy/restart cycle in between. The loop goes from “edit, then a human babysits a rebuild” to “edit, refresh, observe” — in seconds. The same applies to any external tool that edits your project and wants the running app to reflect it.

From the changelog, June 1, 2026.

Components now open to the HTML template by default

v5.3.3 May 29 on GitHub ↗

Components now open to the HTML template by default

When you open a component, the editor now lands on the HTML template instead of the WOD editor. Opening a component is almost always about working on the template — and for inline-syntax components the WOD sidecar is usually empty — so HTML-first is the sensible default.

If you specifically open a .wod file (or .woo / .api), the editor still reveals that part — only the “no specific request” case (opening the component itself, via Open Component, double-clicking the .wo folder, or jumping in from an exception page) defaults to HTML.

Dev server now enabled by default

The dev server — which lets your running application drive Eclipse, most usefully so that clicking a stack-trace line on an exception page in the browser opens that source line in Eclipse — is now on by default and needs no setup. The feature has always existed (it came over from WOLips); it’s just far more accessible now.

What changed:

  • No password. The server listens only on localhost, which is its security boundary — anything that could reach it is already running on your machine. It previously required a shared password between the IDE and the app; that friction is gone, on both sides.
  • On by default. Nothing to enable. Wonder’s ERXExceptionPage (and ng-objects’ equivalent) already generate the links, so for most projects this simply starts working.
  • Fails quietly on a port conflict. If port 9485 is already taken — most commonly because a second Eclipse window already owns it — the server just doesn’t start in that instance and notes it calmly in the log. The first window owns the port, which is the one your app talks to anyway.
  • Configurable. Enable/disable and port live under Preferences → Parsley → Dev Server; changes apply immediately without restarting Eclipse.

From the changelog, May 29, 2026.

Fix: `$application` and `$session` keypaths now resolve against user subclasses in NG projects

v5.3.2 May 14 on GitHub ↗

Fix: $application and $session keypaths now resolve against user subclasses in NG projects

In ng-objects projects, keypaths like $application.formatters or $session.currentUser were producing false “There is no key” validation errors, even though the runtime resolves them correctly. The validator was checking the bare NGApplication / NGSession class instead of walking down to the user’s Application / Session subclass where the actual keys live.

The mechanism for “when this is the declared type, look at subclasses in the current project instead” has been in place for years for the classic WebObjects equivalents (WOApplication, WOSession, WODirectAction) — the ng-objects classes were just missing from the list. Now added: NGApplication, NGSession, NGDirectAction.

Detection is purely name-based and works regardless of which framework the project targets — the validator picks up whichever class appears in the supertype chain.

From the changelog, May 14, 2026.

Fix: problem markers now appear on pulled-up source folders

v5.3.1 May 6 on GitHub ↗

Fix: problem markers now appear on pulled-up source folders

Files with errors inside src/main/components, src/main/woresources, or any pulled-up ng-style resource folder were propagating their error markers up to the project, but the pulled-up folders themselves at the project root showed no marker — even though the error was clearly inside them. So you’d see the red error decorator on the project, then nothing on any of its visible children, with no easy way to drill down to where the error actually was.

The cause was an icon-overlay slot collision: the small “wo”/“ng” badge that marks pulled-up source folders was using the same image overlay slot as Eclipse’s standard problem-marker decorator. The badge was applied first, blocking the marker. The badge has been moved to the top-right corner of the folder icon, leaving the bottom-left slot free for the problem marker.

Fix: false validation errors on methods whose names start with an uppercase letter

Action methods and other unprefixed methods whose names start with an uppercase letter — for example HttpServerUpdateClicked() or HTTPServerUpdateClicked() — were producing false “There is no key ‘X’” errors when bound from a template, even though valueForKey("HttpServerUpdateClicked") finds the method correctly at runtime.

The editor was lowercasing the first character of every method name to derive the binding key, which produced names like hTTPServerUpdateClicked or httpServerUpdateClicked. The runtime never finds methods by those keys (literal-method lookup is case-sensitive), so the editor's “Did you mean...?” suggestion was actually pointing at a key that wouldn't have worked.

The fix follows the standard Cocoa / WebObjects KVC convention:

  • For methods without a get/set/is prefix, the binding key is the method name preserved exactly. HttpServerUpdateClicked() → key HttpServerUpdateClicked; title() → key title.
  • For methods with a bean-style prefix, the prefix is stripped and the first letter is lowercased — unless the first two characters are both uppercase, which preserves acronyms. getURL() → URL; getTitle() → title; getHttpServer() → httpServer.

The same fix applies to the rename refactoring — renaming HttpServerUpdateClicked() on a Java class now correctly updates HttpServerUpdateClicked in bound templates.

From the changelog, May 6, 2026.

Dark mode readability and new color preference pages

v5.3.0 May 4 on GitHub ↗

Dark mode readability and new color preference pages

Two improvements aimed at users running Eclipse in a dark theme:

Plain text now follows Eclipse’s editor theme. The HTML, embedded JavaScript, and embedded CSS scanners used to set the default text color to a hardcoded value (pure black by default), which made plain content — HTML body text, CSS selectors and braces, JavaScript identifiers — render black on a dark background and effectively disappear. These scanners now defer to Eclipse’s standard editor foreground color, which is theme-aware. In dark mode the same text shows up in light gray; in light mode it stays dark, exactly as before.

As part of this change, the “Foreground Color” field in Preferences → Parsley has been removed — it was the setting that previously hardcoded the black default and is no longer needed. To customize the editor’s default text color, use the standard Eclipse setting at Preferences → General → Editors → Text Editors → Colors and Fonts.

New “Embedded CSS” and “Embedded JavaScript” preference pages under Preferences → Parsley, exposing color settings that previously had no UI:

  • Embedded CSS: Comment, Property, Value
  • Embedded JavaScript: Comment, String, Keyword

If you’ve been irritated by the dark-blue CSS property color on a dark editor background, this is where to fix it.

This is a first readability pass. The remaining tag/attribute/binding colors and the `` background tint are still tuned for light themes — theme-aware defaults for those are next.

From the changelog, May 4, 2026.

Updated project template versions

v5.2.2 May 1 on GitHub ↗

Updated project template versions

The New Project wizard now generates projects using the latest released dependency versions:

  • wonder-slim: 8.0.0 (released, replacing the previous 8.0.0.slim-SNAPSHOT; the group id is now is.rebbi.slim)
  • ng-objects: 0.1.1 (was 0.1.0)
  • vermilingua-maven-plugin: 1.1.4 (was 1.0.5)

Existing projects are unaffected — this only impacts new projects created via the wizard.

From the changelog, April 30, 2026.

Validate duplicate attributes

v5.2.1 Apr 12 on GitHub ↗

Validate duplicate attributes

Tags with duplicate attributes — e.g. `` — now produce a validation error. The first occurrence wins (per the HTML spec) and the duplicate is highlighted in the editor and Problems view. Detection is case-insensitive, so class and Class are correctly flagged as duplicates.

From the changelog, April 12, 2026.

Fix: extraneous close tags are now reported

v5.2.0 Apr 10 on GitHub ↗

Fix: extraneous close tags are now reported

Templates with stray close tags — e.g. `` with more closes than opens — now correctly report each dangling close tag as a validation error (“

start tag is not found.”) in the Problems view and inline in the editor.

This was a long-standing bug inherited from the original WOLips parser: the FuzzyXML close-tag handler had a defensive early return whenever the open-tag stack was empty, which silently swallowed the exact case the validation was meant to catch. An empty stack on a close tag is precisely an extraneous close tag.

Fix: close-tag completion after self-closing tag with parentheses in attribute

Fixed a bug where close-tag completion (Ctrl+Space) would suggest the wrong tag after a self-closing tag whose attribute value started with a delimiter character — typically a parenthesis, like ``. The scanner’s quoted-value tracking lost state when the first character inside the quote was a delimiter, which in turn broke the self-closing pop and left the tag sitting on the unclosed-tag stack. Subsequent close-tag completions would incorrectly suggest closing the stale tag.

Also affects values starting with other delimiter characters (;, +, etc.), not just (.

From the changelog, April 10, 2026.