From 1209b1f2107921fb0958ad4bdc5d19f42feca900 Mon Sep 17 00:00:00 2001 From: Laurence Chen Date: Mon, 9 Mar 2026 16:06:49 +0800 Subject: [PATCH 1/2] export clj-kondo hooks and config for library consumers Bundle the hooks and config under resources/clj-kondo.exports/ so downstream users can activate them via: clj-kondo --copy-configs --dependencies --lint classpath Update README and CHANGELOG accordingly. --- CHANGELOG.md | 4 ++ README.md | 10 ++- .../com.lambdaisland/ornament/config.edn | 5 ++ .../ornament/hooks/ornament.clj | 71 +++++++++++++++++++ 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 resources/clj-kondo.exports/com.lambdaisland/ornament/config.edn create mode 100644 resources/clj-kondo.exports/com.lambdaisland/ornament/hooks/ornament.clj diff --git a/CHANGELOG.md b/CHANGELOG.md index d0cbba9..4c6d52a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Added +- Export clj-kondo hooks and config via `resources/clj-kondo.exports/` so library + consumers can activate them by running + `clj-kondo --copy-configs --dependencies --lint classpath` + ## Fixed ## Changed diff --git a/README.md b/README.md index e0efc9f..0ae18fb 100644 --- a/README.md +++ b/README.md @@ -945,11 +945,15 @@ meta-merge). e.g. `{:colors ^:replace {...}}`) ## clj-kondo Support -This library includes a built-in clj-kondo configuration to improve linting for Ornament components. +Ornament ships clj-kondo hooks and configuration that validate `defstyled` forms — catching bad tag names, invalid syntax, and providing correct `def`-like analysis. -To use the configuration, simply copy the .clj-kondo/ directory from this repository into the root of your project. +The hooks are bundled in the JAR under `clj-kondo.exports/`. To activate them in your project, run: -After copying the directory, clj-kondo will automatically use this configuration to provide more accurate linting and reduce false positives in your Ornament projects. +```bash +clj-kondo --copy-configs --dependencies --lint classpath +``` + +This copies the config and hook into your `.clj-kondo/` directory. After that, clj-kondo will automatically validate `defstyled` forms in your project. ## Babashka compatibility diff --git a/resources/clj-kondo.exports/com.lambdaisland/ornament/config.edn b/resources/clj-kondo.exports/com.lambdaisland/ornament/config.edn new file mode 100644 index 0000000..548c6e6 --- /dev/null +++ b/resources/clj-kondo.exports/com.lambdaisland/ornament/config.edn @@ -0,0 +1,5 @@ +{:lint-as {lambdaisland.ornament/defprop clojure.core/def + lambdaisland.ornament/defrules clojure.core/def} + :hooks {:analyze-call {lambdaisland.ornament/defstyled hooks.ornament/defstyled}} + :linters {:lambdaisland.ornament/invalid-syntax + {:level :warning}}} diff --git a/resources/clj-kondo.exports/com.lambdaisland/ornament/hooks/ornament.clj b/resources/clj-kondo.exports/com.lambdaisland/ornament/hooks/ornament.clj new file mode 100644 index 0000000..d43953d --- /dev/null +++ b/resources/clj-kondo.exports/com.lambdaisland/ornament/hooks/ornament.clj @@ -0,0 +1,71 @@ +(ns hooks.ornament + (:require [clj-kondo.hooks-api :as api])) + +(defonce styled-registry (atom #{})) + +(defn- symbol-node? [node] + (and (api/token-node? node) + (symbol? (api/sexpr node)))) + +(defn- styled-component? [node] + (and (symbol-node? node) + (contains? @styled-registry (api/sexpr node)))) + +(defn defstyled [{:keys [node]}] + (let [[class-name html-tag & more] (rest (:children node)) + _ (when-not (and (symbol-node? class-name) + (simple-symbol? (api/sexpr class-name))) + (api/reg-finding! {:row (:row (meta class-name)) + :col (:col (meta class-name)) + :message "Style name must be a simple symbol" + :type :lambdaisland.ornament/invalid-syntax})) + _ (when-not (or (api/keyword-node? html-tag) + (styled-component? html-tag)) + (api/reg-finding! {:row (:row (meta html-tag)) + :col (:col (meta html-tag)) + :message "Tag must be a keyword or an ornament-styled-component" + :type :lambdaisland.ornament/invalid-syntax})) + fn-tag (first (drop-while (fn [x] + (or (api/string-node? x) + (api/keyword-node? x) + (api/map-node? x) + (api/vector-node? x) + (api/token-node? x))) + more)) + _ (when (and fn-tag + (not (api/list-node? fn-tag))) + (api/reg-finding! {:row (:row (meta fn-tag)) + :col (:col (meta fn-tag)) + :message "Function part (if present) must be a list" + :type :lambdaisland.ornament/invalid-syntax})) + symbol-tag? (symbol-node? html-tag)] + ;; Register this component in the styled-registry + (swap! styled-registry conj (api/sexpr class-name)) + (if (api/list-node? fn-tag) + (let [[binding-vec & body] (:children fn-tag) + fn-node (api/list-node + (list* + (api/token-node 'fn) + binding-vec + body)) + new-def-node (api/list-node + (if symbol-tag? + (list (api/token-node 'def) + class-name + (api/list-node + (list (api/token-node 'do) + html-tag + fn-node))) + (list (api/token-node 'def) + class-name + fn-node)))] + {:node new-def-node}) + (let [def-class-form (api/list-node + (if symbol-tag? + (list (api/token-node 'def) + class-name + html-tag) + (list (api/token-node 'def) + class-name + (api/token-node 'nil))))] + {:node def-class-form})))) From 50e4dff516604813f86c3b1ac6e57df87bdd0740 Mon Sep 17 00:00:00 2001 From: Laurence Chen Date: Mon, 9 Mar 2026 16:12:27 +0800 Subject: [PATCH 2/2] fix clj-kondo import instructions in README Use the correct two-step workflow from the clj-kondo docs: --copy-configs --skip-lint (to copy configs) --dependencies --parallel (to warm the cache) The previous instruction used wrong flags and a literal "classpath" string instead of the actual classpath expansion. --- README.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0ae18fb..148c6dc 100644 --- a/README.md +++ b/README.md @@ -947,13 +947,24 @@ meta-merge). e.g. `{:colors ^:replace {...}}`) Ornament ships clj-kondo hooks and configuration that validate `defstyled` forms — catching bad tag names, invalid syntax, and providing correct `def`-like analysis. -The hooks are bundled in the JAR under `clj-kondo.exports/`. To activate them in your project, run: +The hooks are bundled in the JAR under `clj-kondo.exports/`. To activate them in your project: -```bash -clj-kondo --copy-configs --dependencies --lint classpath -``` +1. Ensure a `.clj-kondo` directory exists at your project root: + ``` + mkdir -p .clj-kondo + ``` + +2. Copy the configs from your dependencies: + ``` + clj-kondo --lint "$(clojure -Spath)" --copy-configs --skip-lint + ``` + +3. Warm the linting cache: + ``` + clj-kondo --lint "$(clojure -Spath)" --dependencies --parallel + ``` -This copies the config and hook into your `.clj-kondo/` directory. After that, clj-kondo will automatically validate `defstyled` forms in your project. +After that, clj-kondo will automatically validate `defstyled` forms in your project. Consider checking the copied configs into version control. ## Babashka compatibility