Skip to content

Instantly share code, notes, and snippets.

@Deraen
Created December 13, 2023 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Deraen/67a780b143fd5c402c45c81bb82387b3 to your computer and use it in GitHub Desktop.
Save Deraen/67a780b143fd5c402c45c81bb82387b3 to your computer and use it in GitHub Desktop.
UIx MUI linter
(ns dev.linters
(:require [cljs.analyzer :as ana]
[clojure.string :as str]
[uix.linter :as linter])
(:import (cljs.tagged_literals
JSValue)))
(defn mui-component? [tag]
;; TODO: Could check better if it looks like a MUI component
(symbol? tag))
(defn js-object? [v]
(and (instance? JSValue v)
(map? (.-val v))))
(defn- fn-literal? [form]
(and (list? form) ('#{fn fn*} (first form))))
(defn camel-case? [s]
(not (str/includes? s "-")))
;; Validate :sx value is JS object or fn.
;; Validate :sx JS object keys look like camelCase.
(defmethod linter/lint-element :element/mui-sx [_ form _env]
(let [[_ tag props & _children] form
sx (:sx props)]
(when (and (mui-component? tag)
(map? props)
sx)
;; TODO: The JS object could be dynamically created
;; Maybe it is better to warn when map? value is used vs. trying to
;; detect correct values?
(when (not (or (js-object? sx)
(fn-literal? sx)))
(linter/add-error! form :element/mui-sx (linter/form->loc sx)))
(let [sx-map (cond
(js-object? sx) (.-val sx)
;; TODO: Find fn-literal return value and validate that.
)]
;; Could setup hash-set with valid keys to compare against.
;; New checked keys could be stored to the set.
;; Could be faster than to test same keys again?
(doseq [[k _] sx-map]
(when-not (camel-case? (name k))
(linter/add-error! form :element/mui-sx-case (linter/form->loc sx-map))))))))
(defmethod ana/error-message :element/mui-sx [_ _]
"MUI :sx property needs to be defined as a JS value or a function returning one")
(defmethod ana/error-message :element/mui-sx-case [_ _]
"MUI :sx properties need to be written in camelCase")
;; TODO: Validate :slot :slotProps
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment