You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/scripts/rewrite-soma-reactive.py

95 lines
2.8 KiB

eidos: pilot wrapper pattern + doctrinal API conventions Toggle as the eidos pilot: subdirectory layout (recipe + Svelte wrapper + types + index + README) replacing the flat CSS-only form. Pattern is documented in eidos/components/README.md and the toggle README. Shared types live in eidos/lib/types.ts. First export is `Size` (8 values xxs..xxl + full); components narrow with `Extract<Size, ...>` per the per-component-subset doctrine. No `Eidos` prefix on types — module path already conveys the layer. API doctrine: - soma stays compound (Toggle.Provider) for symmetry with multi-part - eidos exports both default + Provider so single-part components accept both `<Toggle>` (ergonomic) and `<Toggle.Provider>` (compound-style consumers) SoundChannel eager-init fixes the autoplay race: AudioContext is created + resumed synchronously on the first user gesture (capture-phase listener registered in the constructor), avoiding the previous race where the first emit() scheduled the resume in a microtask outside the gesture window. Demo page (web/routes/toggle/+page.svelte) restructured so the live preview renders ALWAYS above the tablist — Sema-tab Play buttons can fire on the real toggle. Motion preview amplifies scale ×8 visually only; doctrinal values stay in the <dl>. Conventions 7-13 added to src/docs/sema-implementation-guide.md covering: directory structure, wrapper composition, no Eidos prefix, soma compound vs eidos flat, iconOnly sr-only body, sound eager-init, docs-preview amplification. CLAUDE.md gets a session hand-off block listing where things stand and next concrete steps (migrate switch/collapsible/dialog/drawer/popover/ toast/avatar; wire topbar sound mute to masterGain; rename theme tokens to drop the success/warning/danger fallback aliases). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
"""One-shot rewrite of soma/reactive imports.
For each soma file (excluding soma/reactive itself):
- find each `import { ... } from '<rel>/reactive'` or `'$soma/reactive'`
- split the names: libs symbols → '$libs/reactive', provider symbols → '$soma/provider'
- emit one or two replacement imports
"""
import os
import re
import sys
LIBS_SYMBOLS = {
'state', 'readableActive', 'writableActive', 'autoReset',
'isState', 'isActive',
'ActiveSymbol', 'WritableSymbol',
'Active', 'State', 'Getter',
'ActiveProps', 'StateProps',
}
PROVIDER_SYMBOLS = {
'bindProps', 'OptsFromProps', 'WritableSpec', 'PropsConfigEntry',
}
IMPORT_RE = re.compile(
r"import\s+(type\s+)?\{([^}]+)\}\s+from\s+['\"](?:(?:\.\./)+reactive|\$soma/reactive)['\"];?",
re.MULTILINE,
)
def parse_names(block):
out = []
for raw in block.split(','):
item = raw.strip()
if not item:
continue
is_type = False
if item.startswith('type '):
is_type = True
item = item[5:].strip()
out.append((item, is_type))
return out
def render_import(items, source, has_type_import):
if not items:
return ''
type_marker = 'type ' if has_type_import else ''
parts = []
for name, is_type in items:
if has_type_import:
parts.append(name)
else:
parts.append(f'type {name}' if is_type else name)
body = ',\n\t'.join(parts)
return f"import {type_marker}{{\n\t{body}\n}} from '{source}';"
def process_match(m):
has_type_import = bool(m.group(1))
names = parse_names(m.group(2))
libs_items = [(n, t) for (n, t) in names if n in LIBS_SYMBOLS]
prov_items = [(n, t) for (n, t) in names if n in PROVIDER_SYMBOLS]
other_items = [(n, t) for (n, t) in names if n not in LIBS_SYMBOLS and n not in PROVIDER_SYMBOLS]
if other_items:
print('UNKNOWN names:', other_items, file=sys.stderr)
return m.group(0)
out = []
if libs_items:
out.append(render_import(libs_items, '$libs/reactive', has_type_import))
if prov_items:
out.append(render_import(prov_items, '$soma/provider', has_type_import))
return '\n'.join(out)
SKIP_DIR = os.path.normpath('src/uix/soma/reactive')
changed = []
for root, dirs, files in os.walk('src/uix/soma'):
if os.path.normpath(root) == SKIP_DIR:
continue
for f in files:
if not f.endswith(('.ts', '.svelte', '.svelte.ts')):
continue
p = os.path.join(root, f)
s = open(p, 'r', encoding='utf-8').read()
new = IMPORT_RE.sub(process_match, s)
if new != s:
open(p, 'w', encoding='utf-8').write(new)
changed.append(p)
for f in changed:
print(f)
print(f'--- {len(changed)} files updated ---')

Powered by TurnKey Linux.