diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..16bd7c7 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Test + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: 'pnpm' + registry-url: 'https://npm.pkg.github.com' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + env: + NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} + + - name: Run tests + run: pnpm test diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 0000000..98475b5 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1 @@ +pnpm test diff --git a/README.md b/README.md index 074b9fa..a92187e 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,25 @@ pnpm dep:outdated # Check for outdated dependencies across workspaces pnpm dep:update # Update all dependencies ``` +## πŸ“ Testing + +```bash +pnpm test +``` + +Added to catch two types of problems: +- **Dependency updates** silently changing rules +- **Our own config edits** disabling or weakening rules + +Each package has two test files: +- `config.snapshot.test.js` β€” snapshots the full config and fails on a change +- `rules.test.js` / `format.test.js` β€” behavioral tests that lint/format real code snippets + +Tests run on pre-push and in GitHub Actions on every pull request. + ## 🎨 Formatting & Linting -The linting in this monorepo uses the settings defined in the child packages. -Husky (CaptainHook alternative) ensures that all files are automatically formatted and linted with each commit. +The linting in this monorepo uses the settings defined in the child packages. Husky ensures that all files are automatically formatted and linted with each commit. ## About us diff --git a/package.json b/package.json index a8926ae..bd3c9cf 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,12 @@ }, "license": "EUPL-1.2", "private": true, + "publishConfig": { + "registry": "https://npm.pkg.github.com/@yardinternet" + }, "packageManager": "pnpm@10.33.0", "scripts": { + "test": "vitest run", "lint:js": "yard-toolkit lint js -m custom ./packages/**/src/**/*.js", "format:js": "yard-toolkit format js -m custom ./packages/**/*.js", "dep:check": "syncpack list-mismatches", @@ -21,9 +25,13 @@ }, "type": "commonjs", "devDependencies": { + "@babel/core": "^7.29.7", + "@babel/eslint-parser": "^7.25.7", + "@yardinternet/toolkit": "workspace:*", "husky": "^9.1.7", "lerna": "^9.0.4", "lint-staged": "^16.2.7", - "syncpack": "^14.0.0" + "syncpack": "^14.0.0", + "vitest": "^3.2.6" } } diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 93f059b..ce69296 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -4,7 +4,7 @@ "description": "Eslint configuration", "main": "src/index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "vitest run" }, "publishConfig": { "registry": "https://npm.pkg.github.com/" @@ -18,6 +18,7 @@ "author": "", "license": "ISC", "dependencies": { + "@babel/eslint-parser": "^7.25.7", "@babel/preset-react": "^7.29.7", "@eslint/compat": "^2.1.0", "@eslint/eslintrc": "^3.3.3", @@ -29,5 +30,9 @@ "eslint-plugin-import": "^2.32.0", "eslint-plugin-react-hooks": "^7.1.1", "globals": "^17.6.0" + }, + "devDependencies": { + "eslint": "^9.39.4", + "vitest": "^3.2.6" } } diff --git a/packages/eslint-config/tests/__snapshots__/config.snapshot.test.js.snap b/packages/eslint-config/tests/__snapshots__/config.snapshot.test.js.snap new file mode 100644 index 0000000..55591de --- /dev/null +++ b/packages/eslint-config/tests/__snapshots__/config.snapshot.test.js.snap @@ -0,0 +1,1919 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`eslint config array length is stable 1`] = `23`; + +exports[`eslint config explicit rules match snapshot 1`] = ` +[ + { + "jsx-a11y/alt-text": "error", + "jsx-a11y/anchor-ambiguous-text": "off", + "jsx-a11y/anchor-has-content": "error", + "jsx-a11y/anchor-is-valid": "error", + "jsx-a11y/aria-activedescendant-has-tabindex": "error", + "jsx-a11y/aria-props": "error", + "jsx-a11y/aria-proptypes": "error", + "jsx-a11y/aria-role": "error", + "jsx-a11y/aria-unsupported-elements": "error", + "jsx-a11y/autocomplete-valid": "error", + "jsx-a11y/click-events-have-key-events": "error", + "jsx-a11y/control-has-associated-label": [ + "off", + { + "ignoreElements": [ + "audio", + "canvas", + "embed", + "input", + "textarea", + "tr", + "video", + ], + "ignoreRoles": [ + "grid", + "listbox", + "menu", + "menubar", + "radiogroup", + "row", + "tablist", + "toolbar", + "tree", + "treegrid", + ], + "includeRoles": [ + "alert", + "dialog", + ], + }, + ], + "jsx-a11y/heading-has-content": "error", + "jsx-a11y/html-has-lang": "error", + "jsx-a11y/iframe-has-title": "error", + "jsx-a11y/img-redundant-alt": "error", + "jsx-a11y/interactive-supports-focus": [ + "error", + { + "tabbable": [ + "button", + "checkbox", + "link", + "searchbox", + "spinbutton", + "switch", + "textbox", + ], + }, + ], + "jsx-a11y/label-has-associated-control": "error", + "jsx-a11y/label-has-for": "off", + "jsx-a11y/media-has-caption": "error", + "jsx-a11y/mouse-events-have-key-events": "error", + "jsx-a11y/no-access-key": "error", + "jsx-a11y/no-autofocus": "error", + "jsx-a11y/no-distracting-elements": "error", + "jsx-a11y/no-interactive-element-to-noninteractive-role": [ + "error", + { + "canvas": [ + "img", + ], + "tr": [ + "none", + "presentation", + ], + }, + ], + "jsx-a11y/no-noninteractive-element-interactions": [ + "error", + { + "alert": [ + "onKeyUp", + "onKeyDown", + "onKeyPress", + ], + "body": [ + "onError", + "onLoad", + ], + "dialog": [ + "onKeyUp", + "onKeyDown", + "onKeyPress", + ], + "handlers": [ + "onClick", + "onError", + "onLoad", + "onMouseDown", + "onMouseUp", + "onKeyPress", + "onKeyDown", + "onKeyUp", + ], + "iframe": [ + "onError", + "onLoad", + ], + "img": [ + "onError", + "onLoad", + ], + }, + ], + "jsx-a11y/no-noninteractive-element-to-interactive-role": [ + "error", + { + "fieldset": [ + "radiogroup", + "presentation", + ], + "li": [ + "menuitem", + "menuitemradio", + "menuitemcheckbox", + "option", + "row", + "tab", + "treeitem", + ], + "ol": [ + "listbox", + "menu", + "menubar", + "radiogroup", + "tablist", + "tree", + "treegrid", + ], + "table": [ + "grid", + ], + "td": [ + "gridcell", + ], + "ul": [ + "listbox", + "menu", + "menubar", + "radiogroup", + "tablist", + "tree", + "treegrid", + ], + }, + ], + "jsx-a11y/no-noninteractive-tabindex": [ + "error", + { + "allowExpressionValues": true, + "roles": [ + "tabpanel", + ], + "tags": [], + }, + ], + "jsx-a11y/no-redundant-roles": "error", + "jsx-a11y/no-static-element-interactions": [ + "error", + { + "allowExpressionValues": true, + "handlers": [ + "onClick", + "onMouseDown", + "onMouseUp", + "onKeyPress", + "onKeyDown", + "onKeyUp", + ], + }, + ], + "jsx-a11y/role-has-required-aria-props": "error", + "jsx-a11y/role-supports-aria-props": "error", + "jsx-a11y/scope": "error", + "jsx-a11y/tabindex-no-positive": "error", + }, + { + "jsx-a11y/label-has-associated-control": [ + "error", + { + "assert": "htmlFor", + }, + ], + "jsx-a11y/media-has-caption": "off", + "jsx-a11y/no-noninteractive-tabindex": "off", + "jsx-a11y/role-has-required-aria-props": "off", + "jsx-quotes": "error", + }, + { + "@wordpress/no-base-control-with-label-without-id": "error", + "@wordpress/no-global-active-element": "error", + "@wordpress/no-global-get-selection": "error", + "@wordpress/no-setting-ds-tokens": "error", + "@wordpress/no-unguarded-get-range-at": "error", + "@wordpress/no-unknown-ds-tokens": "error", + "@wordpress/no-unsafe-wp-apis": "error", + "@wordpress/no-unused-vars-before-return": "error", + "@wordpress/no-wp-process-env": "error", + }, + { + "@wordpress/i18n-hyphenated-range": "error", + "@wordpress/i18n-no-flanking-whitespace": "error", + "@wordpress/no-base-control-with-label-without-id": "off", + }, + { + "@wordpress/no-global-active-element": "off", + "@wordpress/no-global-get-selection": "off", + }, + { + "react/display-name": 2, + "react/jsx-key": 2, + "react/jsx-no-comment-textnodes": 2, + "react/jsx-no-duplicate-props": 2, + "react/jsx-no-target-blank": 2, + "react/jsx-no-undef": 2, + "react/jsx-uses-react": 2, + "react/jsx-uses-vars": 2, + "react/no-children-prop": 2, + "react/no-danger-with-children": 2, + "react/no-deprecated": 2, + "react/no-direct-mutation-state": 2, + "react/no-find-dom-node": 2, + "react/no-is-mounted": 2, + "react/no-render-return-value": 2, + "react/no-string-refs": 2, + "react/no-unescaped-entities": 2, + "react/no-unknown-property": 2, + "react/no-unsafe": 0, + "react/prop-types": 2, + "react/react-in-jsx-scope": 2, + "react/require-render-return": 2, + }, + { + "@wordpress/no-unused-vars-before-return": [ + "error", + { + "excludePattern": "^use", + }, + ], + "react-hooks/exhaustive-deps": [ + "warn", + { + "additionalHooks": "^(useSelect|useSuspenseSelect)$", + }, + ], + "react-hooks/rules-of-hooks": "error", + "react/display-name": "off", + "react/jsx-curly-spacing": [ + "error", + { + "children": true, + "when": "always", + }, + ], + "react/jsx-equals-spacing": "error", + "react/jsx-indent": [ + "error", + "tab", + ], + "react/jsx-indent-props": [ + "error", + "tab", + ], + "react/jsx-key": "error", + "react/jsx-tag-spacing": "error", + "react/no-children-prop": "off", + "react/prop-types": "off", + "react/react-in-jsx-scope": "off", + }, + { + "jsdoc/check-access": "warn", + "jsdoc/check-alignment": "warn", + "jsdoc/check-examples": "off", + "jsdoc/check-indentation": "off", + "jsdoc/check-line-alignment": "off", + "jsdoc/check-param-names": "warn", + "jsdoc/check-property-names": "warn", + "jsdoc/check-syntax": "off", + "jsdoc/check-tag-names": "warn", + "jsdoc/check-types": "warn", + "jsdoc/check-values": "warn", + "jsdoc/empty-tags": "warn", + "jsdoc/implements-on-classes": "warn", + "jsdoc/imports-as-dependencies": "off", + "jsdoc/informative-docs": "off", + "jsdoc/match-description": "off", + "jsdoc/match-name": "off", + "jsdoc/multiline-blocks": "warn", + "jsdoc/no-bad-blocks": "off", + "jsdoc/no-blank-block-descriptions": "off", + "jsdoc/no-blank-blocks": "off", + "jsdoc/no-defaults": "warn", + "jsdoc/no-missing-syntax": "off", + "jsdoc/no-multi-asterisks": "warn", + "jsdoc/no-restricted-syntax": "off", + "jsdoc/no-types": "off", + "jsdoc/no-undefined-types": "warn", + "jsdoc/require-asterisk-prefix": "off", + "jsdoc/require-description": "off", + "jsdoc/require-description-complete-sentence": "off", + "jsdoc/require-example": "off", + "jsdoc/require-file-overview": "off", + "jsdoc/require-hyphen-before-param-description": "off", + "jsdoc/require-jsdoc": "warn", + "jsdoc/require-param": "warn", + "jsdoc/require-param-description": "warn", + "jsdoc/require-param-name": "warn", + "jsdoc/require-param-type": "warn", + "jsdoc/require-property": "warn", + "jsdoc/require-property-description": "warn", + "jsdoc/require-property-name": "warn", + "jsdoc/require-property-type": "warn", + "jsdoc/require-returns": "warn", + "jsdoc/require-returns-check": "warn", + "jsdoc/require-returns-description": "warn", + "jsdoc/require-returns-type": "warn", + "jsdoc/require-throws": "off", + "jsdoc/require-yields": "warn", + "jsdoc/require-yields-check": "warn", + "jsdoc/sort-tags": "off", + "jsdoc/tag-lines": "warn", + "jsdoc/text-escaping": "off", + "jsdoc/valid-types": "warn", + }, + { + "jsdoc/check-access": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-line-alignment": [ + "error", + "always", + { + "preserveMainDescriptionPostDelimiter": true, + "tags": [ + "param", + "arg", + "argument", + "property", + "prop", + ], + }, + ], + "jsdoc/check-param-names": "error", + "jsdoc/check-property-names": "error", + "jsdoc/check-tag-names": "error", + "jsdoc/check-types": "error", + "jsdoc/check-values": "off", + "jsdoc/empty-tags": "error", + "jsdoc/implements-on-classes": "error", + "jsdoc/no-defaults": "off", + "jsdoc/no-multi-asterisks": [ + "error", + { + "preventAtMiddleLines": false, + }, + ], + "jsdoc/no-undefined-types": [ + "error", + { + "definedTypes": [ + "AbortController", + "AbortSignal", + "AnalyserNode", + "Animation", + "AnimationEffectReadOnly", + "AnimationEffectTiming", + "AnimationEffectTimingReadOnly", + "AnimationEvent", + "AnimationPlaybackEvent", + "AnimationTimeline", + "ApplicationCache", + "ApplicationCacheErrorEvent", + "Attr", + "Audio", + "AudioBuffer", + "AudioBufferSourceNode", + "AudioContext", + "AudioDestinationNode", + "AudioListener", + "AudioNode", + "AudioParam", + "AudioProcessingEvent", + "AudioScheduledSourceNode", + "AudioWorkletGlobalScope", + "AudioWorkletNode", + "AudioWorkletProcessor", + "BarProp", + "BaseAudioContext", + "BatteryManager", + "BeforeUnloadEvent", + "BiquadFilterNode", + "Blob", + "BlobEvent", + "BroadcastChannel", + "BudgetService", + "ByteLengthQueuingStrategy", + "Cache", + "CacheStorage", + "CanvasCaptureMediaStreamTrack", + "CanvasGradient", + "CanvasPattern", + "CanvasRenderingContext2D", + "ChannelMergerNode", + "ChannelSplitterNode", + "CharacterData", + "ClipboardEvent", + "ClipboardItem", + "CloseEvent", + "Comment", + "CompositionEvent", + "CompressionStream", + "ConstantSourceNode", + "ConvolverNode", + "CountQueuingStrategy", + "Credential", + "CredentialsContainer", + "Crypto", + "CryptoKey", + "CSS", + "CSSConditionRule", + "CSSFontFaceRule", + "CSSGroupingRule", + "CSSImportRule", + "CSSKeyframeRule", + "CSSKeyframesRule", + "CSSMatrixComponent", + "CSSMediaRule", + "CSSNamespaceRule", + "CSSPageRule", + "CSSPerspective", + "CSSRotate", + "CSSRule", + "CSSRuleList", + "CSSScale", + "CSSSkew", + "CSSSkewX", + "CSSSkewY", + "CSSStyleDeclaration", + "CSSStyleRule", + "CSSStyleSheet", + "CSSSupportsRule", + "CSSTransformValue", + "CSSTranslate", + "CustomElementRegistry", + "CustomEvent", + "DataTransfer", + "DataTransferItem", + "DataTransferItemList", + "DecompressionStream", + "DelayNode", + "DeviceMotionEvent", + "DeviceOrientationEvent", + "Document", + "DocumentFragment", + "DocumentType", + "DOMError", + "DOMException", + "DOMImplementation", + "DOMMatrix", + "DOMMatrixReadOnly", + "DOMParser", + "DOMPoint", + "DOMPointReadOnly", + "DOMQuad", + "DOMRect", + "DOMRectList", + "DOMRectReadOnly", + "DOMStringList", + "DOMStringMap", + "DOMTokenList", + "DragEvent", + "DynamicsCompressorNode", + "Element", + "ErrorEvent", + "Event", + "EventSource", + "EventTarget", + "File", + "FileList", + "FileReader", + "FocusEvent", + "FontFace", + "FontFaceSetLoadEvent", + "FormData", + "FormDataEvent", + "GainNode", + "Gamepad", + "GamepadButton", + "GamepadEvent", + "HashChangeEvent", + "Headers", + "History", + "HTMLAllCollection", + "HTMLAnchorElement", + "HTMLAreaElement", + "HTMLAudioElement", + "HTMLBaseElement", + "HTMLBodyElement", + "HTMLBRElement", + "HTMLButtonElement", + "HTMLCanvasElement", + "HTMLCollection", + "HTMLContentElement", + "HTMLDataElement", + "HTMLDataListElement", + "HTMLDetailsElement", + "HTMLDialogElement", + "HTMLDirectoryElement", + "HTMLDivElement", + "HTMLDListElement", + "HTMLDocument", + "HTMLElement", + "HTMLEmbedElement", + "HTMLFieldSetElement", + "HTMLFontElement", + "HTMLFormControlsCollection", + "HTMLFormElement", + "HTMLFrameElement", + "HTMLFrameSetElement", + "HTMLHeadElement", + "HTMLHeadingElement", + "HTMLHRElement", + "HTMLHtmlElement", + "HTMLIFrameElement", + "HTMLImageElement", + "HTMLInputElement", + "HTMLLabelElement", + "HTMLLegendElement", + "HTMLLIElement", + "HTMLLinkElement", + "HTMLMapElement", + "HTMLMarqueeElement", + "HTMLMediaElement", + "HTMLMenuElement", + "HTMLMetaElement", + "HTMLMeterElement", + "HTMLModElement", + "HTMLObjectElement", + "HTMLOListElement", + "HTMLOptGroupElement", + "HTMLOptionElement", + "HTMLOptionsCollection", + "HTMLOutputElement", + "HTMLParagraphElement", + "HTMLParamElement", + "HTMLPictureElement", + "HTMLPreElement", + "HTMLProgressElement", + "HTMLQuoteElement", + "HTMLScriptElement", + "HTMLSelectElement", + "HTMLShadowElement", + "HTMLSlotElement", + "HTMLSourceElement", + "HTMLSpanElement", + "HTMLStyleElement", + "HTMLTableCaptionElement", + "HTMLTableCellElement", + "HTMLTableColElement", + "HTMLTableElement", + "HTMLTableRowElement", + "HTMLTableSectionElement", + "HTMLTemplateElement", + "HTMLTextAreaElement", + "HTMLTimeElement", + "HTMLTitleElement", + "HTMLTrackElement", + "HTMLUListElement", + "HTMLUnknownElement", + "HTMLVideoElement", + "IDBCursor", + "IDBCursorWithValue", + "IDBDatabase", + "IDBFactory", + "IDBIndex", + "IDBKeyRange", + "IDBObjectStore", + "IDBOpenDBRequest", + "IDBRequest", + "IDBTransaction", + "IDBVersionChangeEvent", + "IdleDeadline", + "IIRFilterNode", + "Image", + "ImageBitmap", + "ImageBitmapRenderingContext", + "ImageCapture", + "ImageData", + "InputEvent", + "IntersectionObserver", + "IntersectionObserverEntry", + "Intl", + "KeyboardEvent", + "KeyframeEffect", + "KeyframeEffectReadOnly", + "Location", + "MediaDeviceInfo", + "MediaDevices", + "MediaElementAudioSourceNode", + "MediaEncryptedEvent", + "MediaError", + "MediaKeyMessageEvent", + "MediaKeySession", + "MediaKeyStatusMap", + "MediaKeySystemAccess", + "MediaList", + "MediaMetadata", + "MediaQueryList", + "MediaQueryListEvent", + "MediaRecorder", + "MediaSettingsRange", + "MediaSource", + "MediaStream", + "MediaStreamAudioDestinationNode", + "MediaStreamAudioSourceNode", + "MediaStreamConstraints", + "MediaStreamEvent", + "MediaStreamTrack", + "MediaStreamTrackEvent", + "MessageChannel", + "MessageEvent", + "MessagePort", + "MIDIAccess", + "MIDIConnectionEvent", + "MIDIInput", + "MIDIInputMap", + "MIDIMessageEvent", + "MIDIOutput", + "MIDIOutputMap", + "MIDIPort", + "MimeType", + "MimeTypeArray", + "MouseEvent", + "MutationEvent", + "MutationObserver", + "MutationRecord", + "NamedNodeMap", + "NavigationPreloadManager", + "Navigator", + "NavigatorUAData", + "NetworkInformation", + "Node", + "NodeFilter", + "NodeIterator", + "NodeList", + "Notification", + "OfflineAudioCompletionEvent", + "OfflineAudioContext", + "OffscreenCanvas", + "OffscreenCanvasRenderingContext2D", + "Option", + "OscillatorNode", + "OverconstrainedError", + "PageTransitionEvent", + "PannerNode", + "Path2D", + "PaymentAddress", + "PaymentRequest", + "PaymentRequestUpdateEvent", + "PaymentResponse", + "Performance", + "PerformanceEntry", + "PerformanceLongTaskTiming", + "PerformanceMark", + "PerformanceMeasure", + "PerformanceNavigation", + "PerformanceNavigationTiming", + "PerformanceObserver", + "PerformanceObserverEntryList", + "PerformancePaintTiming", + "PerformanceResourceTiming", + "PerformanceTiming", + "PeriodicWave", + "Permissions", + "PermissionStatus", + "PhotoCapabilities", + "Plugin", + "PluginArray", + "PointerEvent", + "PopStateEvent", + "Presentation", + "PresentationAvailability", + "PresentationConnection", + "PresentationConnectionAvailableEvent", + "PresentationConnectionCloseEvent", + "PresentationConnectionList", + "PresentationReceiver", + "PresentationRequest", + "ProcessingInstruction", + "ProgressEvent", + "PromiseRejectionEvent", + "PushManager", + "PushSubscription", + "PushSubscriptionOptions", + "RadioNodeList", + "Range", + "ReadableByteStreamController", + "ReadableStream", + "ReadableStreamBYOBReader", + "ReadableStreamBYOBRequest", + "ReadableStreamDefaultController", + "ReadableStreamDefaultReader", + "RemotePlayback", + "Request", + "ResizeObserver", + "ResizeObserverEntry", + "Response", + "RTCCertificate", + "RTCDataChannel", + "RTCDataChannelEvent", + "RTCDtlsTransport", + "RTCIceCandidate", + "RTCIceGatherer", + "RTCIceTransport", + "RTCPeerConnection", + "RTCPeerConnectionIceEvent", + "RTCRtpContributingSource", + "RTCRtpReceiver", + "RTCRtpSender", + "RTCSctpTransport", + "RTCSessionDescription", + "RTCStatsReport", + "RTCTrackEvent", + "Screen", + "ScreenOrientation", + "ScriptProcessorNode", + "SecurityPolicyViolationEvent", + "Selection", + "ServiceWorker", + "ServiceWorkerContainer", + "ServiceWorkerRegistration", + "ShadowRoot", + "SharedWorker", + "SourceBuffer", + "SourceBufferList", + "SpeechSynthesisEvent", + "SpeechSynthesisUtterance", + "StaticRange", + "StereoPannerNode", + "Storage", + "StorageEvent", + "StorageManager", + "StyleSheet", + "StyleSheetList", + "SubmitEvent", + "SubtleCrypto", + "SVGAElement", + "SVGAngle", + "SVGAnimatedAngle", + "SVGAnimatedBoolean", + "SVGAnimatedEnumeration", + "SVGAnimatedInteger", + "SVGAnimatedLength", + "SVGAnimatedLengthList", + "SVGAnimatedNumber", + "SVGAnimatedNumberList", + "SVGAnimatedPreserveAspectRatio", + "SVGAnimatedRect", + "SVGAnimatedString", + "SVGAnimatedTransformList", + "SVGAnimateElement", + "SVGAnimateMotionElement", + "SVGAnimateTransformElement", + "SVGAnimationElement", + "SVGCircleElement", + "SVGClipPathElement", + "SVGComponentTransferFunctionElement", + "SVGDefsElement", + "SVGDescElement", + "SVGDiscardElement", + "SVGElement", + "SVGEllipseElement", + "SVGFEBlendElement", + "SVGFEColorMatrixElement", + "SVGFEComponentTransferElement", + "SVGFECompositeElement", + "SVGFEConvolveMatrixElement", + "SVGFEDiffuseLightingElement", + "SVGFEDisplacementMapElement", + "SVGFEDistantLightElement", + "SVGFEDropShadowElement", + "SVGFEFloodElement", + "SVGFEFuncAElement", + "SVGFEFuncBElement", + "SVGFEFuncGElement", + "SVGFEFuncRElement", + "SVGFEGaussianBlurElement", + "SVGFEImageElement", + "SVGFEMergeElement", + "SVGFEMergeNodeElement", + "SVGFEMorphologyElement", + "SVGFEOffsetElement", + "SVGFEPointLightElement", + "SVGFESpecularLightingElement", + "SVGFESpotLightElement", + "SVGFETileElement", + "SVGFETurbulenceElement", + "SVGFilterElement", + "SVGForeignObjectElement", + "SVGGElement", + "SVGGeometryElement", + "SVGGradientElement", + "SVGGraphicsElement", + "SVGImageElement", + "SVGLength", + "SVGLengthList", + "SVGLinearGradientElement", + "SVGLineElement", + "SVGMarkerElement", + "SVGMaskElement", + "SVGMatrix", + "SVGMetadataElement", + "SVGMPathElement", + "SVGNumber", + "SVGNumberList", + "SVGPathElement", + "SVGPatternElement", + "SVGPoint", + "SVGPointList", + "SVGPolygonElement", + "SVGPolylineElement", + "SVGPreserveAspectRatio", + "SVGRadialGradientElement", + "SVGRect", + "SVGRectElement", + "SVGScriptElement", + "SVGSetElement", + "SVGStopElement", + "SVGStringList", + "SVGStyleElement", + "SVGSVGElement", + "SVGSwitchElement", + "SVGSymbolElement", + "SVGTextContentElement", + "SVGTextElement", + "SVGTextPathElement", + "SVGTextPositioningElement", + "SVGTitleElement", + "SVGTransform", + "SVGTransformList", + "SVGTSpanElement", + "SVGUnitTypes", + "SVGUseElement", + "SVGViewElement", + "TaskAttributionTiming", + "Text", + "TextDecoder", + "TextDecoderStream", + "TextEncoder", + "TextEncoderStream", + "TextEvent", + "TextMetrics", + "TextTrack", + "TextTrackCue", + "TextTrackCueList", + "TextTrackList", + "TimeRanges", + "ToggleEvent", + "Touch", + "TouchEvent", + "TouchList", + "TrackEvent", + "TransformStream", + "TransformStreamDefaultController", + "TransitionEvent", + "TreeWalker", + "UIEvent", + "URL", + "URLSearchParams", + "ValidityState", + "VisualViewport", + "VTTCue", + "WaveShaperNode", + "WebAssembly", + "WebGL2RenderingContext", + "WebGLActiveInfo", + "WebGLBuffer", + "WebGLContextEvent", + "WebGLFramebuffer", + "WebGLProgram", + "WebGLQuery", + "WebGLRenderbuffer", + "WebGLRenderingContext", + "WebGLSampler", + "WebGLShader", + "WebGLShaderPrecisionFormat", + "WebGLSync", + "WebGLTexture", + "WebGLTransformFeedback", + "WebGLUniformLocation", + "WebGLVertexArrayObject", + "WebSocket", + "WheelEvent", + "Window", + "Worker", + "WritableStream", + "WritableStreamDefaultController", + "WritableStreamDefaultWriter", + "XMLDocument", + "XMLHttpRequest", + "XMLHttpRequestEventTarget", + "XMLHttpRequestUpload", + "XMLSerializer", + "XPathEvaluator", + "XPathExpression", + "XPathResult", + "XRAnchor", + "XRBoundedReferenceSpace", + "XRCPUDepthInformation", + "XRDepthInformation", + "XRFrame", + "XRInputSource", + "XRInputSourceArray", + "XRInputSourceEvent", + "XRInputSourcesChangeEvent", + "XRPose", + "XRReferenceSpace", + "XRReferenceSpaceEvent", + "XRRenderState", + "XRRigidTransform", + "XRSession", + "XRSessionEvent", + "XRSpace", + "XRSystem", + "XRView", + "XRViewerPose", + "XRViewport", + "XRWebGLBinding", + "XRWebGLDepthInformation", + "XRWebGLLayer", + "XSLTProcessor", + "ArrayLike", + "Exclude", + "Extract", + "InstanceType", + "Iterable", + "IterableIterator", + "NonNullable", + "Omit", + "Parameters", + "Partial", + "Pick", + "PromiseLike", + "Readonly", + "ReadonlyArray", + "ReadonlyMap", + "ReadonlySet", + "Record", + "Required", + "ReturnType", + "ThisType", + "unknown", + "never", + "NodeJS", + "AsyncIterableIterator", + "NodeRequire", + "true", + "false", + "WPBlockChildren", + "WPBlockNode", + "WPBlockSelection", + "WPBlockSerializationOptions", + "WPBlock", + "WPBlockBindingsSource", + "WPBlockPattern", + "WPBlockType", + "WPBlockTypeIcon", + "WPBlockTypeIconRender", + "WPBlockTypeIconDescriptor", + "WPIcon", + "Component", + "Element", + "DOMHighResTimeStamp", + "espree", + "void", + "React", + ], + }, + ], + "jsdoc/require-jsdoc": "off", + "jsdoc/require-param": "error", + "jsdoc/require-param-description": "off", + "jsdoc/require-param-name": "error", + "jsdoc/require-param-type": "error", + "jsdoc/require-property": "error", + "jsdoc/require-property-description": "error", + "jsdoc/require-property-name": "error", + "jsdoc/require-property-type": "error", + "jsdoc/require-returns": "off", + "jsdoc/require-returns-check": "error", + "jsdoc/require-returns-description": "error", + "jsdoc/require-returns-type": "error", + "jsdoc/require-yields": "off", + "jsdoc/tag-lines": [ + 1, + "any", + { + "applyToEndTag": false, + "endLines": 0, + "startLines": null, + }, + ], + "jsdoc/valid-types": "error", + }, + { + "array-bracket-spacing": [ + "error", + "always", + ], + "array-callback-return": "error", + "brace-style": [ + "error", + "1tbs", + ], + "camelcase": [ + "error", + { + "properties": "never", + }, + ], + "comma-dangle": [ + "error", + "always-multiline", + ], + "comma-spacing": "error", + "comma-style": [ + "error", + "last", + ], + "curly": [ + "error", + "all", + ], + "dot-notation": "error", + "eol-last": "error", + "eqeqeq": "error", + "func-call-spacing": "error", + "indent": [ + "error", + "tab", + { + "SwitchCase": 1, + }, + ], + "key-spacing": "error", + "keyword-spacing": "error", + "linebreak-style": [ + "error", + "unix", + ], + "no-alert": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-cond-assign": [ + "error", + "except-parens", + ], + "no-console": "error", + "no-debugger": "error", + "no-dupe-args": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-else-return": "error", + "no-eval": "error", + "no-extra-semi": "error", + "no-fallthrough": "error", + "no-irregular-whitespace": "error", + "no-lonely-if": "error", + "no-mixed-operators": "error", + "no-mixed-spaces-and-tabs": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": [ + "error", + { + "max": 1, + }, + ], + "no-nested-ternary": "error", + "no-redeclare": "error", + "no-shadow": "error", + "no-trailing-spaces": "error", + "no-undef": "error", + "no-undef-init": "error", + "no-unreachable": "error", + "no-unsafe-negation": "error", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { + "ignoreRestSiblings": true, + }, + ], + "no-useless-return": "error", + "no-whitespace-before-property": "error", + "no-with": "error", + "object-curly-spacing": [ + "error", + "always", + ], + "one-var-declaration-per-line": [ + "error", + "initializations", + ], + "operator-linebreak": "error", + "padded-blocks": [ + "error", + "never", + ], + "quote-props": [ + "error", + "as-needed", + ], + "quotes": [ + "error", + "single", + { + "avoidEscape": true, + }, + ], + "semi": "error", + "semi-spacing": "error", + "space-before-blocks": [ + "error", + "always", + ], + "space-before-function-paren": [ + "error", + { + "anonymous": "never", + "asyncArrow": "always", + "named": "never", + }, + ], + "space-in-parens": [ + "error", + "always", + { + "exceptions": [ + "empty", + ], + }, + ], + "space-infix-ops": "error", + "space-unary-ops": [ + "error", + { + "overrides": { + "!": true, + }, + }, + ], + "valid-typeof": "error", + "vars-on-top": "error", + "wrap-iife": "error", + }, + { + "arrow-parens": [ + "error", + "always", + ], + "arrow-spacing": "error", + "computed-property-spacing": [ + "error", + "always", + ], + "constructor-super": "error", + "no-const-assign": "error", + "no-dupe-class-members": "error", + "no-duplicate-imports": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-var": "error", + "object-shorthand": "error", + "prefer-const": [ + "error", + { + "destructuring": "all", + }, + ], + "quotes": [ + "error", + "single", + { + "allowTemplateLiterals": true, + "avoidEscape": true, + }, + ], + "space-unary-ops": [ + "error", + { + "overrides": { + "!": true, + "yield": true, + }, + }, + ], + "template-curly-spacing": [ + "error", + "always", + ], + "vars-on-top": "off", + }, + { + "@wordpress/i18n-ellipsis": "error", + "@wordpress/i18n-hyphenated-range": "error", + "@wordpress/i18n-no-collapsible-whitespace": "error", + "@wordpress/i18n-no-flanking-whitespace": "error", + "@wordpress/i18n-no-placeholders-only": "error", + "@wordpress/i18n-no-variables": "error", + "@wordpress/i18n-text-domain": "error", + "@wordpress/i18n-translator-comments": "error", + "@wordpress/valid-sprintf": "error", + }, + { + "import/default": "warn", + "import/named": "warn", + "import/no-extraneous-dependencies": [ + "error", + { + "peerDependencies": true, + }, + ], + "import/no-unresolved": "error", + }, + { + "@babel/object-curly-spacing": "off", + "@babel/semi": "off", + "@typescript-eslint/block-spacing": "off", + "@typescript-eslint/brace-style": "off", + "@typescript-eslint/comma-dangle": "off", + "@typescript-eslint/comma-spacing": "off", + "@typescript-eslint/func-call-spacing": "off", + "@typescript-eslint/indent": "off", + "@typescript-eslint/key-spacing": "off", + "@typescript-eslint/keyword-spacing": "off", + "@typescript-eslint/lines-around-comment": 0, + "@typescript-eslint/member-delimiter-style": "off", + "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-extra-semi": "off", + "@typescript-eslint/object-curly-spacing": "off", + "@typescript-eslint/quotes": 0, + "@typescript-eslint/semi": "off", + "@typescript-eslint/space-before-blocks": "off", + "@typescript-eslint/space-before-function-paren": "off", + "@typescript-eslint/space-infix-ops": "off", + "@typescript-eslint/type-annotation-spacing": "off", + "array-bracket-newline": "off", + "array-bracket-spacing": "off", + "array-element-newline": "off", + "arrow-parens": "off", + "arrow-spacing": "off", + "babel/object-curly-spacing": "off", + "babel/quotes": 0, + "babel/semi": "off", + "block-spacing": "off", + "brace-style": "off", + "comma-dangle": "off", + "comma-spacing": "off", + "comma-style": "off", + "computed-property-spacing": "off", + "curly": 0, + "dot-location": "off", + "eol-last": "off", + "flowtype/boolean-style": "off", + "flowtype/delimiter-dangle": "off", + "flowtype/generic-spacing": "off", + "flowtype/object-type-curly-spacing": "off", + "flowtype/object-type-delimiter": "off", + "flowtype/quotes": "off", + "flowtype/semi": "off", + "flowtype/space-after-type-colon": "off", + "flowtype/space-before-generic-bracket": "off", + "flowtype/space-before-type-colon": "off", + "flowtype/union-intersection-spacing": "off", + "func-call-spacing": "off", + "function-call-argument-newline": "off", + "function-paren-newline": "off", + "generator-star": "off", + "generator-star-spacing": "off", + "implicit-arrow-linebreak": "off", + "indent": "off", + "indent-legacy": "off", + "jsx-quotes": "off", + "key-spacing": "off", + "keyword-spacing": "off", + "linebreak-style": "off", + "lines-around-comment": 0, + "max-len": 0, + "max-statements-per-line": "off", + "multiline-ternary": "off", + "new-parens": "off", + "newline-per-chained-call": "off", + "no-arrow-condition": "off", + "no-comma-dangle": "off", + "no-confusing-arrow": 0, + "no-extra-parens": "off", + "no-extra-semi": "off", + "no-floating-decimal": "off", + "no-mixed-operators": 0, + "no-mixed-spaces-and-tabs": "off", + "no-multi-spaces": "off", + "no-multiple-empty-lines": "off", + "no-reserved-keys": "off", + "no-space-before-semi": "off", + "no-spaced-func": "off", + "no-tabs": 0, + "no-trailing-spaces": "off", + "no-unexpected-multiline": 0, + "no-whitespace-before-property": "off", + "no-wrap-func": "off", + "nonblock-statement-body-position": "off", + "object-curly-newline": "off", + "object-curly-spacing": "off", + "object-property-newline": "off", + "one-var-declaration-per-line": "off", + "operator-linebreak": "off", + "padded-blocks": "off", + "quote-props": "off", + "quotes": 0, + "react/jsx-child-element-spacing": "off", + "react/jsx-closing-bracket-location": "off", + "react/jsx-closing-tag-location": "off", + "react/jsx-curly-newline": "off", + "react/jsx-curly-spacing": "off", + "react/jsx-equals-spacing": "off", + "react/jsx-first-prop-new-line": "off", + "react/jsx-indent": "off", + "react/jsx-indent-props": "off", + "react/jsx-max-props-per-line": "off", + "react/jsx-newline": "off", + "react/jsx-one-expression-per-line": "off", + "react/jsx-props-no-multi-spaces": "off", + "react/jsx-space-before-closing": "off", + "react/jsx-tag-spacing": "off", + "react/jsx-wrap-multilines": "off", + "rest-spread-spacing": "off", + "semi": "off", + "semi-spacing": "off", + "semi-style": "off", + "space-after-function-name": "off", + "space-after-keywords": "off", + "space-before-blocks": "off", + "space-before-function-paren": "off", + "space-before-function-parentheses": "off", + "space-before-keywords": "off", + "space-in-brackets": "off", + "space-in-parens": "off", + "space-infix-ops": "off", + "space-return-throw-case": "off", + "space-unary-ops": "off", + "space-unary-word-ops": "off", + "standard/array-bracket-even-spacing": "off", + "standard/computed-property-even-spacing": "off", + "standard/object-curly-even-spacing": "off", + "switch-colon-spacing": "off", + "template-curly-spacing": "off", + "template-tag-spacing": "off", + "unicode-bom": "off", + "unicorn/empty-brace-spaces": "off", + "unicorn/no-nested-ternary": "off", + "unicorn/number-literal-case": "off", + "vue/array-bracket-newline": "off", + "vue/array-bracket-spacing": "off", + "vue/array-element-newline": "off", + "vue/arrow-spacing": "off", + "vue/block-spacing": "off", + "vue/block-tag-newline": "off", + "vue/brace-style": "off", + "vue/comma-dangle": "off", + "vue/comma-spacing": "off", + "vue/comma-style": "off", + "vue/dot-location": "off", + "vue/func-call-spacing": "off", + "vue/html-closing-bracket-newline": "off", + "vue/html-closing-bracket-spacing": "off", + "vue/html-end-tags": "off", + "vue/html-indent": "off", + "vue/html-quotes": "off", + "vue/html-self-closing": 0, + "vue/key-spacing": "off", + "vue/keyword-spacing": "off", + "vue/max-attributes-per-line": "off", + "vue/max-len": 0, + "vue/multiline-html-element-content-newline": "off", + "vue/multiline-ternary": "off", + "vue/mustache-interpolation-spacing": "off", + "vue/no-extra-parens": "off", + "vue/no-multi-spaces": "off", + "vue/no-spaces-around-equal-signs-in-attribute": "off", + "vue/object-curly-newline": "off", + "vue/object-curly-spacing": "off", + "vue/object-property-newline": "off", + "vue/operator-linebreak": "off", + "vue/quote-props": "off", + "vue/script-indent": "off", + "vue/singleline-html-element-content-newline": "off", + "vue/space-in-parens": "off", + "vue/space-infix-ops": "off", + "vue/space-unary-ops": "off", + "vue/template-curly-spacing": "off", + "wrap-iife": "off", + "wrap-regex": "off", + "yield-star-spacing": "off", + }, + { + "arrow-body-style": "off", + "prefer-arrow-callback": "off", + "prettier/prettier": "error", + }, + { + "constructor-super": "off", + "getter-return": "off", + "no-class-assign": "off", + "no-const-assign": "off", + "no-dupe-args": "off", + "no-dupe-class-members": "off", + "no-dupe-keys": "off", + "no-func-assign": "off", + "no-import-assign": "off", + "no-new-native-nonconstructor": "off", + "no-new-symbol": "off", + "no-obj-calls": "off", + "no-redeclare": "off", + "no-setter-return": "off", + "no-this-before-super": "off", + "no-undef": "off", + "no-unreachable": "off", + "no-unsafe-negation": "off", + "no-var": "error", + "no-with": "off", + "prefer-const": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + }, + { + "curly": [ + "error", + "all", + ], + "prettier/prettier": [ + "error", + { + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "overrides": [ + { + "files": [ + "*.css", + "*.js", + "*.jsx", + "*.ts", + "*.tsx", + ], + "options": { + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "parenSpacing": true, + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "useTabs": true, + }, + }, + { + "files": [ + "*.blade.php", + ], + "options": { + "parser": "blade", + "printWidth": 120, + "sortTailwindcssClasses": true, + "tabWidth": 1, + }, + }, + ], + "parenSpacing": true, + "plugins": [ + "/node_modules/@shufo/prettier-plugin-blade/dist/index.cjs", + "/node_modules/prettier-plugin-tailwindcss/dist/index.mjs", + ], + "printWidth": 80, + "semi": true, + "singleQuote": true, + "tabWidth": 4, + "trailingComma": "es5", + "useTabs": true, + }, + ], + }, + { + "@typescript-eslint/method-signature-style": "error", + "@typescript-eslint/no-shadow": "error", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "ignoreRestSiblings": true, + }, + ], + "import/default": "off", + "import/named": "off", + "import/no-duplicates": "error", + "import/no-unresolved": "off", + "jsdoc/require-param-type": "off", + "jsdoc/require-returns-type": "off", + "no-duplicate-imports": "off", + "no-shadow": "off", + "no-unused-vars": "off", + }, + { + "@babel/object-curly-spacing": "off", + "@babel/semi": "off", + "@stylistic/array-bracket-newline": "off", + "@stylistic/array-bracket-spacing": "off", + "@stylistic/array-element-newline": "off", + "@stylistic/arrow-parens": "off", + "@stylistic/arrow-spacing": "off", + "@stylistic/block-spacing": "off", + "@stylistic/brace-style": "off", + "@stylistic/comma-dangle": "off", + "@stylistic/comma-spacing": "off", + "@stylistic/comma-style": "off", + "@stylistic/computed-property-spacing": "off", + "@stylistic/dot-location": "off", + "@stylistic/eol-last": "off", + "@stylistic/func-call-spacing": "off", + "@stylistic/function-call-argument-newline": "off", + "@stylistic/function-call-spacing": "off", + "@stylistic/function-paren-newline": "off", + "@stylistic/generator-star-spacing": "off", + "@stylistic/implicit-arrow-linebreak": "off", + "@stylistic/indent": "off", + "@stylistic/indent-binary-ops": "off", + "@stylistic/js/array-bracket-newline": "off", + "@stylistic/js/array-bracket-spacing": "off", + "@stylistic/js/array-element-newline": "off", + "@stylistic/js/arrow-parens": "off", + "@stylistic/js/arrow-spacing": "off", + "@stylistic/js/block-spacing": "off", + "@stylistic/js/brace-style": "off", + "@stylistic/js/comma-dangle": "off", + "@stylistic/js/comma-spacing": "off", + "@stylistic/js/comma-style": "off", + "@stylistic/js/computed-property-spacing": "off", + "@stylistic/js/dot-location": "off", + "@stylistic/js/eol-last": "off", + "@stylistic/js/func-call-spacing": "off", + "@stylistic/js/function-call-argument-newline": "off", + "@stylistic/js/function-call-spacing": "off", + "@stylistic/js/function-paren-newline": "off", + "@stylistic/js/generator-star-spacing": "off", + "@stylistic/js/implicit-arrow-linebreak": "off", + "@stylistic/js/indent": "off", + "@stylistic/js/jsx-quotes": "off", + "@stylistic/js/key-spacing": "off", + "@stylistic/js/keyword-spacing": "off", + "@stylistic/js/linebreak-style": "off", + "@stylistic/js/lines-around-comment": 0, + "@stylistic/js/max-len": 0, + "@stylistic/js/max-statements-per-line": "off", + "@stylistic/js/multiline-ternary": "off", + "@stylistic/js/new-parens": "off", + "@stylistic/js/newline-per-chained-call": "off", + "@stylistic/js/no-confusing-arrow": 0, + "@stylistic/js/no-extra-parens": "off", + "@stylistic/js/no-extra-semi": "off", + "@stylistic/js/no-floating-decimal": "off", + "@stylistic/js/no-mixed-operators": 0, + "@stylistic/js/no-mixed-spaces-and-tabs": "off", + "@stylistic/js/no-multi-spaces": "off", + "@stylistic/js/no-multiple-empty-lines": "off", + "@stylistic/js/no-tabs": 0, + "@stylistic/js/no-trailing-spaces": "off", + "@stylistic/js/no-whitespace-before-property": "off", + "@stylistic/js/nonblock-statement-body-position": "off", + "@stylistic/js/object-curly-newline": "off", + "@stylistic/js/object-curly-spacing": "off", + "@stylistic/js/object-property-newline": "off", + "@stylistic/js/one-var-declaration-per-line": "off", + "@stylistic/js/operator-linebreak": "off", + "@stylistic/js/padded-blocks": "off", + "@stylistic/js/quote-props": "off", + "@stylistic/js/quotes": 0, + "@stylistic/js/rest-spread-spacing": "off", + "@stylistic/js/semi": "off", + "@stylistic/js/semi-spacing": "off", + "@stylistic/js/semi-style": "off", + "@stylistic/js/space-before-blocks": "off", + "@stylistic/js/space-before-function-paren": "off", + "@stylistic/js/space-in-parens": "off", + "@stylistic/js/space-infix-ops": "off", + "@stylistic/js/space-unary-ops": "off", + "@stylistic/js/switch-colon-spacing": "off", + "@stylistic/js/template-curly-spacing": "off", + "@stylistic/js/template-tag-spacing": "off", + "@stylistic/js/wrap-iife": "off", + "@stylistic/js/wrap-regex": "off", + "@stylistic/js/yield-star-spacing": "off", + "@stylistic/jsx-child-element-spacing": "off", + "@stylistic/jsx-closing-bracket-location": "off", + "@stylistic/jsx-closing-tag-location": "off", + "@stylistic/jsx-curly-newline": "off", + "@stylistic/jsx-curly-spacing": "off", + "@stylistic/jsx-equals-spacing": "off", + "@stylistic/jsx-first-prop-new-line": "off", + "@stylistic/jsx-indent": "off", + "@stylistic/jsx-indent-props": "off", + "@stylistic/jsx-max-props-per-line": "off", + "@stylistic/jsx-newline": "off", + "@stylistic/jsx-one-expression-per-line": "off", + "@stylistic/jsx-props-no-multi-spaces": "off", + "@stylistic/jsx-quotes": "off", + "@stylistic/jsx-tag-spacing": "off", + "@stylistic/jsx-wrap-multilines": "off", + "@stylistic/jsx/jsx-child-element-spacing": "off", + "@stylistic/jsx/jsx-closing-bracket-location": "off", + "@stylistic/jsx/jsx-closing-tag-location": "off", + "@stylistic/jsx/jsx-curly-newline": "off", + "@stylistic/jsx/jsx-curly-spacing": "off", + "@stylistic/jsx/jsx-equals-spacing": "off", + "@stylistic/jsx/jsx-first-prop-new-line": "off", + "@stylistic/jsx/jsx-indent": "off", + "@stylistic/jsx/jsx-indent-props": "off", + "@stylistic/jsx/jsx-max-props-per-line": "off", + "@stylistic/key-spacing": "off", + "@stylistic/keyword-spacing": "off", + "@stylistic/linebreak-style": "off", + "@stylistic/lines-around-comment": 0, + "@stylistic/max-len": 0, + "@stylistic/max-statements-per-line": "off", + "@stylistic/member-delimiter-style": "off", + "@stylistic/multiline-ternary": "off", + "@stylistic/new-parens": "off", + "@stylistic/newline-per-chained-call": "off", + "@stylistic/no-confusing-arrow": 0, + "@stylistic/no-extra-parens": "off", + "@stylistic/no-extra-semi": "off", + "@stylistic/no-floating-decimal": "off", + "@stylistic/no-mixed-operators": 0, + "@stylistic/no-mixed-spaces-and-tabs": "off", + "@stylistic/no-multi-spaces": "off", + "@stylistic/no-multiple-empty-lines": "off", + "@stylistic/no-tabs": 0, + "@stylistic/no-trailing-spaces": "off", + "@stylistic/no-whitespace-before-property": "off", + "@stylistic/nonblock-statement-body-position": "off", + "@stylistic/object-curly-newline": "off", + "@stylistic/object-curly-spacing": "off", + "@stylistic/object-property-newline": "off", + "@stylistic/one-var-declaration-per-line": "off", + "@stylistic/operator-linebreak": "off", + "@stylistic/padded-blocks": "off", + "@stylistic/quote-props": "off", + "@stylistic/quotes": 0, + "@stylistic/rest-spread-spacing": "off", + "@stylistic/semi": "off", + "@stylistic/semi-spacing": "off", + "@stylistic/semi-style": "off", + "@stylistic/space-before-blocks": "off", + "@stylistic/space-before-function-paren": "off", + "@stylistic/space-in-parens": "off", + "@stylistic/space-infix-ops": "off", + "@stylistic/space-unary-ops": "off", + "@stylistic/switch-colon-spacing": "off", + "@stylistic/template-curly-spacing": "off", + "@stylistic/template-tag-spacing": "off", + "@stylistic/ts/block-spacing": "off", + "@stylistic/ts/brace-style": "off", + "@stylistic/ts/comma-dangle": "off", + "@stylistic/ts/comma-spacing": "off", + "@stylistic/ts/func-call-spacing": "off", + "@stylistic/ts/function-call-spacing": "off", + "@stylistic/ts/indent": "off", + "@stylistic/ts/key-spacing": "off", + "@stylistic/ts/keyword-spacing": "off", + "@stylistic/ts/lines-around-comment": 0, + "@stylistic/ts/member-delimiter-style": "off", + "@stylistic/ts/no-extra-parens": "off", + "@stylistic/ts/no-extra-semi": "off", + "@stylistic/ts/object-curly-spacing": "off", + "@stylistic/ts/quotes": 0, + "@stylistic/ts/semi": "off", + "@stylistic/ts/space-before-blocks": "off", + "@stylistic/ts/space-before-function-paren": "off", + "@stylistic/ts/space-infix-ops": "off", + "@stylistic/ts/type-annotation-spacing": "off", + "@stylistic/type-annotation-spacing": "off", + "@stylistic/type-generic-spacing": "off", + "@stylistic/type-named-tuple-spacing": "off", + "@stylistic/wrap-iife": "off", + "@stylistic/wrap-regex": "off", + "@stylistic/yield-star-spacing": "off", + "@typescript-eslint/block-spacing": "off", + "@typescript-eslint/brace-style": "off", + "@typescript-eslint/comma-dangle": "off", + "@typescript-eslint/comma-spacing": "off", + "@typescript-eslint/func-call-spacing": "off", + "@typescript-eslint/indent": "off", + "@typescript-eslint/key-spacing": "off", + "@typescript-eslint/keyword-spacing": "off", + "@typescript-eslint/lines-around-comment": 0, + "@typescript-eslint/member-delimiter-style": "off", + "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-extra-semi": "off", + "@typescript-eslint/object-curly-spacing": "off", + "@typescript-eslint/quotes": 0, + "@typescript-eslint/semi": "off", + "@typescript-eslint/space-before-blocks": "off", + "@typescript-eslint/space-before-function-paren": "off", + "@typescript-eslint/space-infix-ops": "off", + "@typescript-eslint/type-annotation-spacing": "off", + "array-bracket-newline": "off", + "array-bracket-spacing": "off", + "array-element-newline": "off", + "arrow-parens": "off", + "arrow-spacing": "off", + "babel/object-curly-spacing": "off", + "babel/quotes": 0, + "babel/semi": "off", + "block-spacing": "off", + "brace-style": "off", + "comma-dangle": "off", + "comma-spacing": "off", + "comma-style": "off", + "computed-property-spacing": "off", + "curly": 0, + "dot-location": "off", + "eol-last": "off", + "flowtype/boolean-style": "off", + "flowtype/delimiter-dangle": "off", + "flowtype/generic-spacing": "off", + "flowtype/object-type-curly-spacing": "off", + "flowtype/object-type-delimiter": "off", + "flowtype/quotes": "off", + "flowtype/semi": "off", + "flowtype/space-after-type-colon": "off", + "flowtype/space-before-generic-bracket": "off", + "flowtype/space-before-type-colon": "off", + "flowtype/union-intersection-spacing": "off", + "func-call-spacing": "off", + "function-call-argument-newline": "off", + "function-paren-newline": "off", + "generator-star": "off", + "generator-star-spacing": "off", + "implicit-arrow-linebreak": "off", + "indent": "off", + "indent-legacy": "off", + "jsx-quotes": "off", + "key-spacing": "off", + "keyword-spacing": "off", + "linebreak-style": "off", + "lines-around-comment": 0, + "max-len": 0, + "max-statements-per-line": "off", + "multiline-ternary": "off", + "new-parens": "off", + "newline-per-chained-call": "off", + "no-arrow-condition": "off", + "no-comma-dangle": "off", + "no-confusing-arrow": 0, + "no-extra-parens": "off", + "no-extra-semi": "off", + "no-floating-decimal": "off", + "no-mixed-operators": 0, + "no-mixed-spaces-and-tabs": "off", + "no-multi-spaces": "off", + "no-multiple-empty-lines": "off", + "no-reserved-keys": "off", + "no-space-before-semi": "off", + "no-spaced-func": "off", + "no-tabs": 0, + "no-trailing-spaces": "off", + "no-unexpected-multiline": 0, + "no-whitespace-before-property": "off", + "no-wrap-func": "off", + "nonblock-statement-body-position": "off", + "object-curly-newline": "off", + "object-curly-spacing": "off", + "object-property-newline": "off", + "one-var-declaration-per-line": "off", + "operator-linebreak": "off", + "padded-blocks": "off", + "quote-props": "off", + "quotes": 0, + "react/jsx-child-element-spacing": "off", + "react/jsx-closing-bracket-location": "off", + "react/jsx-closing-tag-location": "off", + "react/jsx-curly-newline": "off", + "react/jsx-curly-spacing": "off", + "react/jsx-equals-spacing": "off", + "react/jsx-first-prop-new-line": "off", + "react/jsx-indent": "off", + "react/jsx-indent-props": "off", + "react/jsx-max-props-per-line": "off", + "react/jsx-newline": "off", + "react/jsx-one-expression-per-line": "off", + "react/jsx-props-no-multi-spaces": "off", + "react/jsx-space-before-closing": "off", + "react/jsx-tag-spacing": "off", + "react/jsx-wrap-multilines": "off", + "rest-spread-spacing": "off", + "semi": "off", + "semi-spacing": "off", + "semi-style": "off", + "space-after-function-name": "off", + "space-after-keywords": "off", + "space-before-blocks": "off", + "space-before-function-paren": "off", + "space-before-function-parentheses": "off", + "space-before-keywords": "off", + "space-in-brackets": "off", + "space-in-parens": "off", + "space-infix-ops": "off", + "space-return-throw-case": "off", + "space-unary-ops": "off", + "space-unary-word-ops": "off", + "standard/array-bracket-even-spacing": "off", + "standard/computed-property-even-spacing": "off", + "standard/object-curly-even-spacing": "off", + "switch-colon-spacing": "off", + "template-curly-spacing": "off", + "template-tag-spacing": "off", + "unicorn/empty-brace-spaces": "off", + "unicorn/no-nested-ternary": "off", + "unicorn/number-literal-case": "off", + "unicorn/template-indent": 0, + "vue/array-bracket-newline": "off", + "vue/array-bracket-spacing": "off", + "vue/array-element-newline": "off", + "vue/arrow-spacing": "off", + "vue/block-spacing": "off", + "vue/block-tag-newline": "off", + "vue/brace-style": "off", + "vue/comma-dangle": "off", + "vue/comma-spacing": "off", + "vue/comma-style": "off", + "vue/dot-location": "off", + "vue/func-call-spacing": "off", + "vue/html-closing-bracket-newline": "off", + "vue/html-closing-bracket-spacing": "off", + "vue/html-end-tags": "off", + "vue/html-indent": "off", + "vue/html-quotes": "off", + "vue/html-self-closing": 0, + "vue/key-spacing": "off", + "vue/keyword-spacing": "off", + "vue/max-attributes-per-line": "off", + "vue/max-len": 0, + "vue/multiline-html-element-content-newline": "off", + "vue/multiline-ternary": "off", + "vue/mustache-interpolation-spacing": "off", + "vue/no-extra-parens": "off", + "vue/no-multi-spaces": "off", + "vue/no-spaces-around-equal-signs-in-attribute": "off", + "vue/object-curly-newline": "off", + "vue/object-curly-spacing": "off", + "vue/object-property-newline": "off", + "vue/operator-linebreak": "off", + "vue/quote-props": "off", + "vue/script-indent": "off", + "vue/singleline-html-element-content-newline": "off", + "vue/space-in-parens": "off", + "vue/space-infix-ops": "off", + "vue/space-unary-ops": "off", + "vue/template-curly-spacing": "off", + "wrap-iife": "off", + "wrap-regex": "off", + "yield-star-spacing": "off", + }, + { + "import/no-extraneous-dependencies": 0, + "import/no-unresolved": [ + "error", + { + "ignore": [ + "^@wordpress/", + ], + }, + ], + "jsdoc/require-param": 0, + "no-unused-expressions": [ + "error", + { + "allowTernary": true, + }, + ], + "prettier/prettier": 0, + }, +] +`; + +exports[`eslint config files patterns match snapshot 1`] = ` +[ + [ + "**/*.js", + "**/*.jsx", + ], +] +`; diff --git a/packages/eslint-config/tests/config.snapshot.test.js b/packages/eslint-config/tests/config.snapshot.test.js new file mode 100644 index 0000000..ea4f9e7 --- /dev/null +++ b/packages/eslint-config/tests/config.snapshot.test.js @@ -0,0 +1,58 @@ +'use strict'; + +const config = require( '../src/index.js' ); + +const normalizeNodeModulesPath = ( value ) => { + if ( typeof value !== 'string' ) { + return value; + } + + // Normalize absolute plugin/module paths so snapshots are stable across + // local machines and CI environments. + return value.replace( + /^.*[\\/]node_modules[\\/]/, + '/node_modules/' + ); +}; + +const sanitizeSnapshotValue = ( value ) => { + if ( Array.isArray( value ) ) { + return value.map( sanitizeSnapshotValue ); + } + + if ( value && typeof value === 'object' ) { + return Object.fromEntries( + Object.entries( value ).map( ( [ key, nested ] ) => [ + key, + sanitizeSnapshotValue( nested ), + ] ) + ); + } + + return normalizeNodeModulesPath( value ); +}; + +test( 'eslint config array length is stable', () => { + // If a plugin adds or removes config objects, this catches it immediately. + expect( Array.isArray( config ) ).toBe( true ); + // Snapshot the count β€” fails when @wordpress/eslint-plugin adds/removes config blocks. + expect( config.length ).toMatchSnapshot(); +} ); + +test( 'eslint config explicit rules match snapshot', () => { + // Snapshot only the rule maps (serializable). Functions like parsers/plugins + // are excluded here β€” their presence is verified in behavioral tests. + const ruleEntries = config + .filter( ( c ) => c.rules && Object.keys( c.rules ).length > 0 ) + .map( ( c ) => sanitizeSnapshotValue( c.rules ) ); + expect( ruleEntries ).toMatchSnapshot(); +} ); + +test( 'eslint config files patterns match snapshot', () => { + // compat.extends() blocks use function matchers (non-serializable) β€” filter to strings only. + const filePatterns = config + .filter( ( c ) => c.files ) + .map( ( c ) => c.files.filter( ( f ) => typeof f === 'string' ) ) + .filter( ( patterns ) => patterns.length > 0 ); + expect( filePatterns ).toMatchSnapshot(); +} ); diff --git a/packages/eslint-config/tests/rules.test.js b/packages/eslint-config/tests/rules.test.js new file mode 100644 index 0000000..eaf4477 --- /dev/null +++ b/packages/eslint-config/tests/rules.test.js @@ -0,0 +1,136 @@ +'use strict'; + +const { Linter } = require( 'eslint' ); +const config = require( '../src/index.js' ); + +const linter = new Linter( { configType: 'flat' } ); + +/** + * Lint a code string and return only messages for a specific rule. + * filename must match the config's files pattern (e.g. '**\/*.js'). + */ +// Use an absolute path within the package so FlatCompat-derived configs apply. +const TEST_FILE = require( 'path' ).join( __dirname, '..', 'test.js' ); + +function messagesForRule( code, ruleId, filename = TEST_FILE ) { + return linter + .verify( code, config, { filename } ) + .filter( ( m ) => m.ruleId === ruleId ); +} + +describe( 'explicitly configured rules', () => { + describe( 'no-unused-expressions', () => { + test( 'errors on unused logical AND expression', () => { + // Short-circuit `x && foo()` is an unused expression β€” not allowed. + const messages = messagesForRule( + 'var x = true; x && foo();', + 'no-unused-expressions' + ); + expect( messages.length ).toBeGreaterThan( 0 ); + } ); + + test( 'allows ternary expressions (allowTernary: true)', () => { + // `x ? a() : b()` is allowed because allowTernary is true. + const messages = messagesForRule( + 'var x = true; x ? foo() : bar();', + 'no-unused-expressions' + ); + expect( messages ).toHaveLength( 0 ); + } ); + } ); + + describe( 'import/no-unresolved', () => { + test( 'ignores @wordpress/* imports (configured ignore pattern)', () => { + // The config sets ignore: ['^@wordpress/'] β€” these must not error. + const messages = messagesForRule( + `import { useSelect } from '@wordpress/data';`, + 'import/no-unresolved' + ); + expect( messages ).toHaveLength( 0 ); + } ); + + test( 'fires on unresolvable non-@wordpress imports (rule is active)', () => { + // Proves the rule is enforcing β€” not vacuously passing because the plugin is unloaded. + const messages = messagesForRule( + `import foo from 'definitely-not-installed-xyz-pkg';`, + 'import/no-unresolved' + ); + expect( messages.length ).toBeGreaterThan( 0 ); + } ); + } ); + + describe( 'disabled rules', () => { + test( 'prettier/prettier is disabled (severity 0)', () => { + // Must not fire regardless of formatting. + const messages = messagesForRule( + `var x="ugly"`, + 'prettier/prettier' + ); + expect( messages ).toHaveLength( 0 ); + } ); + + test( 'import/no-extraneous-dependencies is disabled', () => { + const messages = messagesForRule( + `import foo from 'some-unlisted-package';`, + 'import/no-extraneous-dependencies' + ); + expect( messages ).toHaveLength( 0 ); + } ); + + test( 'jsdoc/require-param is disabled', () => { + // A function with an undocumented param must not trigger jsdoc errors. + const messages = messagesForRule( + `/** @returns {void} */ function foo(undocumented) {}`, + 'jsdoc/require-param' + ); + expect( messages ).toHaveLength( 0 ); + } ); + } ); +} ); + +describe( 'curated inherited rules', () => { + test( 'no-unused-vars errors on declared-but-unused variable', () => { + const messages = messagesForRule( + 'const unused = 1;', + 'no-unused-vars' + ); + expect( messages.length ).toBeGreaterThan( 0 ); + } ); + + test( 'no-console errors on console.log call', () => { + const messages = messagesForRule( + `console.log('hello');`, + 'no-console' + ); + expect( messages.length ).toBeGreaterThan( 0 ); + } ); +} ); + +describe( '@wordpress/eslint-plugin/recommended is loaded', () => { + test( '@wordpress/no-unsafe-wp-apis flags __experimental imports', () => { + // This rule only exists if the WordPress plugin is loaded. + // Import of an __experimental export must produce an error. + const messages = messagesForRule( + `import { __experimentalFoo } from '@wordpress/components';`, + '@wordpress/no-unsafe-wp-apis' + ); + expect( messages.length ).toBeGreaterThan( 0 ); + } ); + + test( '@wordpress/no-unsafe-wp-apis flags __unstable imports', () => { + const messages = messagesForRule( + `import { __unstableBar } from '@wordpress/block-editor';`, + '@wordpress/no-unsafe-wp-apis' + ); + expect( messages.length ).toBeGreaterThan( 0 ); + } ); + + test( '@wordpress/no-unsafe-wp-apis allows stable imports', () => { + // A stable export from a @wordpress package must not be flagged. + const messages = messagesForRule( + `import { useSelect } from '@wordpress/data';`, + '@wordpress/no-unsafe-wp-apis' + ); + expect( messages ).toHaveLength( 0 ); + } ); +} ); diff --git a/packages/eslint-config/vitest.config.mjs b/packages/eslint-config/vitest.config.mjs new file mode 100644 index 0000000..770920c --- /dev/null +++ b/packages/eslint-config/vitest.config.mjs @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['tests/**/*.test.js'], + }, +}); diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index e8bc4c1..7604d7b 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -5,7 +5,7 @@ "main": "src/index.js", "type": "commonjs", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "vitest run" }, "publishConfig": { "registry": "https://npm.pkg.github.com/" @@ -23,5 +23,8 @@ "@wordpress/prettier-config": "^4.48.0", "prettier": "npm:wp-prettier@^3.0.3", "prettier-plugin-tailwindcss": "^0.7.4" + }, + "devDependencies": { + "vitest": "^3.2.6" } } diff --git a/packages/prettier-config/tests/__snapshots__/config.snapshot.test.js.snap b/packages/prettier-config/tests/__snapshots__/config.snapshot.test.js.snap new file mode 100644 index 0000000..52ebf3a --- /dev/null +++ b/packages/prettier-config/tests/__snapshots__/config.snapshot.test.js.snap @@ -0,0 +1,49 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`prettier config options match snapshot (excludes machine-specific plugin paths) 1`] = ` +{ + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "overrides": [ + { + "files": [ + "*.css", + "*.js", + "*.jsx", + "*.ts", + "*.tsx", + ], + "options": { + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "parenSpacing": true, + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "useTabs": true, + }, + }, + { + "files": [ + "*.blade.php", + ], + "options": { + "parser": "blade", + "printWidth": 120, + "sortTailwindcssClasses": true, + "tabWidth": 1, + }, + }, + ], + "parenSpacing": true, + "printWidth": 80, + "semi": true, + "singleQuote": true, + "tabWidth": 4, + "trailingComma": "es5", + "useTabs": true, +} +`; diff --git a/packages/prettier-config/tests/__snapshots__/format.test.js.snap b/packages/prettier-config/tests/__snapshots__/format.test.js.snap new file mode 100644 index 0000000..46d1c59 --- /dev/null +++ b/packages/prettier-config/tests/__snapshots__/format.test.js.snap @@ -0,0 +1,12 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`blade override options > blade formatted output matches snapshot 1`] = ` +"@if ($show) +
+ @foreach ($items as $item) + {{ $item }} + @endforeach +
+@endif +" +`; diff --git a/packages/prettier-config/tests/config.snapshot.test.js b/packages/prettier-config/tests/config.snapshot.test.js new file mode 100644 index 0000000..b174639 --- /dev/null +++ b/packages/prettier-config/tests/config.snapshot.test.js @@ -0,0 +1,29 @@ +'use strict'; + +const config = require( '../src/index.js' ); + +test( 'prettier config options match snapshot (excludes machine-specific plugin paths)', () => { + // Omit plugins: they contain absolute paths that differ per machine. + const { plugins, ...options } = config; + expect( options ).toMatchSnapshot(); +} ); + +test( 'blade plugin is configured', () => { + expect( + config.plugins.some( ( p ) => p.includes( 'prettier-plugin-blade' ) ) + ).toBe( true ); +} ); + +test( 'tailwindcss plugin is configured', () => { + expect( + config.plugins.some( ( p ) => + p.includes( 'prettier-plugin-tailwindcss' ) + ) + ).toBe( true ); +} ); + +test( 'tailwindStylesheet is not present in test environment', () => { + // Confirms findTailwindStylesheet() returns null outside a real project. + // If this fails, snapshot tests may become non-deterministic. + expect( config.tailwindStylesheet ).toBeUndefined(); +} ); diff --git a/packages/prettier-config/tests/format.test.js b/packages/prettier-config/tests/format.test.js new file mode 100644 index 0000000..73231aa --- /dev/null +++ b/packages/prettier-config/tests/format.test.js @@ -0,0 +1,125 @@ +'use strict'; + +const prettier = require( 'prettier' ); +const path = require( 'path' ); + +// Resolve config for a given filename β€” applies the correct override options. +const CONFIG_PATH = path.resolve( __dirname, '../src/index.js' ); + +async function resolveOptions( filename ) { + return prettier.resolveConfig( path.join( __dirname, filename ), { + config: CONFIG_PATH, + } ); +} + +describe( 'wp-prettier fork verification', () => { + test( 'parenSpacing adds spaces inside function call parentheses', async () => { + // CRITICAL: parenSpacing is a wp-prettier–only option. + // Standard prettier silently ignores it β€” foo(bar) stays foo(bar). + // If this test fails, the wrong prettier fork is installed. + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( 'foo(bar, baz)', { + ...options, + parser: 'babel', + } ); + expect( output.trim() ).toBe( 'foo( bar, baz );' ); + } ); + + test( 'parenSpacing adds spaces in nested calls', async () => { + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( 'outer(inner(x))', { + ...options, + parser: 'babel', + } ); + expect( output.trim() ).toBe( 'outer( inner( x ) );' ); + } ); +} ); + +describe( 'JS override options', () => { + test( 'uses tabs for indentation', async () => { + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( + `function foo() {\nreturn "hello"\n}`, + { ...options, parser: 'babel' } + ); + // Indented line must start with a tab, not spaces. + expect( output ).toMatch( /\n\t/ ); + } ); + + test( 'converts double quotes to single quotes', async () => { + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( `const x = "hello";`, { + ...options, + parser: 'babel', + } ); + expect( output ).toContain( "'hello'" ); + expect( output ).not.toContain( '"hello"' ); + } ); + + test( 'adds trailing commas in objects (es5)', async () => { + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( + `const obj = {\n a: 1,\n b: 2\n};`, + { ...options, parser: 'babel' } + ); + // Last property must have a trailing comma before closing brace. + expect( output ).toMatch( /b: 2,\n/ ); + } ); + + test( 'adds semicolons', async () => { + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( `const x = 1`, { + ...options, + parser: 'babel', + } ); + expect( output.trim() ).toMatch( /;$/ ); + } ); + + test( 'always wraps arrow function params in parens (arrowParens: always)', async () => { + const options = await resolveOptions( 'test.js' ); + const output = await prettier.format( `const fn = x => x;`, { + ...options, + parser: 'babel', + } ); + // parenSpacing (wp-prettier) adds spaces inside the parens: ( x ) => + expect( output ).toMatch( /\( x \) =>/ ); + // But the param must still be wrapped in parens (arrowParens: always), not bare: x => + expect( output ).not.toMatch( /\bx =>/ ); + expect( output ).not.toMatch( /x =>/ ); + expect( output ).toMatch( /=>/ ); // sanity: it's still an arrow function + } ); +} ); + +describe( 'blade override options', () => { + test( 'reorders tailwind classes (sortTailwindcssClasses: true)', async () => { + const options = await resolveOptions( 'test.blade.php' ); + // Classes in an unsorted order β€” the sorter must reorder them. + // @shufo/tailwindcss-class-sorter uses Tailwind's utility order, not alphabetical. + // We assert the output differs from input rather than hardcoding the exact order. + const input = `
content
\n`; + const output = await prettier.format( input, { + ...options, + parser: 'blade', + } ); + // Sorted output must differ from original class order. + expect( output ).not.toContain( 'text-sm bg-white mt-4 z-10 p-2' ); + } ); + + test( 'blade formatted output matches snapshot', async () => { + const options = await resolveOptions( 'test.blade.php' ); + const input = [ + '@if($show)', + '
', + '@foreach($items as $item)', + '{{ $item }}', + '@endforeach', + '
', + '@endif', + ].join( '\n' ); + const output = await prettier.format( input, { + ...options, + parser: 'blade', + } ); + expect( output ).toMatchSnapshot(); + } ); +} ); diff --git a/packages/prettier-config/vitest.config.mjs b/packages/prettier-config/vitest.config.mjs new file mode 100644 index 0000000..5a85bad --- /dev/null +++ b/packages/prettier-config/vitest.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['tests/**/*.test.js'], + testTimeout: 15000, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b5fd8b..ab27935 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,15 @@ importers: .: devDependencies: + '@babel/core': + specifier: ^7.29.7 + version: 7.29.7 + '@babel/eslint-parser': + specifier: ^7.25.7 + version: 7.25.7(@babel/core@7.29.7)(eslint@9.39.4(jiti@2.7.0)) + '@yardinternet/toolkit': + specifier: workspace:* + version: link:packages/toolkit husky: specifier: ^9.1.7 version: 9.1.7 @@ -20,9 +29,15 @@ importers: syncpack: specifier: ^14.0.0 version: 14.3.1 + vitest: + specifier: ^3.2.6 + version: 3.2.6(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) packages/eslint-config: dependencies: + '@babel/eslint-parser': + specifier: ^7.25.7 + version: 7.25.7(@babel/core@7.29.7)(eslint@9.39.4(jiti@2.7.0)) '@babel/preset-react': specifier: ^7.29.7 version: 7.29.7(@babel/core@7.29.7) @@ -56,6 +71,13 @@ importers: globals: specifier: ^17.6.0 version: 17.6.0 + devDependencies: + eslint: + specifier: ^9.39.4 + version: 9.39.4(jiti@2.7.0) + vitest: + specifier: ^3.2.6 + version: 3.2.6(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) packages/postcss-config: dependencies: @@ -98,6 +120,10 @@ importers: prettier-plugin-tailwindcss: specifier: ^0.7.4 version: 0.7.4(wp-prettier@3.0.3) + devDependencies: + vitest: + specifier: ^3.2.6 + version: 3.2.6(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) packages/stylelint-config: dependencies: @@ -182,6 +208,19 @@ importers: stylelint-config-recommended: specifier: ^18.0.0 version: 18.0.0(stylelint@17.13.0(typescript@5.9.3)) + optionalDependencies: + '@yardinternet/eslint-config': + specifier: ^1.2.10 + version: 1.2.10(@babel/core@7.29.7)(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(wp-prettier@3.0.3) + '@yardinternet/prettier-config': + specifier: ^2.0.10 + version: 2.0.10(yaml@2.9.0) + '@yardinternet/stylelint-config': + specifier: ^1.1.8 + version: 1.1.8(typescript@5.9.3) + '@yardinternet/vite-config': + specifier: ^1.3.3 + version: 1.3.3(@types/node@25.9.2)(eslint@9.39.4(jiti@2.7.0))(meow@14.1.0)(optionator@0.9.4)(postcss@8.5.15)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) packages/ts-config: {} @@ -246,7 +285,7 @@ importers: version: 7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) vite-plugin-checker: specifier: ^0.12.0 - version: 0.12.0(eslint@9.39.4(jiti@2.7.0))(optionator@0.9.4)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + version: 0.12.0(eslint@9.39.4(jiti@2.7.0))(meow@14.1.0)(optionator@0.9.4)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) vite-plugin-dts: specifier: ^4.5.4 version: 4.5.4(@types/node@25.9.2)(rollup@4.61.1)(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) @@ -2762,6 +2801,12 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} @@ -3105,6 +3150,35 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + '@vitest/expect@3.2.6': + resolution: {integrity: sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==} + + '@vitest/mocker@3.2.6': + resolution: {integrity: sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.6': + resolution: {integrity: sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==} + + '@vitest/runner@3.2.6': + resolution: {integrity: sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==} + + '@vitest/snapshot@3.2.6': + resolution: {integrity: sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==} + + '@vitest/spy@3.2.6': + resolution: {integrity: sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==} + + '@vitest/utils@3.2.6': + resolution: {integrity: sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==} + '@volar/language-core@2.4.28': resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} @@ -3717,6 +3791,20 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + '@yardinternet/eslint-config@1.2.10': + resolution: {integrity: sha512-Ug/qbtd3rdCe2nvsl2fN90WdhEfFkWAFvrNkMGP21nCxCNfgEBIMtibm6KYRH6ObRbhQMQA1/6GmUz67Gi7SOQ==, tarball: https://npm.pkg.github.com/download/@yardinternet/eslint-config/1.2.10/64ead03dfa86a58fbcff1cc947ba5f2c3e20ce89} + + '@yardinternet/prettier-config@2.0.10': + resolution: {integrity: sha512-maMOheaifZHQOq4KBLy/WZMdDX5+PqyypEXg4FRXNOkqOsX/KdRI1rsVurnk1QFkX4GWGeEZbp1mGaF0Uat5MA==, tarball: https://npm.pkg.github.com/download/@yardinternet/prettier-config/2.0.10/080b28a72b61726d5bc9e09d94e8d5649693e78b} + + '@yardinternet/stylelint-config@1.1.8': + resolution: {integrity: sha512-7H0HyoXRIqNXl6HD+DJGJsySH6AtM81fT+0wW9Z8T8Y56X/cDmzzTkx68iW3achnkWPlO0uzJE/5nUZGcGuXKg==, tarball: https://npm.pkg.github.com/download/@yardinternet/stylelint-config/1.1.8/17ed13dda4c80a9319925232547784b6baa6ce8d} + + '@yardinternet/vite-config@1.3.3': + resolution: {integrity: sha512-pXr8c9P82AnRi5VPOOBck4xdq1pCgADtiX2vPUe3hzzK6XAn+I4YMWj3WO3v1pThJKQ8iWX6lAEF0VfmcnK/Dw==, tarball: https://npm.pkg.github.com/download/@yardinternet/vite-config/1.3.3/c848f6736246566801efaa4a307080ea7ad09e33} + peerDependencies: + vite: ^7.1.2 + '@yardinternet/vite-plugin-gutenberg-blocks@2.6.1': resolution: {integrity: sha512-pMqK65qzVHd8w1wejDPaYC+wZEoc1JYAQX+VF1EV/dqHWWwKwZFZyqTDgzULyo92vSxIVb7BQXrjojkm+J1WKw==, tarball: https://npm.pkg.github.com/download/@yardinternet/vite-plugin-gutenberg-blocks/2.6.1/ae4552d3e7a9fe68c0cac9b4336dcfa5db6d8a3d} engines: {node: ^18.0.0 || ^20.0.0 || ^22.0.0 || ^24.0.0 || ^25.0.0} @@ -3946,6 +4034,10 @@ packages: asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} @@ -4080,6 +4172,10 @@ packages: resolution: {integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==} engines: {node: '>=12.17'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + cacache@20.0.4: resolution: {integrity: sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==} engines: {node: ^20.17.0 || >=22.9.0} @@ -4134,6 +4230,10 @@ packages: capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + chalk@4.1.0: resolution: {integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==} engines: {node: '>=10'} @@ -4152,6 +4252,10 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -4573,6 +4677,10 @@ packages: babel-plugin-macros: optional: true + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -4792,6 +4900,9 @@ packages: es-module-lexer@0.4.1: resolution: {integrity: sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} @@ -5037,6 +5148,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -5063,6 +5177,10 @@ packages: resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==} engines: {node: '>=10'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} @@ -5902,6 +6020,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -6211,6 +6332,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -6895,6 +7019,10 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + php-parser@3.5.0: resolution: {integrity: sha512-EHdzSckQNP86jQRCEsMYhs+YzS4BfvfxnyhvzHVhVRoRUGEMFi8f3xKfuS9xdChBazZSyvb10SZbqhYQLGBcQg==} @@ -7783,6 +7911,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -7894,6 +8025,9 @@ packages: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} @@ -7909,6 +8043,9 @@ packages: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -8002,6 +8139,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + stylehacks@7.0.11: resolution: {integrity: sha512-iODNfhXVLqc5LADs+Y6Oh5wJuK5ZcHbVng8aiK3y9pjMQdc5hLrBW0eFU6FtnpNrE6PoEg/MmFTU4waotj5WNg==} engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} @@ -8225,6 +8365,12 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.2.4: resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} @@ -8237,6 +8383,18 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + tmp@0.2.6: resolution: {integrity: sha512-5sJPdPjfI5Kx+qbrDesxkglRBxW//g7hCsqspEjwkewGvBMGIKMOTKzLt1hFVJzyadba3lDUN20O9qhvbQUSTA==} engines: {node: '>=14.14'} @@ -8492,6 +8650,11 @@ packages: resolution: {integrity: sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==} engines: {node: ^18.17.0 || >=20.5.0} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + vite-plugin-checker@0.12.0: resolution: {integrity: sha512-CmdZdDOGss7kdQwv73UyVgLPv0FVYe5czAgnmRX2oKljgEvSrODGuClaV3PDR2+3ou7N/OKGauDDBjy2MB07Rg==} engines: {node: '>=16.11'} @@ -8593,6 +8756,34 @@ packages: yaml: optional: true + vitest@3.2.6: + resolution: {integrity: sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.6 + '@vitest/ui': 3.2.6 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vlq@1.0.1: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} @@ -8678,6 +8869,11 @@ packages: engines: {node: ^20.17.0 || >=22.9.0} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -10550,11 +10746,11 @@ snapshots: '@npmcli/fs@4.0.0': dependencies: - semver: 7.7.2 + semver: 7.8.2 '@npmcli/fs@5.0.0': dependencies: - semver: 7.7.2 + semver: 7.8.2 '@npmcli/git@6.0.3': dependencies: @@ -10564,7 +10760,7 @@ snapshots: npm-pick-manifest: 10.0.0 proc-log: 5.0.0 promise-retry: 2.0.1 - semver: 7.7.2 + semver: 7.8.2 which: 5.0.0 '@npmcli/git@7.0.2': @@ -10575,7 +10771,7 @@ snapshots: lru-cache: 11.5.1 npm-pick-manifest: 11.0.3 proc-log: 6.1.0 - semver: 7.7.2 + semver: 7.8.2 which: 6.0.1 '@npmcli/installed-package-contents@3.0.0': @@ -10601,7 +10797,7 @@ snapshots: json-parse-even-better-errors: 5.0.0 pacote: 21.5.0 proc-log: 6.1.0 - semver: 7.7.2 + semver: 7.8.2 transitivePeerDependencies: - supports-color @@ -11418,6 +11614,13 @@ snapshots: dependencies: '@babel/types': 7.29.7 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.9': {} '@types/gradient-parser@0.1.3': {} @@ -11791,6 +11994,48 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/expect@3.2.6': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.6 + '@vitest/utils': 3.2.6 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.6(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 3.2.6 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + + '@vitest/pretty-format@3.2.6': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.6': + dependencies: + '@vitest/utils': 3.2.6 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.6': + dependencies: + '@vitest/pretty-format': 3.2.6 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@3.2.6': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.6': + dependencies: + '@vitest/pretty-format': 3.2.6 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + '@volar/language-core@2.4.28': dependencies: '@volar/source-map': 2.4.28 @@ -13324,6 +13569,107 @@ snapshots: '@xtuc/long@4.2.2': {} + '@yardinternet/eslint-config@1.2.10(@babel/core@7.29.7)(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(wp-prettier@3.0.3)': + dependencies: + '@babel/preset-react': 7.29.7(@babel/core@7.29.7) + '@eslint/compat': 2.1.0(eslint@9.39.4(jiti@2.7.0)) + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@typescript-eslint/eslint-plugin': 8.60.1(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@wordpress/eslint-plugin': 24.5.0(@babel/core@7.29.7)(eslint@9.39.4(jiti@2.7.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(wp-prettier@3.0.3) + eslint-config-prettier: 10.1.8(eslint@9.39.4(jiti@2.7.0)) + eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.32.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.5)(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-react-hooks: 7.1.1(eslint@9.39.4(jiti@2.7.0)) + globals: 17.6.0 + transitivePeerDependencies: + - '@babel/core' + - '@types/eslint' + - '@typescript-eslint/parser' + - eslint + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - jest + - prettier + - react + - react-dom + - stylelint + - supports-color + - typescript + optional: true + + '@yardinternet/prettier-config@2.0.10(yaml@2.9.0)': + dependencies: + '@shufo/prettier-plugin-blade': 1.16.2(yaml@2.9.0) + '@shufo/tailwindcss-class-sorter': 3.0.1(yaml@2.9.0) + '@wordpress/prettier-config': 4.48.0(wp-prettier@3.0.3) + prettier: wp-prettier@3.0.3 + prettier-plugin-tailwindcss: 0.7.4(wp-prettier@3.0.3) + transitivePeerDependencies: + - '@ianvs/prettier-plugin-sort-imports' + - '@prettier/plugin-hermes' + - '@prettier/plugin-oxc' + - '@prettier/plugin-pug' + - '@shopify/prettier-plugin-liquid' + - '@trivago/prettier-plugin-sort-imports' + - '@zackad/prettier-plugin-twig' + - prettier-plugin-astro + - prettier-plugin-css-order + - prettier-plugin-jsdoc + - prettier-plugin-marko + - prettier-plugin-multiline-arrays + - prettier-plugin-organize-attributes + - prettier-plugin-organize-imports + - prettier-plugin-sort-imports + - prettier-plugin-svelte + - tsx + - yaml + optional: true + + '@yardinternet/stylelint-config@1.1.8(typescript@5.9.3)': + dependencies: + stylelint: 17.13.0(typescript@5.9.3) + stylelint-config-idiomatic-order: 10.0.0(stylelint@17.13.0(typescript@5.9.3)) + stylelint-config-recommended: 18.0.0(stylelint@17.13.0(typescript@5.9.3)) + transitivePeerDependencies: + - supports-color + - typescript + optional: true + + '@yardinternet/vite-config@1.3.3(@types/node@25.9.2)(eslint@9.39.4(jiti@2.7.0))(meow@14.1.0)(optionator@0.9.4)(postcss@8.5.15)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0))': + dependencies: + '@roots/vite-plugin': 1.3.1(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(lightningcss@1.32.0)(postcss@8.5.15)) + '@tailwindcss/vite': 4.3.0(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + '@vitejs/plugin-react': 5.2.0(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + '@yardinternet/vite-plugin-gutenberg-blocks': 2.6.1(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + chalk: 5.6.2 + laravel-vite-plugin: 2.1.0(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + postcss-prefixwrap: 1.58.0(postcss@8.5.15) + vite: 7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + vite-plugin-checker: 0.12.0(eslint@9.39.4(jiti@2.7.0))(meow@14.1.0)(optionator@0.9.4)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + vite-plugin-dts: 4.5.4(@types/node@25.9.2)(rollup@4.61.1)(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + vite-plugin-externals: 0.6.2(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + optionalDependencies: + '@rollup/rollup-linux-x64-gnu': 4.61.1 + transitivePeerDependencies: + - '@biomejs/biome' + - '@types/node' + - eslint + - meow + - optionator + - oxlint + - postcss + - rollup + - stylelint + - supports-color + - typescript + - vls + - vti + - vue-tsc + - webpack + optional: true + '@yardinternet/vite-plugin-gutenberg-blocks@2.6.1(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0))': dependencies: chalk: 5.6.2 @@ -13552,6 +13898,8 @@ snapshots: asap@2.0.6: {} + assertion-error@2.0.1: {} + ast-types-flow@0.0.8: {} astral-regex@2.0.0: {} @@ -13716,6 +14064,8 @@ snapshots: byte-size@8.1.1: {} + cac@6.7.14: {} + cacache@20.0.4: dependencies: '@npmcli/fs': 5.0.0 @@ -13790,6 +14140,14 @@ snapshots: tslib: 2.8.1 upper-case-first: 2.0.2 + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + chalk@4.1.0: dependencies: ansi-styles: 4.3.0 @@ -13819,6 +14177,8 @@ snapshots: chardet@2.1.1: {} + check-error@2.1.3: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -14054,7 +14414,7 @@ snapshots: handlebars: 4.7.9 json-stringify-safe: 5.0.1 meow: 8.1.2 - semver: 7.7.2 + semver: 7.8.2 split: 1.0.1 conventional-commits-filter@3.0.0: @@ -14268,6 +14628,8 @@ snapshots: optionalDependencies: babel-plugin-macros: 3.1.0 + deep-eql@5.0.2: {} + deep-is@0.1.4: {} deepmerge@4.3.1: {} @@ -14520,6 +14882,8 @@ snapshots: es-module-lexer@0.4.1: {} + es-module-lexer@1.7.0: {} + es-module-lexer@2.1.0: {} es-object-atoms@1.1.1: @@ -14889,6 +15253,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + esutils@2.0.3: {} etag@1.8.1: {} @@ -14913,6 +15281,8 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + expect-type@1.3.0: {} + exponential-backoff@3.1.3: {} exsolve@1.0.8: {} @@ -15153,7 +15523,7 @@ snapshots: git-semver-tags@5.0.1: dependencies: meow: 8.1.2 - semver: 7.7.2 + semver: 7.8.2 git-up@7.0.0: dependencies: @@ -15739,6 +16109,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -16092,6 +16464,8 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.2.1: {} + lower-case@2.0.2: dependencies: tslib: 2.8.1 @@ -16539,7 +16913,7 @@ snapshots: graceful-fs: 4.2.11 nopt: 9.0.0 proc-log: 6.1.0 - semver: 7.7.2 + semver: 7.8.2 tar: 7.5.11 tinyglobby: 0.2.12 undici: 6.26.0 @@ -16572,7 +16946,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.2 - semver: 7.7.2 + semver: 7.8.2 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -16589,11 +16963,11 @@ snapshots: npm-install-checks@7.1.2: dependencies: - semver: 7.7.2 + semver: 7.8.2 npm-install-checks@8.0.0: dependencies: - semver: 7.7.2 + semver: 7.8.2 npm-normalize-package-bin@4.0.0: {} @@ -16603,7 +16977,7 @@ snapshots: dependencies: hosted-git-info: 8.1.0 proc-log: 5.0.0 - semver: 7.7.2 + semver: 7.8.2 validate-npm-package-name: 6.0.2 npm-package-arg@13.0.1: @@ -16623,14 +16997,14 @@ snapshots: npm-install-checks: 7.1.2 npm-normalize-package-bin: 4.0.0 npm-package-arg: 12.0.2 - semver: 7.7.2 + semver: 7.8.2 npm-pick-manifest@11.0.3: dependencies: npm-install-checks: 8.0.0 npm-normalize-package-bin: 5.0.0 npm-package-arg: 13.0.1 - semver: 7.7.2 + semver: 7.8.2 npm-registry-fetch@19.1.0: dependencies: @@ -17084,6 +17458,8 @@ snapshots: pathe@2.0.3: {} + pathval@2.0.1: {} + php-parser@3.5.0: {} picocolors@1.1.1: {} @@ -17962,6 +18338,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -18075,6 +18453,8 @@ snapshots: stable-hash-x@0.2.0: {} + stackback@0.0.2: {} + stackframe@1.3.4: {} stacktrace-parser@0.1.11: @@ -18085,6 +18465,8 @@ snapshots: statuses@2.0.2: {} + std-env@3.10.0: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -18206,6 +18588,10 @@ snapshots: strip-json-comments@3.1.1: {} + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + stylehacks@7.0.11(postcss@8.5.15): dependencies: browserslist: 4.28.2 @@ -18455,6 +18841,10 @@ snapshots: tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + tinyexec@1.2.4: {} tinyglobby@0.2.12: @@ -18467,6 +18857,12 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.4: {} + tmp@0.2.6: {} tmpl@1.0.5: {} @@ -18710,7 +19106,49 @@ snapshots: validate-npm-package-name@6.0.2: {} - vite-plugin-checker@0.12.0(eslint@9.39.4(jiti@2.7.0))(optionator@0.9.4)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)): + vite-node@3.2.4(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.3.5(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite-node@3.2.4(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite-plugin-checker@0.12.0(eslint@9.39.4(jiti@2.7.0))(meow@14.1.0)(optionator@0.9.4)(stylelint@17.13.0(typescript@5.9.3))(typescript@5.9.3)(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)): dependencies: '@babel/code-frame': 7.29.7 chokidar: 4.0.3 @@ -18723,6 +19161,7 @@ snapshots: vscode-uri: 3.1.0 optionalDependencies: eslint: 9.39.4(jiti@2.7.0) + meow: 14.1.0 optionator: 0.9.4 stylelint: 17.13.0(typescript@5.9.3) typescript: 5.9.3 @@ -18767,6 +19206,24 @@ snapshots: tinyglobby: 0.2.17 vite: 7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + vite@7.3.5(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0): + dependencies: + esbuild: 0.27.7 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.15 + rollup: 4.61.1 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.9.2 + fsevents: 2.3.3 + jiti: 1.21.7 + lightningcss: 1.32.0 + sass: 1.100.0 + sugarss: 5.0.1(postcss@8.5.15) + terser: 5.48.0 + yaml: 2.9.0 + vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0): dependencies: esbuild: 0.27.7 @@ -18785,6 +19242,88 @@ snapshots: terser: 5.48.0 yaml: 2.9.0 + vitest@3.2.6(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.6 + '@vitest/mocker': 3.2.6(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + '@vitest/pretty-format': 3.2.6 + '@vitest/runner': 3.2.6 + '@vitest/snapshot': 3.2.6 + '@vitest/spy': 3.2.6 + '@vitest/utils': 3.2.6 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.17 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.3.5(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + vite-node: 3.2.4(@types/node@25.9.2)(jiti@1.21.7)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.9.2 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vitest@3.2.6(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.6 + '@vitest/mocker': 3.2.6(vite@7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0)) + '@vitest/pretty-format': 3.2.6 + '@vitest/runner': 3.2.6 + '@vitest/snapshot': 3.2.6 + '@vitest/spy': 3.2.6 + '@vitest/utils': 3.2.6 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.17 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.3.5(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + vite-node: 3.2.4(@types/node@25.9.2)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.100.0)(sugarss@5.0.1(postcss@8.5.15))(terser@5.48.0)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.9.2 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vlq@1.0.1: {} vscode-oniguruma@1.7.0: {} @@ -18912,6 +19451,11 @@ snapshots: dependencies: isexe: 4.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wide-align@1.1.5: dependencies: string-width: 4.2.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 18ec407..b85884c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,12 @@ packages: - 'packages/*' + +publicHoistPattern: + - prettier + - stylelint + - eslint + - eslint-* + - eslint-plugin-* + - '@eslint/*' + - '@typescript-eslint/*' + - '@wordpress/eslint-plugin' diff --git a/vitest.config.mjs b/vitest.config.mjs new file mode 100644 index 0000000..6c182ed --- /dev/null +++ b/vitest.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig( { + test: { + projects: [ + 'packages/eslint-config/vitest.config.mjs', + 'packages/prettier-config/vitest.config.mjs', + ], + }, +} );