{"ref":"artifact:abap2ui5-linter","page":"/artifacts/abap2ui5-linter","json":"/artifacts/abap2ui5-linter.json","generated":"2026-10-26","drafted_with_ai":true,"entity":{"id":"abap2ui5-linter","name":"@abap2ui5/linter","artifact_type":"cli","ecosystem":"abap","domain":"developer-experience","secondary_domains":["ui-and-frontend-bridge"],"origin_ring":"community-org","use_as":"dependency","source_available":true,"description":{"one_line":"A command line that checks an [abap2UI5](artifact:abap2ui5-abap2ui5) app class together with the UI5 view its builder chain produces, with no SAP system and no UI5 project.","short":"Command-line checker for abap2UI5 app classes and their views","what_it_solves":"The view an [abap2UI5](artifact:abap2ui5-abap2ui5) app shows does not exist until the app runs: it is built by a chain of `z2ui5_cl_ui5_view_builder` calls, so the ABAP compiler never sees a control name and no UI5 tooling ever sees the class. `npx @abap2ui5/linter src` reconstructs that view from the chain and judges the two together. A property gate resolves every control, property, aggregation, enum value and icon against a UI5 metadata snapshot held to the release `--ui5` names, and more than a hundred rules read class and view at once: a binding path the derived model has no field for, a PROTECTED attribute bound, an ABAP boolean written straight into the view. A render gate loads the view with a real `XMLView.create` in headless Chromium, which needs a UI5 runtime and is therefore a second install, `@abap2ui5/linter-render`, while `--screenshot` keeps that view standing and photographs it. The CLI, the library and the GitHub Action `abap2UI5/linter@v0` read one `abap2ui5lint.jsonc`, and `--update-baseline` freezes the findings of a codebase that already exists so that new ones fail on their own.","when_not_to_use":"Event roundtrips and visual fidelity stay with a live run: the documentation leaves those to the project's MCP server and to [abap2UI5 for VS Code](artifact:abap2ui5-vscode-extension). A class that builds view parts in helper methods without the handle idiom cannot be statically reconstructed, and the render gate is then skipped with a notice while the property gate runs on what was reconstructed. A screenshot is not a preview of the app: nothing round-trips, no event reaches ABAP, and a table filled by a SELECT photographs empty unless a mock JSON file sits beside the source.","to_build_on_it":"The checkout runs over its own fixtures with `node cli.mjs test/fixtures --no-render`, and `npm test` gates four generated artefacts, among them the UI5 metadata snapshot, the config schema and `data/compat.json`, which records which abap2UI5 releases a linter line understands. Two further generators need network, so a scheduled workflow refreshes each one and opens a pull request with the diff. `data/portable-v1.json` is copied by hand from the abap2UI5 protocol repository, and the test suite pins its hash."},"links":{"repo":"https://github.com/abap2UI5/linter","npm":"https://www.npmjs.com/package/@abap2ui5/linter","docs":"https://abap2ui5.github.io/docs/advanced/linter.html","homepage":"https://abap2ui5.github.io/linter/"},"maintainers":["actor:abap2ui5","actor:oblomov-dev"],"compat":{"runtimes":["node"]},"type_properties":{"distribution":{"value":["npm"],"sources":[{"url":"https://github.com/abap2UI5/linter","title":"@abap2ui5/linter — README","checked":"2026-10-18","quote":"npx @abap2ui5/linter src"}]}},"provides":[{"capability":"capability:abap-static-analysis","what_it_does":"Judges an abap2UI5 app class and the view it builds in one run, without a system: the property gate resolves everything the view writes against a UI5 metadata snapshot held to a named UI5 release and distribution, the render gate loads the view with `XMLView.create` in headless Chromium to catch one that fails to load at all, and more than a hundred rules cover the defects that sit between the ABAP class and the view and stay silent at runtime. Each finding carries a severity and a rule id, `--fail-on` decides which severities break the build, waivers work at line, repository and member scope, and `--update-baseline` freezes the debt of an existing codebase.","sources":[{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter","checked":"2026-10-17","quote":"It reconstructs the view from the builder chain and judges the class and the view together"},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, The property gate","checked":"2026-10-17","quote":"Everything the view writes is resolved against a UI5 metadata snapshot — every control OpenUI5 ships, with its full member list and types, and every enum, generated from the OpenUI5 sources."},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, The render gate","checked":"2026-10-17","quote":"The view is then loaded with a real XMLView.create in headless Chromium against a local OpenUI5 runtime, with UI5 future mode active."},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, The abap2UI5 rules","checked":"2026-10-17","quote":"On top of the UI5 rules sit the ones that are the reason this tool exists rather than a UI5 linter: the defects that live between the ABAP class and the view it builds, and stay silent at runtime."},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, The abap2UI5 rules","checked":"2026-10-17","quote":"There are more than a hundred rules in total."},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, Adopting it on a codebase that already exists","checked":"2026-10-17","quote":"The baseline freezes that debt instead of hiding it:"}]}],"requires":[{"ref":"artifact:abap2ui5-abap2ui5","requirement":"required","basis":"binding","role":"framework","for":"the app classes it checks: the view it judges is reconstructed from the class's `z2ui5_cl_ui5_view_builder` chain, and a class that builds its view with the frozen predecessor of that builder cannot be read by those rules","sources":[{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter","checked":"2026-10-17","quote":"It is built by a chain of z2ui5_cl_ui5_view_builder calls and handed to the browser as a string, so the ABAP compiler never sees a control name, and no UI5 tooling ever sees the class."},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, The abap2UI5 rules","checked":"2026-10-17","quote":"the class builds its view with the frozen predecessor of z2ui5_cl_ui5_view_builder"}]},{"ref":"external:playwright","requirement":"conditional","basis":"binding","role":"headless-browser","condition":"the render gate or --screenshot is used","for":"the headless Chromium the render gate loads the view in: that gate is a second install, `@abap2ui5/linter-render` plus `npx playwright install chromium`, and the property gate runs in full without it","sources":[{"url":"https://github.com/abap2ui5/linter","title":"abap2UI5/linter — README, Documentation","checked":"2026-10-17","quote":"`npm i -D @abap2ui5/linter-render` + `npx playwright install chromium` — the headless `XMLView.create` that catches a view which fails to *load*"},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, The render gate","checked":"2026-10-17","quote":"Without it the property gate still runs in full, and says so"}]}],"interfaces":[{"key":"library","kind":"api","direction":"in","for":"calling the gates from code: `checkFiles`, `checkAbapSource` and `checkXmlSource` return the findings, `screenshotFiles` returns PNG buffers for an editor holding an unsaved buffer, and the `findings` and `report` subpaths expose the rule registry and the formatters","sources":[{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, As a library","checked":"2026-10-17","quote":"screenshotFiles is the same runtime taking pictures instead of a verdict, returning PNGs as buffers"},{"url":"https://abap2ui5.github.io/docs/advanced/linter.html","title":"abap2UI5 — abap2UI5 linter, As a library","checked":"2026-10-17","quote":"The findings subpath exposes the rule registry, the severity/message annotation and the directive handling, so a consumer never reinvents them; the report subpath holds the formatters, the run summary and the badge builders."}]}],"provenance":{"discovered_via":[{"source":"source:github"}],"first_seen":"2026-10-17"},"drafted_with_ai":true,"contributors":["actor:oblomov-dev"]},"effective_normative_relations":[],"readings":{"liveness":[{"label":"Maintenance","tier":"good","evidence":"released this month"},{"label":"Continuity","tier":"good","evidence":"4 contributors, 1 publisher, org-owned"},{"label":"Repository","tier":"good","evidence":"pushed 2026-10, not archived"}],"compatibility":[{"label":"Declared for","tier":"fair","evidence":"nothing declared"},{"label":"Survived majors","tier":"unknown","evidence":"not read on ABAP: its lines run side by side"},{"label":"Maintainer's CI","tier":"good","evidence":"CI green, 2026-10-23"}],"practice":[{"label":"Tests","tier":"good","evidence":"137 test files, npm test"},{"label":"Docs","tier":"good","evidence":"docs site, README 9 KB"},{"label":"Changelog","tier":"good","evidence":"CHANGELOG in the repo"}],"reach":[{"value":350,"unit":"installs/week"},{"value":0,"unit":"watching"}]},"signals":{"crawled_at":"2026-10-24","latest_version":"0.9.0","majors":{"0.1":{"version":"0.1.0","date":"2026-08-15"},"0.2":{"version":"0.2.0","date":"2026-08-16"},"0.3":{"version":"0.3.0","date":"2026-08-23"},"0.4":{"version":"0.4.0","date":"2026-08-25"},"0.5":{"version":"0.5.0","date":"2026-08-27"},"0.6":{"version":"0.6.0","date":"2026-08-30"},"0.7":{"version":"0.7.0","date":"2026-09-24"},"0.8":{"version":"0.8.0","date":"2026-09-27"},"0.9":{"version":"0.9.0","date":"2026-10-14"}},"license":"MIT","first_release":"2026-08-15","last_release":"2026-10-14","releases":20,"cadence_days":1,"maintainers":1,"repository":"git+https://github.com/abap2UI5/linter.git","repository_directory":null,"peer_cds":null,"dependencies":0,"node_engine":">=22","test_script":true,"types":true,"downloads_weekly":350,"downloads_monthly":7066,"stars":0,"forks":0,"open_issues":0,"archived":false,"pushed_at":"2026-10-23","license_spdx":"MIT","org_owned":true,"default_branch":"main","created_at":"2026-08-01T22:44:19Z","open_prs":0,"tree_truncated":false,"test_files":137,"workflows":9,"other_ci":false,"readme_bytes":9548,"docs_files":0,"changelog":true,"license_file":true,"dts_files":1,"first_commit":"2026-08-01","last_commit":"2026-10-23","commits":305,"contributors":4,"ci_status":"success","ci_run_at":"2026-10-23","ci_workflow":"CI","ci_event":"push","readme_path":"README.md","readme_sha":"59df92b5261ac9650235253b83178e9a78be26f3","months_since_release":0,"dormant":false,"repo_read":"2026-10-24"},"release_notes":{"license":"MIT","quotable":true,"source":{"kind":"repo","path":"CHANGELOG.md","ref":"main","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md"},"format":"headings","releases":[{"version":"0.9.0","date":"2026-10-14","date_source":"heading","heading":"0.9.0 - 2026-10-14","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#090---2026-10-14","sections":[{"kind":"other","heading":"Read before upgrading","items":8},{"kind":"other","heading":"Rules","items":23},{"kind":"other","heading":"Reconstruction","items":16},{"kind":"fix","heading":"--fix","items":6},{"kind":"other","heading":"CLI, output and config","items":17},{"kind":"other","heading":"--cache","items":2},{"kind":"other","heading":"Render gate","items":3},{"kind":"performance","heading":"Performance","items":4},{"kind":"other","heading":"Action","items":3},{"kind":"other","heading":"Metadata","items":3},{"kind":"other","heading":"Also in this release","items":30}],"hash":"1c0e65bf023eb1df"},{"version":"0.8.5","date":"2026-09-30","date_source":"heading","heading":"0.8.5 - 2026-09-30","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#085---2026-09-30","sections":[{"kind":"other","heading":null,"items":1}],"hash":"73cc9908b593496b"},{"version":"0.8.4","date":"2026-09-30","date_source":"heading","heading":"0.8.4 - 2026-09-30","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#084---2026-09-30","sections":[{"kind":"other","heading":null,"items":29}],"hash":"1d8cae2f644470b3"},{"version":"0.8.3","date":"2026-09-28","date_source":"heading","heading":"0.8.3 - 2026-09-28","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#083---2026-09-28","sections":[{"kind":"other","heading":null,"items":1}],"hash":"a8670881fe075807"},{"version":"0.8.2","date":"2026-09-27","date_source":"heading","heading":"0.8.2 - 2026-09-27","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#082---2026-09-27","sections":[{"kind":"other","heading":null,"items":6}],"hash":"72042546ce5af90c"},{"version":"0.8.1","date":"2026-09-27","date_source":"heading","heading":"0.8.1 - 2026-09-27","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#081---2026-09-27","sections":[{"kind":"other","heading":null,"items":9}],"hash":"5b6f8da3d06e423e"},{"version":"0.8.0","date":"2026-09-27","date_source":"heading","heading":"0.8.0 - 2026-09-27","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#080---2026-09-27","sections":[{"kind":"other","heading":null,"items":14}],"hash":"06fac540400849b3"},{"version":"0.7.0","date":"2026-09-24","date_source":"heading","heading":"0.7.0 - 2026-09-24","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#070---2026-09-24","sections":[{"kind":"other","heading":null,"items":72}],"hash":"276b0b0ec3785e67"},{"version":"0.6.1","date":"2026-08-30","date_source":"heading","heading":"0.6.1 - 2026-08-30","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#061---2026-08-30","sections":[{"kind":"other","heading":null,"items":1}],"hash":"f617ef3adc2a68f9"},{"version":"0.6.0","date":"2026-08-30","date_source":"heading","heading":"0.6.0 - 2026-08-30","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#060---2026-08-30","sections":[{"kind":"other","heading":null,"items":13}],"hash":"1eb500e12fbe475c"},{"version":"0.5.1","date":"2026-08-27","date_source":"heading","heading":"0.5.1 - 2026-08-27","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#051---2026-08-27","sections":[{"kind":"other","heading":null,"items":1}],"hash":"a49592ff8a229008"},{"version":"0.5.0","date":"2026-08-27","date_source":"heading","heading":"0.5.0 - 2026-08-27","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#050---2026-08-27","sections":[{"kind":"other","heading":null,"items":3},{"kind":"feature","heading":"Added","items":5}],"hash":"cdcc1155d10ccdb1"},{"version":"0.4.1","date":"2026-08-25","date_source":"heading","heading":"0.4.1 - 2026-08-25","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#041---2026-08-25","sections":[{"kind":"other","heading":null,"items":1}],"hash":"8f9e444661466812"},{"version":"0.4.0","date":"2026-08-25","date_source":"heading","heading":"0.4.0 - 2026-08-25","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#040---2026-08-25","sections":[{"kind":"other","heading":null,"items":4}],"hash":"9aa0d0a9bb75a0cd"},{"version":"0.3.0","date":"2026-08-23","date_source":"heading","heading":"0.3.0 - 2026-08-23","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#030---2026-08-23","sections":[{"kind":"other","heading":null,"items":3}],"hash":"ea59db2114c11eaf"},{"version":"0.2.2","date":"2026-08-18","date_source":"heading","heading":"0.2.2 - 2026-08-18","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#022---2026-08-18","sections":[{"kind":"other","heading":null,"items":6}],"hash":"c28c873c51263517"},{"version":"0.2.1","date":"2026-08-16","date_source":"heading","heading":"0.2.1 - 2026-08-16","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#021---2026-08-16","sections":[{"kind":"other","heading":null,"items":3}],"hash":"76279928e766c8b3"},{"version":"0.2.0","date":"2026-08-16","date_source":"heading","heading":"0.2.0 - 2026-08-16","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#020---2026-08-16","sections":[{"kind":"feature","heading":"New: frozen-view-builder","items":12}],"hash":"610ed5265afb542d"},{"version":"0.1.1","date":"2026-08-15","date_source":"heading","heading":"0.1.1 - 2026-08-15","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#011---2026-08-15","sections":[{"kind":"other","heading":null,"items":2}],"hash":"cdbfe8d16812f16c"},{"version":"0.1.0","date":"2026-08-15","date_source":"heading","heading":"0.1.0 - 2026-08-15","url":"https://github.com/abap2UI5/linter/blob/main/CHANGELOG.md#010---2026-08-15","sections":[{"kind":"other","heading":null,"items":7}],"hash":"5fac99a30bda6bc3"}],"versions":[{"version":"0.9.0","date":"2026-10-14"},{"version":"0.8.5","date":"2026-09-30"},{"version":"0.8.4","date":"2026-09-30"},{"version":"0.8.3","date":"2026-09-28"},{"version":"0.8.2","date":"2026-09-27"},{"version":"0.8.1","date":"2026-09-27"},{"version":"0.8.0","date":"2026-09-27"},{"version":"0.7.0","date":"2026-09-24"},{"version":"0.6.1","date":"2026-08-30"},{"version":"0.6.0","date":"2026-08-30"},{"version":"0.5.1","date":"2026-08-27"},{"version":"0.5.0","date":"2026-08-27"},{"version":"0.4.1","date":"2026-08-25"},{"version":"0.4.0","date":"2026-08-25"},{"version":"0.3.0","date":"2026-08-23"},{"version":"0.2.2","date":"2026-08-18"},{"version":"0.2.1","date":"2026-08-16"},{"version":"0.2.0","date":"2026-08-16"},{"version":"0.1.1","date":"2026-08-15"},{"version":"0.1.0","date":"2026-08-15"}],"crawled_at":"2026-10-25"},"edges":{"maintainers":[{"ref":"actor:abap2ui5","name":"abap2UI5","json":"/actors/abap2ui5.json"},{"ref":"actor:oblomov-dev","name":"oblomov-dev","json":"/actors/oblomov-dev.json"}],"contributors":[{"ref":"actor:oblomov-dev","name":"oblomov-dev","json":"/actors/oblomov-dev.json"}],"explained_by":[],"alternative_to_this":[],"needed_by":[],"available_via":[],"parts":[],"add_on_to":{"ref":"artifact:abap2ui5-abap2ui5","name":"abap2UI5","json":"/artifacts/abap2ui5-abap2ui5.json"},"add_ons":[],"answered_through_parts":[]}}