Problem: the hexagonal refactor churns the backend tree for nine more phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper, compose/web image) must move to its own repo first so doc/layout rewrites land once on a backend-only tree. Change: - New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/ (updateURL repointed to oikos-web releases), compose/, own CI (web + desktop jobs), own deploy script (CI-green gate, TOCTOU guard, version-tagged images, prune-to-3), own webhook receiver on :9798 + launchd unit, own compose project publishing the same 8091:80. - Cutover executed on mac-mini in order: oikos stack's web service stopped+removed, oikos-web project brought up on 8091; outer Caddy untouched (targets the published port) — serving + Authentik flow + /wails 404 quirk verified post-cutover. - Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install targets, the compose web service, oikos-web from deploy.sh's fallback prune list; wails + go-keyring dropped from go.mod, vendor synced. - README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now point at the new repo; mbse + mascot design docs carry a path note. Risk: production SPA serving depends on the new pipeline now; rollback is versioned-image re-up of the old web service from a pre-split checkout (port 8091). Desktop builds installed before the split still check dtoro/oikos releases — one manual reinstall, noted in the oikos-web release notes. Verification: go vet, make test (race), make generate-check, golangci (no new findings; baseline down 400→365); post-cutover curls — localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
5.3 KiB
NWSAPI
Fast CSS Selectors API Engine
NWSAPI is the development progress of NWMATCHER aiming at Selectors Level 4 conformance. It has been completely reworked to be easily extended and maintained. It is a right-to-left selector parser and compiler written in pure Javascript with no external dependencies. It was initially thought as a cross browser library to improve event delegation and web page scraping in various frameworks but it has become a popular replacement of the native CSS selection and matching functionality in newer browsers and headless environments.
It uses regular expressions to parse CSS selector strings and metaprogramming to transforms these selector strings into Javascript function resolvers. This process is executed only once for each selector string allowing memoization of the function resolvers and achieving unmatched performances.
Installation
To include NWSAPI in a standard web page:
<script type="text/javascript" src="nwsapi.js"></script>
To include NWSAPI in a standard web page and automatically replace the native QSA:
<script type="text/javascript" src="nwsapi.js" onload="NW.Dom.install()"></script>
To use NWSAPI with Node.js:
$ npm install nwsapi
NWSAPI currently supports browsers (as a global, NW.Dom) and headless environments (as a CommonJS module).
Supported Selectors
Here is a list of all the CSS2/CSS3/CSS4 Supported selectors.
Features and Compliance
You can read more about NWSAPI features and compliance on the wiki.
API
DOM Selection
ancestor( selector, context, callback )
Returns a reference to the nearest ancestor element matching selector, starting at context. Returns null if no element is found. If callback is provided, it is invoked for the matched element.
first( selector, context, callback )
Returns a reference to the first element matching selector, starting at context. Returns null if no element matches. If callback is provided, it is invoked for the matched element.
match( selector, element, callback )
Returns true if element matches selector, starting at context; returns false otherwise. If callback is provided, it is invoked for the matched element.
select( selector, context, callback )
Returns an array of all the elements matching selector, starting at context; returns empty Array otherwise. If callback is provided, it is invoked for each matching element.
DOM Helpers
byId( id, from )
Returns a reference to the first element with ID id, optionally filtered to descendants of the element from.
byTag( tag, from )
Returns an array of elements having the specified tag name tag, optionally filtered to descendants of the element from.
byClass( class, from )
Returns an array of elements having the specified class name class, optionally filtered to descendants of the element from.
Engine Configuration
configure( options )
The following is the list of currently available configuration options, their default values and descriptions, they are boolean flags that can be set to true or false:
IDS_DUPES: true - true to allow using multiple elements having the same id, false to disallowLIVECACHE: true - true for caching both results and resolvers, false for caching only resolversMIXEDCASE: true - true to match tag names case insensitive, false to match using case sensitiveLOGERRORS: true - true to print errors and warnings to the console, false to mute both of them
Examples on extending the basic functionalities
configure( { <configuration-flag>: [ true | false ] } )
Disable logging errors/warnings to console, disallow duplicate ids. Example:
NW.Dom.configure( { LOGERRORS: false, IDS_DUPES: false } );
NOTE: NW.Dom.configure() without parameters return the current configuration.
registerCombinator( symbol, resolver )
Registers a new symbol and its matching resolver in the combinators table. Example:
NW.Dom.registerCombinator( '^', 'e.parentElement' );
registerOperator( symbol, resolver )
Registers a new symbol and its matching resolver in the attribute operators table. Example:
NW.Dom.registerOperator( '!=', { p1: '^', p2: '$', p3: 'false' } );
registerSelector( name, rexp, func )
Registers a new selector, the matching RE and the resolver function, in the selectors table. Example:
NW.Dom.registerSelector('Controls', /^\:(control)(.*)/i,
(function(global) {
return function(match, source, mode, callback) {
var status = true;
source = 'if(/^(button|input|select|textarea)/i.test(e.nodeName)){' + source + '}';
return { 'source': source, 'status': status };
};
})(this));