Skip to content

Commit bf5f847

Browse files
author
cdotlock
committed
chore: emit LS markdown sources
1 parent 98233ef commit bf5f847

4 files changed

Lines changed: 29 additions & 24 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ go build -o bin/lscc ./cmd/lscc
1414

1515
```bash
1616
# Compile a single episode
17-
lsc compile episode.ls --assets mapping.json -o output.json
17+
lsc compile episode.ls.md --assets mapping.json -o output.json
1818

1919
# Compile an entire novel directory
2020
lsc compile novel_001/main/ --assets mapping.json -o novel.json
2121

2222
# Decompile compiled JSON back to LS + recovered asset mapping
2323
lsc decompile output.json
24-
# writes output_decompiled/episode.ls and output_decompiled/assets_mapping.json
24+
# writes output_decompiled/episode.ls.md and output_decompiled/assets_mapping.json
2525

2626
# Validate syntax only
27-
lsc validate episode.ls
27+
lsc validate episode.ls.md
2828
```
2929

3030
## Script Format

api_server.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ def _run_ls(*args: str, workdir: Optional[str] = None, timeout: int = 30) -> sub
3434

3535
@app.post("/compile")
3636
async def compile_script(
37-
script: UploadFile = File(..., description="LS script file (.ls)"),
37+
script: UploadFile = File(..., description="LS script file (.ls or .ls.md)"),
3838
assets: Optional[UploadFile] = File(default=None, description="Optional assets mapping JSON file"),
3939
):
4040
"""
41-
Compile a single LS script (.ls) into structured JSON.
41+
Compile a single LS script (.ls or .ls.md) into structured JSON.
4242
4343
Returns the compiled episode JSON. If an assets mapping is provided,
4444
asset semantic names are resolved to full URLs.
@@ -47,7 +47,7 @@ async def compile_script(
4747
try:
4848
script_bytes = await script.read()
4949
script_text = script_bytes.decode("utf-8")
50-
script_path = os.path.join(tmpdir, "script.ls")
50+
script_path = os.path.join(tmpdir, "script.ls.md")
5151
with open(script_path, "w", encoding="utf-8") as f:
5252
f.write(script_text)
5353

@@ -93,8 +93,8 @@ async def compile_directory(
9393
"""
9494
Compile an entire episode directory (uploaded as a zip) into structured JSON.
9595
96-
The zip should contain one or more `.ls` files (e.g. 01.ls, 02.ls, …).
97-
Directory structure inside the zip is flattened — all `.ls` / `.episode.ls` files are
96+
The zip should contain one or more `.ls` / `.ls.md` files (e.g. 01.ls.md, 02.ls.md, …).
97+
Directory structure inside the zip is flattened — all `.ls` / `.ls.md` / `.episode.ls` / `.episode.ls.md` files are
9898
discovered recursively and compiled together.
9999
100100
Returns the compiled novel JSON (keyed by episode_id).
@@ -152,7 +152,7 @@ async def decompile_json(
152152
"""
153153
Decompile compiled LS JSON back into LS script and asset mapping.
154154
155-
Returns the reconstructed LS source (.ls) and the recovered asset mapping.
155+
Returns the reconstructed LS source (.ls.md) and the recovered asset mapping.
156156
"""
157157
tmpdir = tempfile.mkdtemp(prefix="ls_decompile_")
158158
try:
@@ -187,7 +187,12 @@ async def decompile_json(
187187
mapping = None
188188
for fname in os.listdir(output_dir):
189189
fpath = os.path.join(output_dir, fname)
190-
if fname.endswith(".ls") or fname.endswith(".episode.ls"):
190+
if (
191+
fname.endswith(".ls")
192+
or fname.endswith(".ls.md")
193+
or fname.endswith(".episode.ls")
194+
or fname.endswith(".episode.ls.md")
195+
):
191196
with open(fpath, "r", encoding="utf-8") as f:
192197
ls_files[fname] = f.read()
193198
elif fname.endswith(".json"):
@@ -216,7 +221,7 @@ async def decompile_json(
216221

217222
@app.post("/validate")
218223
async def validate_script(
219-
script: UploadFile = File(..., description="LS script file (.ls) to validate"),
224+
script: UploadFile = File(..., description="LS script file (.ls or .ls.md) to validate"),
220225
assets: Optional[UploadFile] = File(default=None, description="Optional assets mapping JSON file"),
221226
):
222227
"""
@@ -228,7 +233,7 @@ async def validate_script(
228233
try:
229234
script_bytes = await script.read()
230235
script_text = script_bytes.decode("utf-8")
231-
script_path = os.path.join(tmpdir, "script.ls")
236+
script_path = os.path.join(tmpdir, "script.ls.md")
232237
with open(script_path, "w", encoding="utf-8") as f:
233238
f.write(script_text)
234239

@@ -267,7 +272,7 @@ async def validate_script(
267272

268273
@app.post("/fix")
269274
async def fix_script(
270-
script: UploadFile = File(..., description="LS script file (.ls) to fix"),
275+
script: UploadFile = File(..., description="LS script file (.ls or .ls.md) to fix"),
271276
check: bool = Query(default=False, description="Dry-run: report issues without writing changes"),
272277
):
273278
"""
@@ -283,7 +288,7 @@ async def fix_script(
283288
try:
284289
script_bytes = await script.read()
285290
script_text = script_bytes.decode("utf-8")
286-
script_path = os.path.join(tmpdir, "script.ls")
291+
script_path = os.path.join(tmpdir, "script.ls.md")
287292
with open(script_path, "w", encoding="utf-8") as f:
288293
f.write(script_text)
289294

@@ -297,7 +302,7 @@ async def fix_script(
297302
}
298303
)
299304
else:
300-
output_path = os.path.join(tmpdir, "fixed.ls")
305+
output_path = os.path.join(tmpdir, "fixed.ls.md")
301306
proc = _run_ls("fix", script_path, "-o", output_path, timeout=30)
302307

303308
if proc.returncode != 0 and not os.path.exists(output_path):

cmd/lsc/main.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ func usage() {
3939
fmt.Fprintln(os.Stderr, "lsc - Lunascripts interpreter")
4040
fmt.Fprintln(os.Stderr, "")
4141
fmt.Fprintln(os.Stderr, "Usage:")
42-
fmt.Fprintln(os.Stderr, " lsc compile <file.ls|dir/> [--assets mapping.json] [-o output.json]")
43-
fmt.Fprintln(os.Stderr, " lsc decompile <output.json> [-o output-dir] Rebuild .ls + assets_mapping.json")
44-
fmt.Fprintln(os.Stderr, " lsc validate <file.ls> [--assets mapping.json]")
45-
fmt.Fprintln(os.Stderr, " lsc fix <file.ls> [-o output.ls] Fix and write (in-place if no -o)")
46-
fmt.Fprintln(os.Stderr, " lsc fix <file.ls> --check Dry run: report issues, don't write")
42+
fmt.Fprintln(os.Stderr, " lsc compile <file.ls|file.ls.md|dir/> [--assets mapping.json] [-o output.json]")
43+
fmt.Fprintln(os.Stderr, " lsc decompile <output.json> [-o output-dir] Rebuild .ls.md + assets_mapping.json")
44+
fmt.Fprintln(os.Stderr, " lsc validate <file.ls|file.ls.md> [--assets mapping.json]")
45+
fmt.Fprintln(os.Stderr, " lsc fix <file.ls|file.ls.md> [-o output.ls.md] Fix and write (in-place if no -o)")
46+
fmt.Fprintln(os.Stderr, " lsc fix <file.ls|file.ls.md> --check Dry run: report issues, don't write")
4747
os.Exit(1)
4848
}
4949

@@ -159,7 +159,7 @@ func cmdDecompile(args []string) {
159159
for _, ep := range result.Episodes {
160160
name := ep.Name
161161
if len(result.Episodes) == 1 {
162-
name = "episode.ls"
162+
name = "episode.ls.md"
163163
}
164164
path := filepath.Join(outputDir, name)
165165
if err := os.WriteFile(path, ep.Source, 0644); err != nil {
@@ -231,7 +231,7 @@ func compileFile(path string, res emitter.AssetResolver) ([]byte, error) {
231231
}
232232

233233
func isLsSourcePath(path string) bool {
234-
return strings.HasSuffix(path, ".ls") || strings.HasSuffix(path, ".ls.md")
234+
return strings.HasSuffix(path, ".ls.md") || strings.HasSuffix(path, ".ls")
235235
}
236236

237237
func compileDir(dir string, res emitter.AssetResolver) ([]byte, error) {

internal/decompiler/decompiler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ func episodeFileName(ep map[string]interface{}, idx int) string {
129129
if id == "" {
130130
id = fmt.Sprintf("episode_%02d", idx+1)
131131
}
132-
return sanitizeFileName(id) + ".ls"
132+
return sanitizeFileName(id) + ".ls.md"
133133
}
134134

135135
func uniqueEpisodeFileName(name string, used map[string]int) string {
136136
used[name]++
137137
if used[name] == 1 {
138138
return name
139139
}
140-
return strings.TrimSuffix(name, ".ls") + fmt.Sprintf("_%d.ls", used[name])
140+
return strings.TrimSuffix(name, ".ls.md") + fmt.Sprintf("_%d.ls.md", used[name])
141141
}
142142

143143
func sanitizeFileName(s string) string {

0 commit comments

Comments
 (0)