@maccesar/aiskills 1.9.3 → 1.11.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.
package/README.md CHANGED
@@ -114,6 +114,10 @@ Confirmations:
114
114
  - `proceed` / `sí` / `commitea` → release on current branch only.
115
115
  - `merge` → release + fast-forward merge to main + push main, and leaves you on `main`. Aborts cleanly if main has diverged.
116
116
  - `PR` → release + open pull request to main via `gh`.
117
+ - `con tag` / `with tag` (modifier, combinable with any of the above) → on a private repo, force-create the git tag (the GitHub release stays skipped). No effect on public/internal repos.
118
+
119
+ Private-repo behavior:
120
+ - When `gh repo view` reports the repo as `PRIVATE`, the workflow skips both the git tag and the GitHub release by default — tags/releases are distribution artifacts that aren't usually needed for private projects. The version bump in `package.json` / `tiapp.xml` / etc. plus the `CHANGELOG.md` entry remain. Add `con tag` / `with tag` to your confirmation if you want the tag anyway.
117
121
 
118
122
  Language policy (two independent axes):
119
123
  - **Axis 1 — Interaction with you** — always in your language. The command detects the language from your messages and locks it before printing anything; if you switch, it switches with you.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maccesar/aiskills",
3
- "version": "1.9.3",
3
+ "version": "1.11.0",
4
4
  "description": "AI coding assistant skills for Claude Code, Gemini CLI, and Codex CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,6 +13,10 @@ Converts Google Stitch exports (zips with `code.html` + `screen.png`) into a nav
13
13
 
14
14
  Scripts require Python 3.8+. No external dependencies (stdlib only).
15
15
 
16
+ ## Script paths
17
+
18
+ All commands below use `<SKILL_DIR>/scripts/...` as a placeholder. Replace `<SKILL_DIR>` with the absolute "Base directory for this skill" shown in the system message when this skill loads (e.g. `~/.claude/plugins/cache/<plugin>/<version>/skills/stitch-showcase` for plugin installs, or `~/.claude/skills/stitch-showcase` for standalone installs). Do not assume `~/.claude/skills/...` — the path differs by install type.
19
+
16
20
  ## Workflow: Four Modes
17
21
 
18
22
  ```dot
@@ -47,7 +51,7 @@ Steps:
47
51
  1. Identify the source path from the user's message
48
52
  2. Run the build script — **nothing else**:
49
53
  ```bash
50
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/source
54
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/source
51
55
  ```
52
56
  3. Parse the script output to get the `showcase/` path
53
57
  4. Open the showcase in the default browser:
@@ -61,8 +65,8 @@ Steps:
61
65
  Only ask `--type` or `--name` if the **script fails** or the **user explicitly wants to override**:
62
66
  ```bash
63
67
  # Only if script fails to detect type or user requests it
64
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/source --type mobile
65
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/source --name "My App" --type mobile
68
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/source --type mobile
69
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/source --name "My App" --type mobile
66
70
  ```
67
71
 
68
72
  ## Mode 2: Enrich (on-demand — user asks)
@@ -75,7 +79,7 @@ Steps:
75
79
  1. Find the source folder (from the user's message or the project's `showcase.json`)
76
80
  2. Run `--extract-text` to get screen summaries:
77
81
  ```bash
78
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/source --extract-text
82
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/source --extract-text
79
83
  ```
80
84
  This generates `screen_summaries.txt` — a compact text file with visible text from all screen HTMLs.
81
85
  3. Read the existing `DESIGN.md` (in the source folder) + `screen_summaries.txt`
@@ -87,7 +91,7 @@ Steps:
87
91
  6. **Verify colors/fonts**: Scan the screen HTMLs for hex colors in CSS variables and font families. Update `## Colors` and `## Typography` sections if they're missing or incomplete.
88
92
  7. Re-run the build to regenerate HTMLs with enriched data:
89
93
  ```bash
90
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/source
94
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/source
91
95
  ```
92
96
  8. Done — tell the user the showcase has been updated with improved descriptions
93
97
 
@@ -136,13 +140,13 @@ Steps:
136
140
 
