@dr-ishaan/rehype-perfect-code-blocks 1.3.2 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.3] — 2026-06-20
9
+
10
+ ### Summary
11
+
12
+ Patch release fixing CSS conflicts between the plugin and Tailwind CSS Preflight (and similar framework base resets). The plugin's `:where()` zero-specificity design — normally a feature — meant Tailwind's bare-element resets (`pre { overflow-x: auto }`, `code { font-family: ui-monospace }`, `button { background: transparent }`, `* { border-width: 0 }`) overrode the plugin's critical rules. This caused double scrollbars, wrong mono font, stripped copy-button styling, and long lines wrapping instead of scrolling. The fix adds a small block of "framework-reset overrides" with real specificity that beat framework base resets without `!important`.
13
+
14
+ ### Bug fixes
15
+
16
+ - **Tailwind Preflight / daisyUI CSS conflict** — Added a block of "framework-reset overrides" in `src/styles.css` with REAL specificity (`.pcb pre` = (0,1,1), `.pcb__copy` = (0,1,0), `.pcb__bar` = (0,1,0), `.pcb__code` = (0,1,0)) that beat framework base resets targeting bare `pre`/`code`/`button`/`*` elements (specificity (0,0,1) or (0,0,0)). The overrides cover:
17
+ - `.pcb pre { overflow: visible }` — prevents Tailwind's `pre { overflow-x: auto }` from creating a double scrollbar (one on `<pre>`, one on `.pcb__body`).
18
+ - `.pcb pre, .pcb code { font-family: var(--pcb-font-mono) }` — prevents Tailwind's `pre, code { font-family: ui-monospace }` from overriding the plugin's `--pcb-font-mono`.
19
+ - `.pcb__copy { appearance: none; background: transparent; border: 1px solid transparent; cursor: pointer }` — prevents Tailwind's `button { background: transparent; background-image: none }` from stripping the copy button's base styling.
20
+ - `.pcb__bar { border-bottom: 1px solid var(--pcb-border) }` — prevents Tailwind's `* { border-width: 0 }` from nuking the header bar's bottom border.
21
+ - `.pcb__code { white-space: pre }` — prevents Tailwind utilities like `break-words` or global `pre { white-space: pre-wrap }` from wrapping long lines instead of scrolling.
22
+
23
+ The `:where()` zero-specificity rules are preserved for all other styling — user CSS still wins without `!important` arms races. The new overrides only set the properties that frameworks clobber; everything else stays in `:where()`. No `!important` is used in the override block — the specificity is high enough to beat framework resets on its own.
24
+
25
+ ### Verification
26
+
27
+ - All 1114 pre-existing tests pass (no regressions).
28
+ - New `test-tailwind-compat.mjs` adds 20 regression tests covering: `:where()` rules preserved, framework-reset overrides exist with real specificity, overrides come after `:where()` rules (so they win on tie), no `!important` in override declarations, specificity verification (`.pcb pre` beats `pre`, `.pcb__copy` beats `button`, etc.), and documentation comments.
29
+ - Total: 1134/1134 tests passing.
30
+
8
31
  ## [1.3.2] — 2026-06-20
9
32
 
10
33
  ### Summary
package/dist/styles.css CHANGED
@@ -6,6 +6,8 @@
6
6
  - Solid gutter background hides code scrolling behind it
7
7
  - All defaults use :where() for zero specificity so user CSS wins
8
8
  - Every visual property is a --pcb-* CSS variable
9
+ - Framework-reset overrides (Tailwind/daisyUI compat) use real
10
+ specificity so they beat bare-element resets like `pre { ... }`
9
11
  ============================================================ */
10
12
 
11
13
  :where(.pcb) {
@@ -251,6 +253,69 @@
251
253
  display: block;
252
254
  }
253
255
 
256
+ /* ============================================================
257
+ Framework-reset overrides (Tailwind Preflight / daisyUI compat)
258
+ ------------------------------------------------------------
259
+ Tailwind Preflight targets bare `pre`, `code`, and `button`
260
+ elements with specificity (0,0,1). Our :where() rules above
261
+ have zero specificity (0,0,0), so Tailwind's resets WIN and
262
+ break the plugin's overflow model, font inheritance, and
263
+ copy-button styling.
264
+
265
+ These rules use REAL specificity (.pcb pre = (0,1,1),
266
+ .pcb__copy = (0,1,0)) to beat framework base resets WITHOUT
267
+ !important. They only set the properties that frameworks
268
+ clobber — everything else stays in :where() so user CSS
269
+ still wins.
270
+
271
+ If you're NOT using a CSS framework, these rules are harmless
272
+ (they set the same values as the :where() rules above).
273
+ ============================================================ */
274
+
275
+ /* Tailwind sets `pre { overflow-x: auto }` which creates a double-
276
+ scrollbar (one on <pre>, one on .pcb__body). Force <pre> to
277
+ visible so only .pcb__body scrolls. */
278
+ .pcb pre {
279
+ overflow: visible;
280
+ }
281
+
282
+ /* Tailwind sets `pre, code { font-family: ui-monospace, ... }` which
283
+ overrides the plugin's `font: inherit` and ignores --pcb-font-mono.
284
+ Re-assert the plugin's font. */
285
+ .pcb pre,
286
+ .pcb code {
287
+ font-family: var(--pcb-font-mono);
288
+ }
289
+
290
+ /* Tailwind sets `button { background: transparent; background-image: none }`
291
+ which strips the copy button's hover background. Re-assert the plugin's
292
+ button base. (.pcb__copy already has specificity (0,1,0) which beats
293
+ Tailwind's `button` (0,0,1), but we re-assert here for clarity and to
294
+ catch cases where frameworks add higher-specificity button resets.) */
295
+ .pcb__copy {
296
+ appearance: none;
297
+ background: transparent;
298
+ border: 1px solid transparent;
299
+ cursor: pointer;
300
+ }
301
+
302
+ /* Tailwind sets `*, ::before, ::after { border-width: 0 }` which nukes
303
+ borders on the header bar and copy button. Re-assert. */
304
+ .pcb__bar {
305
+ border-bottom: 1px solid var(--pcb-border);
306
+ }
307
+
308
+ /* Tailwind's box-sizing: border-box is fine (the plugin expects it).
309
+ No override needed. */
310
+
311
+ /* Some Tailwind utilities (e.g., `@apply break-words` or global
312
+ `pre { white-space: pre-wrap }`) can clobber the plugin's
313
+ `white-space: pre` on .pcb__code, causing long lines to wrap
314
+ instead of scroll. Re-assert with real specificity. */
315
+ .pcb__code {
316
+ white-space: pre;
317
+ }
318
+
254
319
  /* ---------- Row-based line grid ----------
255
320
  Each <span class="pcb__line"> uses display:contents so its children
256
321
  (.pcb__ln and .pcb__code) become grid items in the <code> container. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dr-ishaan/rehype-perfect-code-blocks",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Beautiful, configurable code blocks for Astro / MDX / any rehype pipeline. Built on Shiki, inspired by rehype-pretty-code, VitePress, Docusaurus, and Expressive Code.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -51,7 +51,7 @@
51
51
  "scripts": {
52
52
  "build": "tsc -p tsconfig.json && cp src/styles.css dist/styles.css",
53
53
  "dev": "tsc -p tsconfig.json --watch",
54
- "test": "node test-meta-parser.mjs && node test-dom-structure.mjs && node test-options.mjs && node test-notations.mjs && node test-security.mjs && node test-integration.mjs && node test-regression.mjs && node test-css.mjs && node test-edge-cases.mjs && node stress-tests.mjs && node new-feature-tests.mjs && node test-issue-12.mjs && node test-issue-11.mjs && node test-architecture-patterns.mjs && node test-copy-button-fix.mjs",
54
+ "test": "node test-meta-parser.mjs && node test-dom-structure.mjs && node test-options.mjs && node test-notations.mjs && node test-security.mjs && node test-integration.mjs && node test-regression.mjs && node test-css.mjs && node test-edge-cases.mjs && node stress-tests.mjs && node new-feature-tests.mjs && node test-issue-12.mjs && node test-issue-11.mjs && node test-architecture-patterns.mjs && node test-copy-button-fix.mjs && node test-tailwind-compat.mjs",
55
55
  "prepublishOnly": "npm run build && npm test",
56
56
  "prepack": "npm run build"
57
57
  },
package/src/styles.css CHANGED
@@ -6,6 +6,8 @@
6
6
  - Solid gutter background hides code scrolling behind it
7
7
  - All defaults use :where() for zero specificity so user CSS wins
8
8
  - Every visual property is a --pcb-* CSS variable
9
+ - Framework-reset overrides (Tailwind/daisyUI compat) use real
10
+ specificity so they beat bare-element resets like `pre { ... }`
9
11
  ============================================================ */
