@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 +4 -0
- package/package.json +1 -1
- package/skills/stitch-showcase/SKILL.md +15 -11
- package/skills/stitch-showcase/references/index.html +4 -4
- package/skills/stitch-showcase/references/viewer.html +19 -4
- package/skills/stitch-showcase/scripts/build_showcase.py +24 -0
- package/skills/stitch-showcase/scripts/extract_zips.py +4 -9
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
|
@@ -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
|
|
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
|
|
65
|
-
python
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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:
|