137
141
  ```bash
138
142
  # Structural components (navbar, footer, sidebar, tabbar)
139
- python ~/.claude/skills/stitch-showcase/scripts/apply_canonical.py /path/to/showcase/assets/ navbar home_screen
143
+ python <SKILL_DIR>/scripts/apply_canonical.py /path/to/showcase/assets/ navbar home_screen
140
144
 
141
145
  # Atomic components (button, input, heading, etc.)
142
- python ~/.claude/skills/stitch-showcase/scripts/apply_canonical.py /path/to/showcase/assets/ button home_screen
146
+ python <SKILL_DIR>/scripts/apply_canonical.py /path/to/showcase/assets/ button home_screen
143
147
 
144
148
  # Target specific screens only
145
- python ~/.claude/skills/stitch-showcase/scripts/apply_canonical.py /path/to/showcase/assets/ navbar home_screen --targets login settings profile
149
+ python <SKILL_DIR>/scripts/apply_canonical.py /path/to/showcase/assets/ navbar home_screen --targets login settings profile
146
150
  ```
147
151
 
148
152
  4. Rebuild the showcase: `build_showcase.py /path/to/source`
@@ -177,13 +181,13 @@ The catalog is generated automatically as part of every build. Open `catalog.htm
177
181
 
178
182
  ```bash
179
183
  # Point to the project root — the script discovers the source automatically
180
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/project
184
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/project
181
185
 
182
186
  # Or point directly to the folder with zips/screens
183
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/project/stitch
187
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/project/stitch
184
188
 
185
189
  # Single mega-zip (zip containing all screens as subfolders)
