powersync-docs/scripts/extract.py
Patrick Schurig 66aa71c990
All checks were successful
Build & Deploy docs / build-deploy (push) Successful in 2m53s
mise a jour
2026-06-06 09:51:43 +02:00

69 lines
3.0 KiB
Python

import xml.etree.ElementTree as ET, re, glob, json, os
SVG="http://www.w3.org/2000/svg"; ETM="https://etm-powersync.fr/ns/schema"
INK="http://www.inkscape.org/namespaces/inkscape"
SODI="http://sodipodi.sourceforge.net/DTD/sodipodi-0.0"
def ln(t): return t.split('}')[-1]
def parse_tf(s):
M=[1,0,0,1,0,0]
if not s: return M
for name,args in re.findall(r'(\w+)\s*\(([^)]*)\)', s):
n=[float(x) for x in re.split(r'[,\s]+',args.strip()) if x!='']
if name=='translate': m=[1,0,0,1,n[0],n[1] if len(n)>1 else 0]
elif name=='scale': m=[n[0],0,0,(n[1] if len(n)>1 else n[0]),0,0]
elif name=='matrix': m=n
else: m=[1,0,0,1,0,0]
a,b,c,d,e,f=M; a2,b2,c2,d2,e2,f2=m
M=[a*a2+c*b2,b*a2+d*b2,a*c2+c*d2,b*c2+d*d2,a*e2+c*f2+e,b*e2+d*f2+f]
return M
def comp(M1,M2):
a,b,c,d,e,f=M1;a2,b2,c2,d2,e2,f2=M2
return [a*a2+c*b2,b*a2+d*b2,a*c2+c*d2,b*c2+d*d2,a*e2+c*f2+e,b*e2+d*f2+f]
def app(M,x,y):
a,b,c,d,e,f=M; return (round(a*x+c*y+e,1),round(b*x+d*y+f,1))
def pos(el):
if ln(el.tag) in("circle","ellipse"): return float(el.get("cx",0)),float(el.get("cy",0))
if ln(el.tag)=="text": return float(el.get("x",0) or 0),float(el.get("y",0) or 0)
if ln(el.tag)=="path" and el.get(f"{{{SODI}}}type")=="arc":
return float(el.get(f"{{{SODI}}}cx",0)),float(el.get(f"{{{SODI}}}cy",0))
return None
lib={}
for fn in sorted(glob.glob("symbol-*.svg")):
root=ET.parse(fn).getroot()
c=root.find(f".//{{{ETM}}}component")
ctype=c.get("type") if c is not None else None
if not ctype: # repli : deduire du nom de fichier
stem=os.path.basename(fn)[:-4]
for pre in ("symbol-","block-"):
if stem.startswith(pre): stem=stem[len(pre):]
ctype=stem.replace("-","_")
terms={}; labels={}
def walk(el,M):
M=comp(M,parse_tf(el.get("transform")))
lab=el.get(f"{{{INK}}}label"); p=pos(el)
# inkscape:label term:/lbl:
if lab and p:
x,y=app(M,*p)
if lab.startswith("term:"): terms[lab[5:]]={"x":x,"y":y}
elif lab.startswith("lbl:"):
anchor=(el.get("text-anchor") or "start")
labels[lab[4:]]={"x":x,"y":y,"anchor":anchor}
# repli etm:terminal / etm:label
et=el.get(f"{{{ETM}}}terminal")
if et and p and et not in terms: terms[et]=dict(zip(("x","y"),app(M,*p)))
el_lbl=el.get(f"{{{ETM}}}label")
if el_lbl and p and el_lbl not in labels:
x,y=app(M,*p); labels[el_lbl]={"x":x,"y":y,"anchor":el.get("text-anchor") or "start"}
for ch in el: walk(ch,M)
walk(root,[1,0,0,1,0,0])
lib[fn]={"type":ctype,"terminals":terms,"labels":labels}
json.dump(lib, open("library.json","w"), indent=2, ensure_ascii=False)
# rapport
print(f"{'fichier':30} {'type':14} terminaux / labels")
for fn,d in lib.items():
t=",".join(d["terminals"]) or ""
l=",".join(d["labels"]) or ""
miss="" if d["type"] else " [TYPE MANQUANT]"
print(f"{fn:30} {str(d['type']):14} T[{t}] L[{l}]{miss}")