@liustack/pptwise 0.22.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/README.zh-CN.md +136 -0
  4. package/cordis.patch.yml +5 -0
  5. package/dist/chunk-3ZUKISTY.js +114 -0
  6. package/dist/chunk-3ZUKISTY.js.map +1 -0
  7. package/dist/chunk-M35M4QUC.js +1167 -0
  8. package/dist/chunk-M35M4QUC.js.map +1 -0
  9. package/dist/chunk-VUOLBHD7.js +19 -0
  10. package/dist/chunk-VUOLBHD7.js.map +1 -0
  11. package/dist/chunk-WL5KWYKS.js +49762 -0
  12. package/dist/chunk-WL5KWYKS.js.map +1 -0
  13. package/dist/cli.js +4753 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/index.d.ts +4224 -0
  16. package/dist/index.js +99 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/node.d.ts +7 -0
  19. package/dist/node.js +11 -0
  20. package/dist/node.js.map +1 -0
  21. package/dist/pixel-audit-H5K6JK3X.js +218 -0
  22. package/dist/pixel-audit-H5K6JK3X.js.map +1 -0
  23. package/dist/registry-C0GJH7ZT.d.ts +46 -0
  24. package/dsh/client.js +1398 -0
  25. package/dsh/index.js +141 -0
  26. package/dsh/preview-tool.js +1931 -0
  27. package/dsh/spawnHidden.js +109 -0
  28. package/package.json +113 -0
  29. package/skills/pptwise/SKILL.md +100 -0
  30. package/skills/pptwise/SKILL.zh-CN.md +102 -0
  31. package/skills/pptwise/references/branding.md +18 -0
  32. package/skills/pptwise/references/branding.zh-CN.md +21 -0
  33. package/skills/pptwise/references/components.md +35 -0
  34. package/skills/pptwise/references/components.zh-CN.md +40 -0
  35. package/skills/pptwise/references/density.md +17 -0
  36. package/skills/pptwise/references/density.zh-CN.md +22 -0
  37. package/skills/pptwise/references/images.md +42 -0
  38. package/skills/pptwise/references/images.zh-CN.md +47 -0
  39. package/skills/pptwise/references/layouts.md +37 -0
  40. package/skills/pptwise/references/layouts.zh-CN.md +42 -0
  41. package/skills/pptwise/references/spec.md +107 -0
  42. package/skills/pptwise/references/spec.zh-CN.md +112 -0
  43. package/skills/pptwise/references/validate.md +82 -0
  44. package/skills/pptwise/references/validate.zh-CN.md +87 -0
  45. package/skills/pptwise/scripts/run.ps1 +192 -0
  46. package/skills/pptwise/scripts/run.sh +229 -0