186
- python ~/.claude/skills/stitch-showcase/scripts/build_showcase.py /path/to/export.zip
190
+ python <SKILL_DIR>/scripts/build_showcase.py /path/to/export.zip
187
191
  ```
188
192
 
189
193
  ### Flags
@@ -186,13 +186,13 @@
186
186
  // Update badge text
187
187
  viewBadge.textContent = currentView === 'mobile' ? 'Mobile' : 'WEB';
188
188
 
189
- // Update toggle icon: show the icon of the OTHER mode (what you'll switch to)
189
+ // Update toggle icon: show the icon of the CURRENT mode (matches the badge)
190
190
  if (currentView === 'mobile') {
191
- iconPhone.classList.add('hidden');
192
- iconMonitor.classList.remove('hidden');
193
- } else {
194
191
  iconPhone.classList.remove('hidden');
195
192
  iconMonitor.classList.add('hidden');
193
+ } else {
194
+ iconPhone.classList.add('hidden');
195
+ iconMonitor.classList.remove('hidden');
196
196
  }
197
197
  }
198
198
  applyViewMode();
@@ -219,6 +219,21 @@
219
219
  var frameMobile = document.getElementById('viewer-frame-mobile');
220
220
  var frameWeb = document.getElementById('viewer-frame-web');
221
221
 
222
+ // Inject scrollbar-hiding CSS into iframes after load (cosmetic, viewer-level only).
223
+ // Keeps source HTMLs untouched so they're clean for downstream handoff.
224
+ function injectScrollbarCSS(frame) {
225
+ try {
226
+ var doc = frame.contentDocument || frame.contentWindow.document;
227
+ if (!doc || doc.getElementById('__no-scrollbar-style')) return;
228
+ var style = doc.createElement('style');
229
+ style.id = '__no-scrollbar-style';
230
+ style.textContent = '*::-webkit-scrollbar{display:none!important}*{scrollbar-width:none!important;-ms-overflow-style:none!important}';
231
+ doc.head.appendChild(style);
232
+ } catch (e) { /* cross-origin or not yet ready */ }
233
+ }
234
+ frameMobile.addEventListener('load', function () { injectScrollbarCSS(frameMobile); });
235
+ frameWeb.addEventListener('load', function () { injectScrollbarCSS(frameWeb); });
236
+
222
237
  var screens = SCREENS;
223
238
  var currentIndex = 0;
224
239
  var VIEW_KEY = 'showcase-view-mode-' + '{{PROJECT_SLUG}}';
@@ -230,13 +245,13 @@
230
245
  root.classList.remove('view-mobile', 'view-web');
231
246
  root.classList.add('view-' + currentView);
232
247
 
233
- // Toggle icon shows what you'll switch TO
248
+ // Toggle icon shows the CURRENT mode (matches the badge)
234
249
  if (currentView === 'mobile') {
235
- iconPhone.classList.add('hidden');
236
- iconMonitor.classList.remove('hidden');
237
- } else {
238
250
  iconPhone.classList.remove('hidden');
239
251
  iconMonitor.classList.add('hidden');
252
+ } else {
253
+ iconPhone.classList.add('hidden');
254
+ iconMonitor.classList.remove('hidden');
240
255
  }
241
256
 
242
257
  // Recalc phone scaling when switching to mobile
@@ -106,6 +106,18 @@ def build(source_dir: str, project_type: str = None, project_name: str = None) -
106
106
  print("Error: no screens found (no zips or folders with code.html).", file=sys.stderr)
107
107
  sys.exit(1)
108
108
 
109
+ # Copy shared asset folders (images, fonts, css, js) referenced by relative paths in HTMLs.
110
+ # Searches in source/, then source.parent/ (project root). Skips if already copied.
111
+ for asset_name in ('images', 'fonts', 'css', 'js'):
112
+ for candidate_root in (source, source.parent):
113
+ candidate = candidate_root / asset_name
114
+ if candidate.is_dir():
115
+ dest = assets_dir / asset_name
116
+ if not dest.exists():
117
+ shutil.copytree(candidate, dest)
118
+ print(f" ✓ Copied shared {asset_name}/ from {candidate_root.name}/")
119
+ break
120
+
109
121
  # Enrich with DESIGN.md metadata
110
122
  screens = _enrich_screens(screens_raw, metadata, source)
111
123
 
@@ -160,6 +172,18 @@ def build_context(source_dir: str, project_type: str = None, project_name: str =
160
172
  print("Error: no screens found (no zips or folders with code.html).", file=sys.stderr)
161
173
  sys.exit(1)
162
174
 
175
+ # Copy shared asset folders (images, fonts, css, js) referenced by relative paths in HTMLs.
176
+ # Searches in source/, then source.parent/ (project root). Skips if already copied.
177
+ for asset_name in ('images', 'fonts', 'css', 'js'):
178
+ for candidate_root in (source, source.parent):
179
+ candidate = candidate_root / asset_name
180
+ if candidate.is_dir():
181
+ dest = assets_dir / asset_name
182
+ if not dest.exists():
183
+ shutil.copytree(candidate, dest)
184
+ print(f" ✓ Copied shared {asset_name}/ from {candidate_root.name}/")
185
+ break
186
+
163
187
  # Enrich with DESIGN.md metadata
164
188
  screens = _enrich_screens(screens_raw, metadata, source)
165
189
 
@@ -136,16 +136,11 @@ def _process_dir(dir_path: Path, slug: str, assets: Path) -> dict | None:
136
136
  }
137
137
 
138
138
 
139
- _NO_SCROLLBAR_CSS = '<style>*::-webkit-scrollbar{display:none!important}*{scrollbar-width:none!important;-ms-overflow-style:none!important}</style>'
140
-
141
139
  def _copy_html(src: Path, dst: Path) -> None:
142
- """Copy HTML injecting scrollbar-hiding CSS into <head>."""
143
- text = src.read_text(encoding="utf-8", errors="ignore")
144
- if "</head>" in text:
145
- text = text.replace("</head>", f"{_NO_SCROLLBAR_CSS}</head>", 1)
146
- elif "<body" in text:
147
- text = text.replace("<body", f"{_NO_SCROLLBAR_CSS}<body", 1)
148
- dst.write_text(text, encoding="utf-8")
140
+ """Copy HTML verbatim. Scrollbar-hiding CSS is now injected at viewer level
141
+ (see references/viewer.html), keeping the source HTML untouched so it can be
142
+ handed off cleanly to downstream tools (e.g., Laravel Blade conversion)."""
143
+ shutil.copy2(src, dst)
149
144
 
150
145
 
151
146
  def _find_file(root: Path, filename: str) -> Path | None: