Skip to content

feat(format): adopt Nextcloud's prettier config - #114

Merged
rubenvdlinde merged 1 commit into
developmentfrom
feat/nextcloud-prettier
Aug 13, 2026
Merged

feat(format): adopt Nextcloud's prettier config#114
rubenvdlinde merged 1 commit into
developmentfrom
feat/nextcloud-prettier

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What this is

Part of the fleet-wide adoption of @nextcloud/prettier-config
(useTabs: true, tabWidth: 4) — the tool Nextcloud itself uses, and the only one in our
stack that covers CSS/SCSS, since @nextcloud/stylelint-config carries no indentation
rule (stylelint 15+ dropped stylistic rules).

Measured first: this app had no style drift

The rollout's premise is that CSS has drifted from the .editorconfig that says
indent_style = tab — true elsewhere (openconnector 32 tab / 603 space, opencatalogi
27 / 347, openregister 219 / 522). Not here. launchpad's styles measure
84 tab-lines / 0 space-lines before and after.

That is not an argument against adopting prettier here; it is the reason to. The
compliance was unenforced — nothing in CI would have noticed it slipping. What this PR
adds is (a) an enforcing check over the styles that were already correct, and (b) a
formatter over the JS/Vue side, which is where the 210-file diff comes from.

Credit where due: #113 had already quoted the stylelint:fix glob so it covers what the
check covers. This is the same defect class one layer out — a rule that exists but reaches
nothing.

Why eslint-config-prettier is not optional

It is spread last, so it can only turn rules off. Two formatters with overlapping
jurisdiction make a repo unfixable — the trap this fleet already hit with php-cs-fixer
and PHPCS, where cs:fix and phpcs demanded opposite things and neither could be
satisfied.

It disables no correctness rule. This app corrects the Vue-2 rule set by hand rather
than via the shared preset, and all 18 of its hand-listed vue/no-deprecated-* rules
plus vue/no-reserved-props, vue/no-v-for-template-key-on-child and
vue/require-slots-as-functions remain present and ON
— prettier has no opinion about
any of them. indent is now off in eslint and enforced by prettier's useTabs: true:
the same tab, from the tool that also covers styles.

Why the glob is code and styles, not .

Unrestricted, prettier would rewrite markdown and JSON that has its own generator:

path why that is dangerous
openspec/** parsed by the hydra gates — gate-16 reads @spec anchors, gate-19 reads Scenario headings. A formatter and a gate disagreeing about one file is how the gate loses quietly
l10n/** written by the translation workflow
lib/Settings/**.json OpenRegister register/schema config, read at install and parsed by the manifest gates

So the glob is **/*.{js,ts,vue,css,scss}, with build output in .prettierignore.

⚠️ l10n/ is in .prettierignore, which the larpingapp pilot did not need. This app
carries 37 generated l10n/*.js bundles (OC.L10N.register(…), four-space indent);
the pilot app is JSON-only. It is also not gitignored, which makes this the one
load-bearing entry in the file — prettier 3 reads .gitignore as an ignore path by
default
, so js/, coverage/ and phpmetrics/ would have been excluded anyway. They
are kept explicit regardless, because an ignore that depends on another file's contents is
one refactor away from silently switching off.

Note: this app had neither of the two hazards

Measured, not assumed — other apps in this rollout hit both:

  • 0 multi-statement inline Vue handlers. Elsewhere these break the build: Vue detects
    multiple statements by testing content.includes(';') and prettier's semi: false
    deletes exactly that semicolon (41 build errors on openregister, 18 handlers on
    opencatalogi).
  • 0 case-mismatched closing tags, the class that made prettier refuse an entire file
    on opencatalogi.

So this diff is a pure reformat.

Verified

check result
npm run format clean
npm run lint exit 0 — 0 errors, 3 warnings (development: 0 errors, 35 warnings)
npm run stylelint exit 0 (same as development)
npm test 641/641, 58/58 files
npm run lint:initial-state exit 0
npm run lint:translation-domain exit 0
npm run check:manifest exit 0
npm run build webpack compiled, 0 errors
style indentation 84 tab / 0 space → 84 tab / 0 space (already compliant)
non-code files touched 0 under openspec/, l10n/, lib/Settings/, docs/, .vscode/

The resolved config was asserted before formatting, because a prettier run with no
config silently falls back to defaults and would have written double quotes, which
@nextcloud/prettier-config forbids. It reads
useTabs=true tabWidth=4 singleQuote=true semi=false printWidth=85.

Installed with npx npm@10.8.2 — npm 11 poisons the lockfile and npm ci then fails in
CI on jobs that never touch Vue.

Gate results

⚠️ gate-16 (spec-coverage) is expected to fail on this PR and it is a false positive,
already being fixed in the gate itself: gate-16 inspects frontend methods, and its
normaliser deliberately does not normalise JS re-wraps (ASI / array elision), so every
prettier-touched method reads as "changed" and the gate demands an @spec tag. Nothing
has been annotated to satisfy it, and the glob has not been narrowed to dodge it

adding @spec tags to methods nobody changed would bake the defect in.

A PR-vs-development table for the same gates at the same base SHA is posted as a
comment below once this run finishes.

Adopts @nextcloud/prettier-config (useTabs: true, tabWidth: 4), the tool
Nextcloud itself uses, which unlike stylelint covers CSS/SCSS.

eslint-config-prettier is spread LAST in eslint.config.js so the two formatters
cannot demand opposite things.

Measured first: this app's styles were already 84 tab-lines / 0 space-lines, so
there was no drift to correct — the value here is the JS/Vue side plus a
standing guarantee for the styles.

l10n/ is in .prettierignore: 37 generated l10n/*.js translation bundles.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ 0b9f065

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
composer ✅ 104/104
npm ✅ 548/548
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-13 08:39 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Gate results — PR vs development, same Hydra Gates job

gate development this PR mine?
gate-7 no-admin-idor FAIL 2 FAIL 2 no — identical
gate-19 e2e-coverage FAIL 128 FAIL 128 no — identical
gate-26 visual-coverage FAIL 1 FAIL 1 no — identical
gate-57 orphaned-write-capability FAIL 1 FAIL 1 no — identical
gate-16 spec-coverage PASS FAIL 18 no — known false positive

gate-16 is the only gate that moves, and it is the false positive already being fixed in
the gate.
It inspects frontend methods, and its normaliser deliberately does not
normalise JS re-wraps (ASI / array elision), so every prettier-touched method reads as
"changed" and the gate demands an @spec tag.

Nothing has been annotated to satisfy it and the glob has not been narrowed to dodge it —
adding @spec tags to methods nobody changed would bake the defect in.

Every other failing gate reports the identical count on both sides.

@rubenvdlinde
rubenvdlinde merged commit cf6b07a into development Aug 13, 2026
32 of 34 checks passed
@rubenvdlinde
rubenvdlinde deleted the feat/nextcloud-prettier branch August 14, 2026 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants