@iamdangavin/claude-skill-vitepress-docs 1.9.0 → 2.1.0

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/skill/SKILL.md +321 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamdangavin/claude-skill-vitepress-docs",
3
- "version": "1.9.0",
3
+ "version": "2.1.0",
4
4
  "description": "Installs the vitepress:docs Claude Code skill — VitePress docs setup, generation, screenshots, and sync.",
5
5
  "type": "module",
6
6
  "bin": {
package/skill/SKILL.md CHANGED
@@ -23,6 +23,8 @@ Four modes for full VitePress documentation lifecycle. If no mode is given as an
23
23
  - "generate — Analyze the codebase and write documentation pages"
24
24
  - "screenshot — Capture real screenshots and replace placeholders"
25
25
  - "sync — Detect code drift and update docs that are out of date"
26
+ - "brand — Configure colors, fonts, logo, and visual identity"
27
+ - "update — Retrofit an existing docs setup with the latest components and dependencies"
26
28
 
27
29
  ---
28
30
 
@@ -588,13 +590,13 @@ If `apiBase` was collected in Q1b, write the following files before updating the
588
590
  @click="activeTab = tab"
589
591
  >{{ tab }}</button>
590
592
  </div>
591
- <pre class="api-ep__code"><code>{{ currentSample }}</code></pre>
593
+ <pre class="api-ep__code"><code v-html="highlightedSample"></code></pre>
592
594
  <p v-if="activeTab === 'Fetch'" class="api-ep__note">
593
595
  Must be called from an authenticated browser session — cookies are sent automatically.
594
596
  </p>
595
597
  <template v-if="response">
596
598
  <div class="api-ep__section-label">Sample Response</div>
597
- <pre class="api-ep__code"><code>{{ formattedResponse }}</code></pre>
599
+ <pre class="api-ep__code"><code v-html="highlightedResponse"></code></pre>
598
600
  </template>
599
601
  </div>
600
602
  </div>
@@ -603,6 +605,19 @@ If `apiBase` was collected in Q1b, write the following files before updating the
603
605
  <script setup>
604
606
  import { ref, computed } from 'vue'
605
607
  import { useData } from 'vitepress'
608
+ import hljs from 'highlight.js/lib/core'
609
+ import javascript from 'highlight.js/lib/languages/javascript'
610
+ import bash from 'highlight.js/lib/languages/bash'
611
+ import json from 'highlight.js/lib/languages/json'
612
+ // ADD THESE ONLY IF THE CORRESPONDING TAB WAS SELECTED IN Q1b:
613
+ // import php from 'highlight.js/lib/languages/php'
614
+ // import python from 'highlight.js/lib/languages/python'
615
+
616
+ hljs.registerLanguage('javascript', javascript) // Fetch + Axios
617
+ hljs.registerLanguage('bash', bash) // cURL
618
+ hljs.registerLanguage('json', json) // response bodies
619
+ // hljs.registerLanguage('php', php)
620
+ // hljs.registerLanguage('python', python)
606
621
 
607
622
  const props = defineProps({
608
623
  method: { type: String, required: true },
@@ -658,9 +673,33 @@ const currentSample = computed(() => {
658
673
  return ''
659
674
  })
660
675
 
676
+ // Map tab names to highlight.js language identifiers
677
+ const tabLang = {
678
+ 'Fetch': 'javascript',
679
+ 'Axios': 'javascript',
680
+ 'cURL': 'bash',
681
+ 'PHP': 'php',
682
+ 'Python': 'python',
683
+ }
684
+
685
+ const highlight = (code, lang) => {
686
+ const registered = hljs.getLanguage(lang)
687
+ return registered
688
+ ? hljs.highlight(code, { language: lang }).value
689
+ : hljs.highlightAuto(code).value
690
+ }
691
+
692
+ const highlightedSample = computed(() =>
693
+ highlight(currentSample.value, tabLang[activeTab.value] ?? 'bash')
694
+ )
695
+
661
696
  const formattedResponse = computed(() =>
662
697
  props.response ? JSON.stringify(props.response, null, 2) : ''
663
698
  )
699
+
700
+ const highlightedResponse = computed(() =>
701
+ formattedResponse.value ? highlight(formattedResponse.value, 'json') : ''
702
+ )
664
703
  </script>
665
704
 
666
705
  <style scoped>
@@ -686,10 +725,10 @@ const formattedResponse = computed(() =>
686
725
  </style>
687
726
  ```
688
727
 
689
- **Install `medium-zoom`** in the docs folder:
728
+ **Install dependencies** in the docs folder:
690
729
 
691
730
  ```bash
692
- cd DOCS_FOLDER && npm install medium-zoom
731
+ cd DOCS_FOLDER && npm install medium-zoom highlight.js
693
732
  ```
694
733
 
695
734
  **`.vitepress/theme/index.css`** — create if it doesn't exist, otherwise append:
@@ -1026,6 +1065,284 @@ Updated X of N drifted pages.
1026
1065
 
1027
1066
  ---
1028
1067
 
1068
+ ## Mode: brand
1069
+
1070
+ ### Step 1 — Locate docs paths
1071
+
1072
+ Check the manifest(s) to find all configured docs folders. If no manifest exists, scan for `.vitepress/config.mjs` files across the known focus paths. Present what was found so the user can confirm before proceeding.
1073
+
1074
+ ### Step 2 — Shared or per-path branding
1075
+
1076
+ If more than one docs path is found, ask:
1077
+
1078
+ - header: "Branding scope"
1079
+ - question: "How should branding be applied across your docs?"
1080
+ - options:
1081
+ - "Same brand across all docs"
1082
+ - "Different brand per path — I'll configure each one separately"
1083
+
1084
+ If per-path: complete all brand questions for path 1 before moving to path 2 — never ask about two paths simultaneously.
1085
+
1086
+ ### Step 3 — Brand questions
1087
+
1088
+ Ask these once (shared) or once per path (per-path). Always label the header with the path name when in per-path mode so the user knows which repo they're configuring.
1089
+
1090
+ **B-Q1 — Primary brand color** (plain text): Ask — "What is the primary brand color? (hex, e.g. `#E63946`). This becomes the link, button, and accent color throughout the docs."
1091
+
1092
+ From this single hex value, derive the full VitePress brand palette automatically:
1093
+ - `--vp-c-brand-1`: the base hex
1094
+ - `--vp-c-brand-2`: 15% lighter
1095
+ - `--vp-c-brand-3`: 30% lighter
1096
+ - `--vp-c-brand-soft`: the hex at 12% opacity (for backgrounds)
1097
+
1098
+ Also derive dark mode variants — slightly brighter versions of each to account for dark backgrounds. Present the derived palette to the user before writing anything.
1099
+
1100
+ **B-Q2 — Logo:**
1101
+ - header: "Logo"
1102
+ - question: "Do you have a logo to use in the docs nav?"
1103
+ - options:
1104
+ - "Yes — I'll provide the path to the file"
1105
+ - "Text only — use the site title"
1106
+ - "Skip for now"
1107
+
1108
+ If yes: ask as plain text — "What is the path to the logo file? (SVG or PNG recommended, e.g. `public/logo.svg`)"
1109
+
1110
+ **B-Q3 — Favicon:**
1111
+ - header: "Favicon"
1112
+ - question: "Do you have a favicon?"
1113
+ - options:
1114
+ - "Yes — I'll provide the path"
1115
+ - "Use the logo as favicon"
1116
+ - "Skip for now"
1117
+
1118
+ If yes: ask as plain text — "Path to favicon? (e.g. `public/favicon.ico` or `public/favicon.svg`)"
1119
+
1120
+ **B-Q4 — Font:**
1121
+ - header: "Font"
1122
+ - question: "What font should the docs use?"
1123
+ - options:
1124
+ - "VitePress default (Inter)"
1125
+ - "System font stack (no external load)"
1126
+ - "Google Font — I'll tell you which"
1127
+ - "Custom — I'll provide the CSS import"
1128
+
1129
+ If Google Font: ask as plain text — "Which Google Font family? (e.g. `Outfit`, `DM Sans`)"
1130
+ If custom: ask as plain text — "Paste your @import or @font-face CSS."
1131
+
1132
+ **B-Q5 — Dark mode:**
1133
+ - header: "Dark mode"
1134
+ - question: "How should dark mode colors work?"
1135
+ - options:
1136
+ - "Auto-derive from brand color (recommended)"
1137
+ - "I want to set a custom dark mode accent color"
1138
+ - "Use VitePress default dark mode"
1139
+
1140
+ If custom: ask as plain text — "What hex color for dark mode accent?"
1141
+
1142
+ ### Step 4 — Preview palette
1143
+
1144
+ Before writing any files, present the full derived palette as a table:
1145
+
1146
+ ```
1147
+ Light mode
1148
+ --vp-c-brand-1: #E63946
1149
+ --vp-c-brand-2: #EB5E6A
1150
+ --vp-c-brand-3: #F28B93
1151
+ --vp-c-brand-soft: #E6394620
1152
+
1153
+ Dark mode
1154
+ --vp-c-brand-1: #F05A64
1155
+ --vp-c-brand-2: #F47980
1156
+ --vp-c-brand-3: #F7A0A5
1157
+ --vp-c-brand-soft: #F05A6420
1158
+ ```
1159
+
1160
+ Then ask:
1161
+
1162
+ - header: "Palette"
1163
+ - question: "Does this palette look right?"
1164
+ - options:
1165
+ - "Yes — apply it"
1166
+ - "Adjust the base color — I'll give you a new hex"
1167
+ - "Manually tweak individual values"
1168
+
1169
+ If adjust: take the new hex and re-derive. If manual: ask as plain text for each value to change.
1170
+
1171
+ ### Step 5 — Write brand files
1172
+
1173
+ For each docs path being branded:
1174
+
1175
+ **`.vitepress/theme/index.css`** — append the brand variables block. Do not remove existing entries — only add or update the brand vars:
1176
+
1177
+ ```css
1178
+ :root {
1179
+ --vp-c-brand-1: HEX1;
1180
+ --vp-c-brand-2: HEX2;
1181
+ --vp-c-brand-3: HEX3;
1182
+ --vp-c-brand-soft: HEXSOFT;
1183
+ /* FONT_VARS if custom font selected */
1184
+ }
1185
+
1186
+ .dark {
1187
+ --vp-c-brand-1: DARK_HEX1;
1188
+ --vp-c-brand-2: DARK_HEX2;
1189
+ --vp-c-brand-3: DARK_HEX3;
1190
+ --vp-c-brand-soft: DARK_HEXSOFT;
1191
+ }
1192
+ ```
1193
+
1194
+ If a Google Font was selected, add the `@import` at the top of the CSS file and set `--vp-font-family-base`.
1195
+
1196
+ **`.vitepress/config.mjs`** — add to `themeConfig`:
1197
+ - `logo` field if a logo was provided
1198
+ - `favicon` via `head` entry if a favicon was provided
1199
+
1200
+ Read the existing config before editing. Make only targeted additions — do not rewrite unrelated sections.
1201
+
1202
+ ### Step 6 — Summary
1203
+
1204
+ ```
1205
+ Branded X docs path(s).
1206
+
1207
+ Files updated:
1208
+ PATH/.vitepress/theme/index.css — brand palette + font
1209
+ PATH/.vitepress/config.mjs — logo, favicon
1210
+
1211
+ Run the local dev server to preview: npm run dev
1212
+ ```
1213
+
1214
+ ---
1215
+
1216
+ ## Mode: update
1217
+
1218
+ Retrofits an existing VitePress docs setup with the latest components, dependencies, and theme wiring from this skill. Does not re-run setup or regenerate pages.
1219
+
1220
+ ### Step 1 — Locate docs paths
1221
+
1222
+ Scan the current working directory and any known focus paths for `.vitepress/config.mjs` (or `.ts`) files. List what was found and ask the user to confirm which paths to upgrade.
1223
+
1224
+ ### Step 2 — Inventory current state
1225
+
1226
+ For each confirmed docs path, check what is already present:
1227
+
1228
+ - `.vitepress/components/ApiEndpoint.vue` — exists? version detectable?
1229
+ - `.vitepress/theme/index.js` — exists? includes `medium-zoom`? includes `ApiEndpoint`?
1230
+ - `.vitepress/theme/index.css` — exists? includes `.medium-zoom-overlay` z-index rules?
1231
+ - `package.json` — are `medium-zoom` and `highlight.js` listed in dependencies?
1232
+
1233
+ Report findings as a checklist:
1234
+ ```
1235
+ Path: docs/
1236
+ [x] ApiEndpoint.vue — found (needs update)
1237
+ [ ] medium-zoom installed
1238
+ [x] highlight.js installed
1239
+ [x] theme/index.js — found (missing medium-zoom wiring)
1240
+ [x] theme/index.css — found (missing z-index rules)
1241
+ ```
1242
+
1243
+ Then ask:
1244
+
1245
+ - header: "Update"
1246
+ - question: "What would you like to update?"
1247
+ - options:
1248
+ - "Everything that's missing or outdated"
1249
+ - "Let me choose item by item"
1250
+
1251
+ ### Step 3 — Gather inputs (only if needed)
1252
+
1253
+ If `ApiEndpoint.vue` is being written or updated and no existing `apiBase` is in the VitePress config, ask:
1254
+
1255
+ **U-Q1 — API base URL** (plain text): "What is the API base URL? (e.g. `https://api.example.com/wp-json/my-plugin/v1`)"
1256
+
1257
+ **U-Q2 — Code sample tabs:**
1258
+ - header: "Code tabs"
1259
+ - question: "Which code sample tabs should the ApiEndpoint component show?"
1260
+ - options:
1261
+ - "Fetch + cURL (default)"
1262
+ - "Fetch + cURL + PHP"
1263
+ - "Fetch + cURL + Python"
1264
+ - "Fetch + cURL + Axios"
1265
+ - "All of the above"
1266
+ - "Custom — I'll list them"
1267
+
1268
+ Skip U-Q1 and U-Q2 if `apiBase` already exists in `.vitepress/config.mjs` `themeConfig` — infer `apiBase` and existing tabs from the config and the current `ApiEndpoint.vue`.
1269
+
1270
+ ### Step 4 — Apply upgrades
1271
+
1272
+ Apply only the items selected (or all missing/outdated items if "Everything" was chosen). Always read existing files before editing — never overwrite unrelated content.
1273
+
1274
+ **`ApiEndpoint.vue`** — write the full component from the template in generate Step 6, substituting the correct tab list. If the file already exists, replace it entirely (it is a generated component, not hand-edited).
1275
+
1276
+ **`medium-zoom` + `highlight.js`** — if either is missing from `package.json` dependencies, run:
1277
+ ```bash
1278
+ cd DOCS_FOLDER && npm install medium-zoom highlight.js
1279
+ ```
1280
+
1281
+ **`.vitepress/theme/index.css`** — if `.medium-zoom-overlay` z-index block is missing, append:
1282
+ ```css
1283
+ .medium-zoom-overlay {
1284
+ z-index: 100;
1285
+ }
1286
+
1287
+ .medium-zoom-image--opened {
1288
+ z-index: 101;
1289
+ }
1290
+ ```
1291
+ Do not remove or overwrite existing entries.
1292
+
1293
+ **`.vitepress/theme/index.js`** — merge only what is missing:
1294
+ - If `medium-zoom` wiring is absent, add the `onMounted`/`watch` setup block
1295
+ - If `ApiEndpoint` registration is absent (and `apiBase` is configured), add the import and `app.component()` call
1296
+ - Never remove existing registrations or setup logic
1297
+
1298
+ Use this as the reference template for the full correct state of `index.js`:
1299
+ ```js
1300
+ import DefaultTheme from 'vitepress/theme'
1301
+ import { onMounted, watch, nextTick } from 'vue'
1302
+ import { useRoute } from 'vitepress'
1303
+ import mediumZoom from 'medium-zoom'
1304
+ import './index.css'
1305
+ import ApiEndpoint from '../components/ApiEndpoint.vue'
1306
+
1307
+ export default {
1308
+ extends: DefaultTheme,
1309
+ setup() {
1310
+ const route = useRoute()
1311
+ const initZoom = () => mediumZoom('.main img', { background: 'var(--vp-c-bg)' })
1312
+ onMounted(initZoom)
1313
+ watch(() => route.path, () => nextTick(initZoom))
1314
+ },
1315
+ enhanceApp({ app }) {
1316
+ app.component('ApiEndpoint', ApiEndpoint)
1317
+ }
1318
+ }
1319
+ ```
1320
+
1321
+ **`.vitepress/config.mjs`** — if `apiBase` was collected and is not already in `themeConfig`, add it:
1322
+ ```js
1323
+ themeConfig: {
1324
+ apiBase: 'API_BASE_URL',
1325
+ // ...existing themeConfig
1326
+ }
1327
+ ```
1328
+
1329
+ ### Step 5 — Summary
1330
+
1331
+ ```
1332
+ Upgraded X of Y docs path(s).
1333
+
1334
+ Changes applied:
1335
+ PATH/.vitepress/components/ApiEndpoint.vue — written (tabs: Fetch, cURL, PHP)
1336
+ PATH/.vitepress/theme/index.js — merged medium-zoom + ApiEndpoint
1337
+ PATH/.vitepress/theme/index.css — added z-index rules
1338
+ PATH/package.json — installed medium-zoom, highlight.js
1339
+
1340
+ No changes needed:
1341
+ PATH/.vitepress/config.mjs — apiBase already present
1342
+ ```
1343
+
1344
+ ---
1345
+
1029
1346
  ## Notes
1030
1347
 
1031
1348
  - Never write the GitHub Actions workflow inside the docs folder — it goes in `.github/workflows/` at the repo root.