@@ -0,0 +1,192 @@
1
+ # pptwise skill launcher (Windows, PowerShell 5.1 compatible).
2
+ #
3
+ # The Windows twin of run.sh: identical resolution order, identical diagnostic
4
+ # fields, identical exit codes. One stable action for the agent ("run
5
+ # pptwise"); this script picks a working way to run it here.
6
+ #
7
+ # Invoke it per-process so no global policy is touched:
8
+ # powershell -ExecutionPolicy Bypass -File run.ps1 validate deck.json
9
+ #
10
+ # Resolution order (kept identical in run.sh):
11
+ # 1. A compatible pptwise already on PATH -> run it directly.
12
+ # 2. npx present, on a node meeting the floor -> run the pinned npm version.
13
+ # 3. bunx present -> run the pinned version via Bun.
14
+ # 4. Nothing usable -> structured diagnosis, exit 78.
15
+ #
16
+ # It never writes PATH, never needs admin rights, never fetches a second script,
17
+ # and has no postinstall step.
18
+
19
+ $ErrorActionPreference = 'Stop'
20
+
21
+ # --- Version constants: stamped by scripts/stamp.mts at release time. ---------
22
+ # Do not edit $Pinned by hand; scripts/stamp.test.mts asserts it equals the
23
+ # package.json version, and `pnpm release:version` rewrites it on every bump.
24
+ $Package = '@liustack/pptwise'
25
+ $Bin = 'pptwise'
26
+ $Pinned = '0.22.0'
27
+ # ------------------------------------------------------------------------------
28
+
29
+ # Environment snapshot, filled by Collect and read by the emitter.
30
+ $script:Arch = ''
31
+ $script:CliPresent = $false
32
+ $script:CliPath = $null
33
+ $script:CliVer = $null
34
+ $script:CliCompat = $false
35
+ $script:NpxPresent = $false
36
+ $script:NpxPath = $null
37
+ $script:BunxPresent = $false
38
+ $script:BunxPath = $null
39
+ $script:NodePresent = $false
40
+ $script:NodeVer = $null
41
+ $script:NodeFloorOk = $false
42
+ $script:Selected = 'none'
43
+
44
+ # First "X.Y.Z" token printed by `$Bin --version`.
45
+ function Get-CliVersion {
46
+ try { $out = & $Bin --version 2>$null } catch { return '' }
47
+ if (-not $out) { return '' }
48
+ $line = [string]($out | Select-Object -First 1)
49
+ $m = [regex]::Match($line, '[0-9]+\.[0-9]+\.[0-9]+')
50
+ if ($m.Success) { return $m.Value } else { return '' }
51
+ }
52
+
53
+ # Compatible = same major version as $Pinned AND not older than $Pinned.
54
+ # Same major keeps a globally installed CLI usable without a forced re-download;
55
+ # not-older refuses a stale build that predates the version this skill needs.
56
+ function Test-Compatible {
57
+ param([string] $Ver)
58
+ $f = $Ver -split '\.'
59
+ $p = $Pinned -split '\.'
60
+ if ($f.Count -lt 3 -or $p.Count -lt 3) { return $false }
61
+ $fMaj = [int]$f[0]; $fMin = [int]$f[1]; $fPat = [int]$f[2]
62
+ $pMaj = [int]$p[0]; $pMin = [int]$p[1]; $pPat = [int]$p[2]
63
+ if ($fMaj -ne $pMaj) { return $false }
64
+ if ($fMin -gt $pMin) { return $true }
65
+ if ($fMin -lt $pMin) { return $false }
66
+ return ($fPat -ge $pPat)
67
+ }
68
+
69
+ # The npx path runs the CLI on this machine's node, so npx is only usable when
70
+ # node itself meets the package's floor (package.json engines).
71
+ $NodeFloor = '22.19.0'
72
+ function Test-NodeMeetsFloor {
73
+ if (-not (Get-Command node -ErrorAction SilentlyContinue)) { return $false }
74
+ try { $nv = ((& node --version 2>$null) -replace '^v', '') } catch { return $false }
75
+ if (-not $nv) { return $false }
76
+ $n = $nv -split '\.'
77
+ $f = $NodeFloor -split '\.'
78
+ if ($n.Count -lt 2) { return $false }
79
+ $nMaj = [int]$n[0]; $nMin = [int]$n[1]
80
+ $fMaj = [int]$f[0]; $fMin = [int]$f[1]
81
+ if ($nMaj -gt $fMaj) { return $true }
82
+ if ($nMaj -lt $fMaj) { return $false }
83
+ return ($nMin -ge $fMin)
84
+ }
85
+
86
+ # Return exactly one word: the chosen launch path.
87
+ function Resolve-LaunchKind {
88
+ $cli = Get-Command $Bin -ErrorAction SilentlyContinue
89
+ if ($cli) {
90
+ $v = Get-CliVersion
91
+ if ($v -and (Test-Compatible $v)) { return 'path' }
92
+ }
93
+ if ((Get-Command npx -ErrorAction SilentlyContinue) -and (Test-NodeMeetsFloor)) { return 'npx' }
94
+ if (Get-Command bunx -ErrorAction SilentlyContinue) { return 'bunx' }
95
+ return 'none'
96
+ }
97
+
98
+ function Get-Arch {
99
+ switch ($env:PROCESSOR_ARCHITECTURE) {
100
+ 'AMD64' { return 'x64' }
101
+ 'ARM64' { return 'arm64' }
102
+ 'x86' { return 'x86' }
103
+ default { return $env:PROCESSOR_ARCHITECTURE }
104
+ }
105
+ }
106
+
107
+ # Probe the environment once into the $script:* snapshot.
108
+ function Collect {
109
+ $script:Arch = Get-Arch
110
+
111
+ $cli = Get-Command $Bin -ErrorAction SilentlyContinue
112
+ if ($cli) {
113
+ $script:CliPresent = $true
114
+ $script:CliPath = $cli.Source
115
+ $script:CliVer = Get-CliVersion
116
+ $script:CliCompat = [bool]($script:CliVer -and (Test-Compatible $script:CliVer))
117
+ }
118
+
119
+ $npx = Get-Command npx -ErrorAction SilentlyContinue
120
+ if ($npx) { $script:NpxPresent = $true; $script:NpxPath = $npx.Source }
121
+
122
+ $bunx = Get-Command bunx -ErrorAction SilentlyContinue
123
+ if ($bunx) { $script:BunxPresent = $true; $script:BunxPath = $bunx.Source }
124
+
125
+ $node = Get-Command node -ErrorAction SilentlyContinue
126
+ if ($node) {
127
+ $script:NodePresent = $true
128
+ try { $script:NodeVer = ((& node --version 2>$null) -replace '^v', '') } catch { $script:NodeVer = $null }
129
+ $script:NodeFloorOk = Test-NodeMeetsFloor
130
+ }
131
+
132
+ $script:Selected = Resolve-LaunchKind
133
+ }
134
+
135
+ # Assemble the structured diagnosis.
136
+ function Build-DiagnosisJson {
137
+ $checked = [ordered]@{
138
+ pathCli = [ordered]@{ present = $script:CliPresent; path = $script:CliPath; version = $script:CliVer; compatible = $script:CliCompat }
139
+ npx = [ordered]@{ present = $script:NpxPresent; path = $script:NpxPath; nodeMeetsFloor = $script:NodeFloorOk }
140
+ bunx = [ordered]@{ present = $script:BunxPresent; path = $script:BunxPath }
141
+ node = [ordered]@{ present = $script:NodePresent; version = $script:NodeVer }
142
+ }
143
+ $steps = @()
144
+ if ($script:Selected -eq 'none') {
145
+ $major = $Pinned.Split('.')[0]
146
+ $first = "Install Node 22.19+ from https://nodejs.org so npx can run $Package@$Pinned, then re-run this launcher."
147
+ if ($script:NpxPresent -and (-not $script:NodeFloorOk)) {
148
+ $first = "npx is present but node $(if ($script:NodeVer) { $script:NodeVer } else { 'missing' }) is below the $NodeFloor floor this CLI needs. Upgrade Node at https://nodejs.org, then re-run this launcher."
149
+ }
150
+ $steps = @(
151
+ $first,
152
+ "No JavaScript runtime? Install Bun from https://bun.sh to use bunx, or put a compatible $Bin (major $major, at or above $Pinned) on PATH."
153
+ )
154
+ }
155
+ $obj = [ordered]@{
156
+ tool = $Bin
157
+ package = $Package
158
+ pinnedVersion = $Pinned
159
+ os = 'windows'
160
+ arch = $script:Arch
161
+ checked = $checked
162
+ selected = $script:Selected
163
+ nextSteps = @($steps)
164
+ }
165
+ return ($obj | ConvertTo-Json -Depth 20)
166
+ }
167
+
168
+ # Default action: forward every argument to the resolved CLI and exit with its
169
+ # code. No usable runtime -> structured diagnosis on stderr, exit 78 (EX_CONFIG)
170
+ # so the agent never mistakes the diagnosis for a result.
171
+ function Invoke-Run {
172
+ param([string[]] $CliArgs)
173
+ $sel = Resolve-LaunchKind
174
+ switch ($sel) {
175
+ 'path' { & $Bin @CliArgs; exit $LASTEXITCODE }
176
+ 'npx' { & npx --yes --package "$Package@$Pinned" $Bin @CliArgs; exit $LASTEXITCODE }
177
+ 'bunx' { & bunx --bun "$Package@$Pinned" @CliArgs; exit $LASTEXITCODE }
178
+ 'none' {
179
+ Collect
180
+ [Console]::Error.WriteLine((Build-DiagnosisJson))
181
+ exit 78
182
+ }
183
+ }
184
+ }
185
+
186
+ $Command = ''
187
+ if ($args.Count -ge 1) { $Command = [string]$args[0] }
188
+
189
+ switch ($Command) {
190
+ 'where' { Collect; Write-Output $script:Selected }
191
+ default { Invoke-Run -CliArgs $args }
192
+ }
@@ -0,0 +1,229 @@
1
+ #!/bin/sh
2
+ # pptwise skill launcher (macOS / Linux).
3
+ #
4
+ # One stable action for the agent ("run pptwise"); this script picks a working
5
+ # way to run it in the current environment. Written to POSIX sh so it runs under
6
+ # dash, busybox ash, and bash alike. Invoke it with `bash run.sh ...` (or plain
7
+ # `sh run.sh ...`) so a lost execute bit after a file copy never matters.
8
+ #
9
+ # Resolution order (kept identical in run.ps1):
10
+ # 1. A compatible pptwise already on PATH -> run it directly.
11
+ # 2. npx present, on a node meeting the floor -> run the pinned npm version.
12
+ # 3. bunx present -> run the pinned version via Bun.
13
+ # 4. Nothing usable -> structured diagnosis, exit 78.
14
+ #
15
+ # It never writes PATH, never needs admin rights, never fetches a second script,
16
+ # and has no postinstall step.
17
+ set -eu
18
+
19
+ # --- Version constants: stamped by scripts/stamp.mts at release time. ---------
20
+ # Do not edit PINNED by hand; scripts/stamp.test.mts asserts it equals the
21
+ # package.json version, and `pnpm release:version` rewrites it on every bump.
22
+ PKG="@liustack/pptwise"
23
+ BIN="pptwise"
24
+ PINNED="0.22.0"
25
+ # ------------------------------------------------------------------------------
26
+
27
+ # Split "X.Y.Z" (extra suffix ignored) into the globals _MAJ, _MIN, _PAT.
28
+ # Any non-numeric component becomes 0 so integer tests below never abort.
29
+ parse_semver() {
30
+ _raw="$1"
31
+ _MAJ="${_raw%%.*}"
32
+ _rest="${_raw#*.}"
33
+ if [ "$_rest" = "$_raw" ]; then
34
+ _MIN=0
35
+ _PAT=0
36
+ else
37
+ _MIN="${_rest%%.*}"
38
+ _rest2="${_rest#*.}"
39
+ if [ "$_rest2" = "$_rest" ]; then _PAT=0; else _PAT="${_rest2%%.*}"; fi
40
+ fi
41
+ case "$_MAJ" in '' | *[!0-9]*) _MAJ=0 ;; esac
42
+ case "$_MIN" in '' | *[!0-9]*) _MIN=0 ;; esac
43
+ case "$_PAT" in '' | *[!0-9]*) _PAT=0 ;; esac
44
+ }
45
+
46
+ # Compatible = same major version as PINNED AND not older than PINNED.
47
+ # Same major keeps a globally installed CLI usable without a forced re-download;
48
+ # not-older refuses a stale build that predates the version this skill needs.
49
+ compatible() {
50
+ parse_semver "$1"
51
+ _f_maj=$_MAJ
52
+ _f_min=$_MIN
53
+ _f_pat=$_PAT
54
+ parse_semver "$PINNED"
55
+ [ "$_f_maj" = "$_MAJ" ] || return 1
56
+ if [ "$_f_min" -gt "$_MIN" ]; then return 0; fi
57
+ if [ "$_f_min" -lt "$_MIN" ]; then return 1; fi
58
+ [ "$_f_pat" -ge "$_PAT" ]
59
+ }
60
+
61
+ # First "X.Y.Z" token printed by `$BIN --version`.
62
+ cli_version() {
63
+ "$BIN" --version 2>/dev/null | head -n 1 |
64
+ sed -n 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'
65
+ }
66
+
67
+ # The npx path runs the CLI on this machine's node, so npx is only usable when
68
+ # node itself meets the package's floor (package.json engines). An old node
69
+ # with a working npx would otherwise be selected into a path known to fail.
70
+ NODE_FLOOR="22.19.0"
71
+ node_meets_floor() {
72
+ command -v node >/dev/null 2>&1 || return 1
73
+ _nv="$(node --version 2>/dev/null | sed 's/^v//')"
74
+ [ -n "$_nv" ] || return 1
75
+ parse_semver "$NODE_FLOOR"
76
+ _floor_maj="$_MAJ"
77
+ _floor_min="$_MIN"
78
+ parse_semver "$_nv"
79
+ if [ "$_MAJ" -gt "$_floor_maj" ]; then return 0; fi
80
+ if [ "$_MAJ" -lt "$_floor_maj" ]; then return 1; fi
81
+ [ "$_MIN" -ge "$_floor_min" ]
82
+ }
83
+
84
+ # Echo exactly one word: the chosen launch path.
85
+ resolve() {
86
+ if command -v "$BIN" >/dev/null 2>&1; then
87
+ _v="$(cli_version)"
88
+ if [ -n "$_v" ] && compatible "$_v"; then
89
+ echo "path"
90
+ return
91
+ fi
92
+ fi
93
+ if command -v npx >/dev/null 2>&1 && node_meets_floor; then
94
+ echo "npx"
95
+ return
96
+ fi
97
+ if command -v bunx >/dev/null 2>&1; then
98
+ echo "bunx"
99
+ return
100
+ fi
101
+ echo "none"
102
+ }
103
+
104
+ detect_os() { uname -s 2>/dev/null | tr '[:upper:]' '[:lower:]'; }
105
+
106
+ detect_arch() {
107
+ _a="$(uname -m 2>/dev/null)"
108
+ case "$_a" in
109
+ x86_64 | amd64) echo "x64" ;;
110
+ aarch64 | arm64) echo "arm64" ;;
111
+ *) echo "$_a" ;;
112
+ esac
113
+ }
114
+
115
+ # Escape a value for a JSON string literal (backslash and double quote).
116
+ json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
117
+
118
+ # Render "null" for an empty value, else an escaped JSON string.
119
+ jstr() {
120
+ if [ -z "$1" ]; then printf 'null'; else printf '"%s"' "$(json_escape "$1")"; fi
121
+ }
122
+
123
+ # 1 -> true, anything else -> false.
124
+ jbool() { if [ "$1" = "1" ]; then printf 'true'; else printf 'false'; fi; }
125
+
126
+ # Probe the environment once into G_* globals shared by the emitters.
127
+ collect() {
128
+ G_OS="$(detect_os)"
129
+ G_ARCH="$(detect_arch)"
130
+
131
+ G_CLI_PRESENT=0
132
+ G_CLI_PATH=""
133
+ G_CLI_VER=""
134
+ G_CLI_COMPAT=0
135
+ if command -v "$BIN" >/dev/null 2>&1; then
136
+ G_CLI_PRESENT=1
137
+ G_CLI_PATH="$(command -v "$BIN")"
138
+ G_CLI_VER="$(cli_version)"
139
+ if [ -n "$G_CLI_VER" ] && compatible "$G_CLI_VER"; then G_CLI_COMPAT=1; fi
140
+ fi
141
+
142
+ G_NPX_PRESENT=0
143
+ G_NPX_PATH=""
144
+ if command -v npx >/dev/null 2>&1; then
145
+ G_NPX_PRESENT=1
146
+ G_NPX_PATH="$(command -v npx)"
147
+ fi
148
+
149
+ G_BUNX_PRESENT=0
150
+ G_BUNX_PATH=""
151
+ if command -v bunx >/dev/null 2>&1; then
152
+ G_BUNX_PRESENT=1
153
+ G_BUNX_PATH="$(command -v bunx)"
154
+ fi
155
+
156
+ G_NODE_PRESENT=0
157
+ G_NODE_VER=""
158
+ if command -v node >/dev/null 2>&1; then
159
+ G_NODE_PRESENT=1
160
+ G_NODE_VER="$(node --version 2>/dev/null | sed 's/^v//')"
161
+ fi
162
+
163
+ G_NODE_FLOOR_OK=0
164
+ if node_meets_floor; then G_NODE_FLOOR_OK=1; fi
165
+
166
+ G_SEL="$(resolve)"
167
+ }
168
+
169
+ # Build the nextSteps JSON array body (without the brackets) into G_NEXTSTEPS.
170
+ compute_next_steps() {
171
+ if [ "$G_SEL" = "none" ]; then
172
+ if [ "$G_NPX_PRESENT" = 1 ] && [ "$G_NODE_FLOOR_OK" = 0 ]; then
173
+ _s1="npx is present but node ${G_NODE_VER:-missing} is below the $NODE_FLOOR floor this CLI needs. Upgrade Node at https://nodejs.org, then re-run this launcher."
174
+ else
175
+ _s1="Install Node 22.19+ from https://nodejs.org so npx can run $PKG@$PINNED, then re-run this launcher."
176
+ fi
177
+ _s2="No JavaScript runtime? Install Bun from https://bun.sh to use bunx, or put a compatible $BIN (major ${PINNED%%.*}, at or above $PINNED) on PATH."
178
+ G_NEXTSTEPS="$(printf '"%s", "%s"' "$(json_escape "$_s1")" "$(json_escape "$_s2")")"
179
+ else
180
+ G_NEXTSTEPS=""
181
+ fi
182
+ }
183
+
184
+ # Emit the structured diagnosis.
185
+ emit_json() {
186
+ compute_next_steps
187
+ printf '{\n'
188
+ printf ' "tool": %s,\n' "$(jstr "$BIN")"
189
+ printf ' "package": %s,\n' "$(jstr "$PKG")"
190
+ printf ' "pinnedVersion": %s,\n' "$(jstr "$PINNED")"
191
+ printf ' "os": %s,\n' "$(jstr "$G_OS")"
192
+ printf ' "arch": %s,\n' "$(jstr "$G_ARCH")"
193
+ printf ' "checked": {\n'
194
+ printf ' "pathCli": { "present": %s, "path": %s, "version": %s, "compatible": %s },\n' \
195
+ "$(jbool "$G_CLI_PRESENT")" "$(jstr "$G_CLI_PATH")" "$(jstr "$G_CLI_VER")" "$(jbool "$G_CLI_COMPAT")"
196
+ printf ' "npx": { "present": %s, "path": %s, "nodeMeetsFloor": %s },\n' "$(jbool "$G_NPX_PRESENT")" "$(jstr "$G_NPX_PATH")" "$(jbool "$G_NODE_FLOOR_OK")"
197
+ printf ' "bunx": { "present": %s, "path": %s },\n' "$(jbool "$G_BUNX_PRESENT")" "$(jstr "$G_BUNX_PATH")"
198
+ printf ' "node": { "present": %s, "version": %s }\n' "$(jbool "$G_NODE_PRESENT")" "$(jstr "$G_NODE_VER")"
199
+ printf ' },\n'
200
+ printf ' "selected": %s,\n' "$(jstr "$G_SEL")"
201
+ printf ' "nextSteps": [%s]\n' "$G_NEXTSTEPS"
202
+ printf '}\n'
203
+ }
204
+
205
+ # Default action: forward every argument to the resolved CLI, inheriting stdio
206
+ # and exit code. No usable runtime -> structured diagnosis on stderr, exit 78
207
+ # (EX_CONFIG) so the agent never mistakes the diagnosis for a result.
208
+ run() {
209
+ _sel="$(resolve)"
210
+ case "$_sel" in
211
+ path) exec "$BIN" "$@" ;;
212
+ npx) exec npx --yes --package "$PKG@$PINNED" "$BIN" "$@" ;;
213
+ bunx) exec bunx --bun "$PKG@$PINNED" "$@" ;;
214
+ none)
215
+ collect
216
+ emit_json >&2
217
+ exit 78
218
+ ;;
219
+ esac
220
+ }
221
+
222
+ case "${1:-}" in
223
+ where)
224
+ resolve
225
+ ;;
226
+ *)
227
+ run "$@"
228
+ ;;
229
+ esac