10
12
 
11
13
  :where(.pcb) {
@@ -251,6 +253,69 @@
251
253
  display: block;
252
254
  }
253
255
 
256
+ /* ============================================================
257
+ Framework-reset overrides (Tailwind Preflight / daisyUI compat)
258
+ ------------------------------------------------------------
259
+ Tailwind Preflight targets bare `pre`, `code`, and `button`
260
+ elements with specificity (0,0,1). Our :where() rules above
261
+ have zero specificity (0,0,0), so Tailwind's resets WIN and
262
+ break the plugin's overflow model, font inheritance, and
263
+ copy-button styling.
264
+
265
+ These rules use REAL specificity (.pcb pre = (0,1,1),
266
+ .pcb__copy = (0,1,0)) to beat framework base resets WITHOUT
267
+ !important. They only set the properties that frameworks
268
+ clobber — everything else stays in :where() so user CSS
269
+ still wins.
270
+
271
+ If you're NOT using a CSS framework, these rules are harmless
272
+ (they set the same values as the :where() rules above).
273
+ ============================================================ */
274
+
275
+ /* Tailwind sets `pre { overflow-x: auto }` which creates a double-
276
+ scrollbar (one on <pre>, one on .pcb__body). Force <pre> to
277
+ visible so only .pcb__body scrolls. */
278
+ .pcb pre {
279
+ overflow: visible;
280
+ }
281
+
282
+ /* Tailwind sets `pre, code { font-family: ui-monospace, ... }` which
283
+ overrides the plugin's `font: inherit` and ignores --pcb-font-mono.
284
+ Re-assert the plugin's font. */
285
+ .pcb pre,
286
+ .pcb code {
287
+ font-family: var(--pcb-font-mono);
288
+ }
289
+
290
+ /* Tailwind sets `button { background: transparent; background-image: none }`
291
+ which strips the copy button's hover background. Re-assert the plugin's
292
+ button base. (.pcb__copy already has specificity (0,1,0) which beats
293
+ Tailwind's `button` (0,0,1), but we re-assert here for clarity and to
294
+ catch cases where frameworks add higher-specificity button resets.) */
295
+ .pcb__copy {
296
+ appearance: none;
297
+ background: transparent;
298
+ border: 1px solid transparent;
299
+ cursor: pointer;
300
+ }
301
+
302
+ /* Tailwind sets `*, ::before, ::after { border-width: 0 }` which nukes
303
+ borders on the header bar and copy button. Re-assert. */
304
+ .pcb__bar {
305
+ border-bottom: 1px solid var(--pcb-border);
306
+ }
307
+
308
+ /* Tailwind's box-sizing: border-box is fine (the plugin expects it).
309
+ No override needed. */
310
+
311
+ /* Some Tailwind utilities (e.g., `@apply break-words` or global
312
+ `pre { white-space: pre-wrap }`) can clobber the plugin's
313
+ `white-space: pre` on .pcb__code, causing long lines to wrap
314
+ instead of scroll. Re-assert with real specificity. */
315
+ .pcb__code {
316
+ white-space: pre;
317
+ }
318
+
254
319
  /* ---------- Row-based line grid ----------
255
320
  Each <span class="pcb__line"> uses display:contents so its children
256
321
  (.pcb__ln and .pcb__code) become grid items in the <code> container. */