@chanmeng666/archlang 0.6.0 → 0.7.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/dist/{chunk-PABYLU6Z.js → chunk-CPK5CI5Y.js} +421 -241
- package/dist/chunk-CPK5CI5Y.js.map +1 -0
- package/dist/cli.js +5 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +211 -25
- package/dist/index.js +5 -3
- package/package.json +2 -3
- package/dist/chunk-PABYLU6Z.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -243,6 +243,163 @@ interface PlanNode {
|
|
|
243
243
|
body: Statement[];
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
/** Pure geometry helpers. All coordinates in millimetres. Deterministic. */
|
|
247
|
+
|
|
248
|
+
interface Bounds {
|
|
249
|
+
minX: number;
|
|
250
|
+
minY: number;
|
|
251
|
+
maxX: number;
|
|
252
|
+
maxY: number;
|
|
253
|
+
}
|
|
254
|
+
interface WallSegment {
|
|
255
|
+
a: Point;
|
|
256
|
+
b: Point;
|
|
257
|
+
thickness: number;
|
|
258
|
+
category: string;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Backend-neutral **Scene IR** — the keystone drawing intermediate.
|
|
263
|
+
*
|
|
264
|
+
* `resolve()` produces semantic geometry (rooms, walls, openings); this module
|
|
265
|
+
* defines a flat list of *positioned drawing primitives* tagged with a layer and
|
|
266
|
+
* paint. Geometry is computed exactly **once** here (by the elements, lowered via
|
|
267
|
+
* `scene-build.ts`); every backend (SVG, DXF, PDF, …) is then a thin, pure
|
|
268
|
+
* serializer of the same `Scene`. This kills the geometry duplication the
|
|
269
|
+
* string-based `RenderOp` forced (DXF re-deriving door arcs, PDF rasterizing SVG).
|
|
270
|
+
*
|
|
271
|
+
* Prior art: Typst's `Frame`/`FrameItem` (crates/typst-library/src/layout/frame.rs)
|
|
272
|
+
* — a positioned list of drawable items — and D2's `d2target` (a flat, pointer-free
|
|
273
|
+
* render target consumed by independent backends). ArchLang has no nested
|
|
274
|
+
* transforms, so unlike Typst's `Frame` the node list is flat (no sub-frames).
|
|
275
|
+
*
|
|
276
|
+
* Phase v0.7 keeps this deliberately small: line-weight/line-type/named-layer
|
|
277
|
+
* metadata, hatch primitives, and circles are intentionally deferred to Phase v0.9
|
|
278
|
+
* (roadmap §6). Poché stays an SVG `<pattern>` fill string; page chrome (north
|
|
279
|
+
* arrow, scale bar, title block) stays in the backends for now.
|
|
280
|
+
*/
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Ordered draw layers. Nodes are bucketed by `layer` and emitted in this order,
|
|
284
|
+
* preserving collection order within a layer — this exactly reproduces the v0.1
|
|
285
|
+
* global draw order (all wall fills, then all wall faces, doors before windows,
|
|
286
|
+
* labels above fills, …). Doubles as the discriminant of {@link SceneNode.layer}.
|
|
287
|
+
*/
|
|
288
|
+
declare const RENDER_PASSES: readonly ["floor", "furniture", "wallFill", "wallFace", "doors", "windows", "labels", "dims", "annotations"];
|
|
289
|
+
type RenderPass = (typeof RENDER_PASSES)[number];
|
|
290
|
+
/** Render-derived sizes (in mm), scaled from the drawing's reference dimension. */
|
|
291
|
+
interface RenderSizes {
|
|
292
|
+
refDim: number;
|
|
293
|
+
wallStroke: number;
|
|
294
|
+
thin: number;
|
|
295
|
+
roomFont: number;
|
|
296
|
+
areaFont: number;
|
|
297
|
+
dimFont: number;
|
|
298
|
+
furnFont: number;
|
|
299
|
+
margin: number;
|
|
300
|
+
hatchGap: number;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* How a primitive is painted. Strokes/fills carry colours (already theme-resolved
|
|
304
|
+
* and escaped at the serialization boundary); `width`/`dash` carry *raw* numbers
|
|
305
|
+
* that each backend formats. The optional `linecap`/`linejoin`/`fillRule` cover
|
|
306
|
+
* the exact SVG attributes the original element emitters used, so the SVG
|
|
307
|
+
* serializer reproduces today's output byte-for-byte.
|
|
308
|
+
*/
|
|
309
|
+
interface Paint {
|
|
310
|
+
/** A colour, `"none"`, or an SVG pattern ref like `"url(#poche)"`. */
|
|
311
|
+
fill?: string;
|
|
312
|
+
stroke?: string;
|
|
313
|
+
/** Raw stroke width in mm (backend applies its own number formatting). */
|
|
314
|
+
width?: number;
|
|
315
|
+
/** `stroke-dasharray` pair in mm (e.g. door swing arc). */
|
|
316
|
+
dash?: [number, number];
|
|
317
|
+
linecap?: "square";
|
|
318
|
+
linejoin?: "miter";
|
|
319
|
+
fillRule?: "nonzero";
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* A positioned drawing primitive. Coordinates are absolute millimetres in the
|
|
323
|
+
* plan's space (origin top-left, +x right, +y down — SVG convention); backends
|
|
324
|
+
* apply their own transforms (e.g. DXF's Y-flip).
|
|
325
|
+
*/
|
|
326
|
+
type ScenePrim =
|
|
327
|
+
/** A filled/stroked closed polygon (room, furniture, column, opening cover, per-segment wall fill). */
|
|
328
|
+
{
|
|
329
|
+
t: "polygon";
|
|
330
|
+
pts: Point[];
|
|
331
|
+
}
|
|
332
|
+
/** A single straight segment (wall face, door leaf, window pane, dimension lines/ticks). */
|
|
333
|
+
| {
|
|
334
|
+
t: "line";
|
|
335
|
+
a: Point;
|
|
336
|
+
b: Point;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* A multi-loop closed region drawn as one path (`fill-rule` nonzero), used for
|
|
340
|
+
* unioned orthogonal walls so the poché fills with proper holes and the outline
|
|
341
|
+
* has no internal seams.
|
|
342
|
+
*/
|
|
343
|
+
| {
|
|
344
|
+
t: "region";
|
|
345
|
+
loops: Point[][];
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* A circular arc (door swing). Carries the `center`/`r` a CAD backend needs to
|
|
349
|
+
* emit a native arc, plus the explicit `start`/`end` points + `sweep` flag an
|
|
350
|
+
* SVG `A` command needs — so neither backend re-derives endpoints from trig.
|
|
351
|
+
*/
|
|
352
|
+
| {
|
|
353
|
+
t: "arc";
|
|
354
|
+
center: Point;
|
|
355
|
+
r: number;
|
|
356
|
+
start: Point;
|
|
357
|
+
end: Point;
|
|
358
|
+
sweep: 0 | 1;
|
|
359
|
+
}
|
|
360
|
+
/** A text label. `value` is the raw (unescaped) string; backends escape on emit. */
|
|
361
|
+
| {
|
|
362
|
+
t: "text";
|
|
363
|
+
at: Point;
|
|
364
|
+
value: string;
|
|
365
|
+
size: number;
|
|
366
|
+
anchor: "start" | "middle" | "end";
|
|
367
|
+
baseline: "central";
|
|
368
|
+
/** SVG `font-weight` (e.g. 600 for a room name). */
|
|
369
|
+
weight?: number;
|
|
370
|
+
/** Rotation in degrees about `at` (e.g. dimension text along its line). */
|
|
371
|
+
rotate?: number;
|
|
372
|
+
};
|
|
373
|
+
/** One drawable: a primitive on a layer, with paint and an optional source span. */
|
|
374
|
+
interface SceneNode {
|
|
375
|
+
layer: RenderPass;
|
|
376
|
+
prim: ScenePrim;
|
|
377
|
+
paint: Paint;
|
|
378
|
+
span?: Span;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* A complete, backend-neutral drawing. `nodes` is the geometry; the remaining
|
|
382
|
+
* fields are the page-level context backends need (viewBox sizing, theme colours
|
|
383
|
+
* for chrome, north/scale/title block, hatch materials in use). Theme is baked
|
|
384
|
+
* into node paint already — it is carried here only for the page chrome.
|
|
385
|
+
*/
|
|
386
|
+
interface Scene {
|
|
387
|
+
/** Padded page width/height in mm (drawing extent + annotation margin). */
|
|
388
|
+
width: number;
|
|
389
|
+
height: number;
|
|
390
|
+
/** Tight drawing bounds (before margin), for chrome placement. */
|
|
391
|
+
bounds: Bounds;
|
|
392
|
+
nodes: SceneNode[];
|
|
393
|
+
theme: Theme;
|
|
394
|
+
sizes: RenderSizes;
|
|
395
|
+
north: NorthDir;
|
|
396
|
+
scale?: string;
|
|
397
|
+
title?: TitleNode;
|
|
398
|
+
name: string;
|
|
399
|
+
/** Distinct wall materials in use (stable order), so the SVG backend can emit hatch `<pattern>`s. */
|
|
400
|
+
materials: string[];
|
|
401
|
+
}
|
|
402
|
+
|
|
246
403
|
interface CompileError {
|
|
247
404
|
/** Human-readable message. */
|
|
248
405
|
message: string;
|
|
@@ -280,15 +437,12 @@ interface CompileResult {
|
|
|
280
437
|
diagnostics: Diagnostic[];
|
|
281
438
|
/** The validated AST, present whenever parsing succeeded. */
|
|
282
439
|
ast?: PlanNode;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
b: Point;
|
|
290
|
-
thickness: number;
|
|
291
|
-
category: string;
|
|
440
|
+
/**
|
|
441
|
+
* The backend-neutral Scene IR (positioned drawing primitives), present
|
|
442
|
+
* whenever rendering succeeded (i.e. no fatal errors). Feed it to alternate
|
|
443
|
+
* backends: `toDxf(scene)`, `toPdf(scene)`.
|
|
444
|
+
*/
|
|
445
|
+
scene?: Scene;
|
|
292
446
|
}
|
|
293
447
|
|
|
294
448
|
/**
|
|
@@ -381,29 +535,61 @@ declare function resolve(ast: PlanNode): {
|
|
|
381
535
|
};
|
|
382
536
|
|
|
383
537
|
/**
|
|
384
|
-
*
|
|
385
|
-
* AC1009, the most broadly importable flavor). Pure, synchronous, zero-dep:
|
|
386
|
-
* DXF is plain text, so this needs no external library and is safe to ship in
|
|
387
|
-
* the core. It is NOT part of `compile()` — call it on the IR from `resolve()`.
|
|
538
|
+
* Lowers a resolved plan (IR) to the backend-neutral {@link Scene}.
|
|
388
539
|
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
540
|
+
* This is the single place geometry is assembled: each element contributes
|
|
541
|
+
* positioned primitives via its registry `render`, walls are unioned/offset here
|
|
542
|
+
* (the only element needing cross-segment treatment), and the page-level sizing
|
|
543
|
+
* (reference dimension, derived font/stroke sizes, bounds) is computed once and
|
|
544
|
+
* carried on the Scene for the backends. Pure & deterministic — no I/O, no time.
|
|
391
545
|
*/
|
|
392
546
|
|
|
393
|
-
/**
|
|
394
|
-
|
|
547
|
+
/**
|
|
548
|
+
* Build the {@link Scene} for a resolved plan. The theme is merged + sanitized
|
|
549
|
+
* once here and baked into node paint; it is also carried on the Scene for the
|
|
550
|
+
* page chrome (north/scale/title). `opts.width` does not affect the Scene (it is
|
|
551
|
+
* an SVG-only attribute) — only `opts.theme` participates.
|
|
552
|
+
*/
|
|
553
|
+
declare function toScene(ir: ResolvedPlan, opts?: CompileOptions): Scene;
|
|
395
554
|
|
|
396
555
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
556
|
+
* DXF export backend — a pure serializer of the {@link Scene}. Emits ASCII DXF
|
|
557
|
+
* (R12 / AC1009, the most broadly importable flavor). Pure, synchronous,
|
|
558
|
+
* zero-dep: DXF is plain text, so this needs no external library and ships in the
|
|
559
|
+
* core. Build a Scene with `toScene(resolve(ast).ir)` (or `compile().scene`).
|
|
560
|
+
*
|
|
561
|
+
* As of v0.7 the geometry is NOT re-derived here: door arcs, window panes, and
|
|
562
|
+
* dimension ticks are the very `ScenePrim`s the elements produced. Each primitive
|
|
563
|
+
* maps generically to a DXF entity; the only element-aware step is mapping a draw
|
|
564
|
+
* layer to a DXF layer name. DXF's Y axis points up while ArchLang's points down,
|
|
565
|
+
* so every Y is negated to keep plans right-side-up in CAD.
|
|
401
566
|
*/
|
|
567
|
+
|
|
568
|
+
/** Render a {@link Scene} as an ASCII DXF document string. */
|
|
569
|
+
declare function toDxf(scene: Scene): string;
|
|
570
|
+
|
|
402
571
|
/**
|
|
403
|
-
*
|
|
404
|
-
*
|
|
572
|
+
* PDF export backend — a **true vector** serializer of the {@link Scene}.
|
|
573
|
+
*
|
|
574
|
+
* Walks the Scene's positioned primitives into pdfkit drawing ops, so strokes
|
|
575
|
+
* are real vector paths and text is selectable (no SVG rasterization round-trip).
|
|
576
|
+
* `pdfkit` is an OPTIONAL dependency, lazy-`import()`ed so the zero-dep core never
|
|
577
|
+
* hard-requires it; a clear error is thrown if it is absent. Async + Node-oriented
|
|
578
|
+
* — NOT part of `compile()`. Build a Scene with `toScene(ir)` or `compile().scene`.
|
|
579
|
+
*
|
|
580
|
+
* Coordinates: ArchLang is mm, top-left origin, +y down — pdfkit's user space is
|
|
581
|
+
* the same orientation, so we map the viewBox by translating by its top-left and
|
|
582
|
+
* treat 1mm as 1pt (as the previous SVG-based exporter did with `assumePt`).
|
|
583
|
+
*
|
|
584
|
+
* Page chrome (north arrow, scale bar, title block) is drawn with PDF-native
|
|
585
|
+
* helpers to keep parity with the SVG output. This duplicates the chrome geometry
|
|
586
|
+
* (also in `backends/svg.ts`) — a deliberate, bounded cost until chrome itself
|
|
587
|
+
* moves into the Scene in a later phase. Hatch patterns are SVG-specific, so
|
|
588
|
+
* poché regions fill with the solid poché base colour in PDF.
|
|
405
589
|
*/
|
|
406
|
-
|
|
590
|
+
|
|
591
|
+
/** Convert a {@link Scene} to a vector PDF (Uint8Array). Requires optional `pdfkit`. */
|
|
592
|
+
declare function toPdf(scene: Scene): Promise<Uint8Array>;
|
|
407
593
|
|
|
408
594
|
/**
|
|
409
595
|
* ArchLang — compile declarative floor-plan source to a professional SVG.
|
|
@@ -417,4 +603,4 @@ declare function compile(source: string, opts?: CompileOptions): CompileResult;
|
|
|
417
603
|
/** Clear the internal compile cache (useful in long-lived processes/tests). */
|
|
418
604
|
declare function clearCache(): void;
|
|
419
605
|
|
|
420
|
-
export { type AstElement, type ColumnNode, type CompileError, type CompileOptions, type CompileResult, type CompileWarning, type ComponentDef, type Diagnostic, type DimNode, type DoorNode, type ElementKind, type ExprPoint, type FurnitureNode, type InstanceNode, type LetNode, type NodeBase, type NorthDir, type PlanNode, type Point, type RColumn, type RDim, type RDoor, type RFurniture, type RRoom, type RWall, type RWindow, type ResolvedElement, type ResolvedPlan, type RoomNode, type Severity, type Span, type Statement, type TitleNode, type WallNode, type WindowNode, clearCache, compile, formatDiagnostic, offsetToLineCol, resolve, toDxf, toPdf };
|
|
606
|
+
export { type AstElement, type ColumnNode, type CompileError, type CompileOptions, type CompileResult, type CompileWarning, type ComponentDef, type Diagnostic, type DimNode, type DoorNode, type ElementKind, type ExprPoint, type FurnitureNode, type InstanceNode, type LetNode, type NodeBase, type NorthDir, type Paint, type PlanNode, type Point, type RColumn, type RDim, type RDoor, type RFurniture, type RRoom, type RWall, type RWindow, type RenderPass, type RenderSizes, type ResolvedElement, type ResolvedPlan, type RoomNode, type Scene, type SceneNode, type ScenePrim, type Severity, type Span, type Statement, type TitleNode, type WallNode, type WindowNode, clearCache, compile, formatDiagnostic, offsetToLineCol, resolve, toDxf, toPdf, toScene };
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,9 @@ import {
|
|
|
5
5
|
offsetToLineCol,
|
|
6
6
|
resolve,
|
|
7
7
|
toDxf,
|
|
8
|
-
toPdf
|
|
9
|
-
|
|
8
|
+
toPdf,
|
|
9
|
+
toScene
|
|
10
|
+
} from "./chunk-CPK5CI5Y.js";
|
|
10
11
|
export {
|
|
11
12
|
clearCache,
|
|
12
13
|
compile,
|
|
@@ -14,6 +15,7 @@ export {
|
|
|
14
15
|
offsetToLineCol,
|
|
15
16
|
resolve,
|
|
16
17
|
toDxf,
|
|
17
|
-
toPdf
|
|
18
|
+
toPdf,
|
|
19
|
+
toScene
|
|
18
20
|
};
|
|
19
21
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chanmeng666/archlang",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A small declarative language that compiles to professional SVG floor plans — like Typst/LaTeX, but for architecture.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"architecture",
|
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
"vscode-textmate": "^9.3.2"
|
|
67
67
|
},
|
|
68
68
|
"optionalDependencies": {
|
|
69
|
-
"pdfkit": "^0.15.2"
|
|
70
|
-
"svg-to-pdfkit": "^0.1.8"
|
|
69
|
+
"pdfkit": "^0.15.2"
|
|
71
70
|
}
|
|
72
71
|
}
|