@knitting-tools/core 2.0.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/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # @knitting-tools/core
2
+
3
+ A knitting pattern engine for expanding rows, applying shaping, and compiling pattern DSL.
4
+
5
+ ## What it includes
6
+
7
+ - Expand repeat-based row definitions
8
+ - Evenly distribute increases/decreases
9
+ - Apply physical shaping to stitch streams
10
+ - Compile simple knitting DSL
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pnpm add @knitting-tools/core
16
+ ```
17
+
18
+ ## Quick example
19
+
20
+ ```ts
21
+ import {
22
+ compilePattern,
23
+ compileRowDsl,
24
+ parseRowDsl,
25
+ rowToRowDsl,
26
+ } from "@knitting-tools/core";
27
+
28
+ const row = parseRowDsl("[k1]s (k2 p2) p1 [k1]e");
29
+ const normalised = rowToRowDsl(row);
30
+ const stitches = compileRowDsl(normalised, 10);
31
+
32
+ const compiled = compilePattern(
33
+ {
34
+ rows: [row],
35
+ },
36
+ 10
37
+ );
38
+
39
+ console.log(stitches.length);
40
+ console.log(compiled.rows[0].normalisedRowDsl);
41
+ ```
42
+
43
+ ## Development
44
+
45
+ Run from the repository root:
46
+
47
+ ```bash
48
+ pnpm --dir packages/knitting-math typecheck
49
+ pnpm --dir packages/knitting-math test
50
+ pnpm --dir packages/knitting-math test:coverage
51
+ pnpm --dir packages/knitting-math check
52
+ ```
53
+
54
+ ## API Stability & Breaking Changes
55
+
56
+ This package follows [Semantic Versioning](https://semver.org/). The public API surface is locked in with snapshot tests. Any change to exports, types, or function signatures will cause tests to fail, ensuring breaking changes are intentional and documented.
57
+
58
+ **Quick links:**
59
+ - [API Compatibility Policy](./API_COMPATIBILITY.md) — Detailed policy on versioning and breaking changes
60
+ - [API Quick Reference](./API_COMPATIBILITY_QUICK_REF.md) — Commands and workflows for development
61
+ - [Test Snapshots](./src/__snapshots__/api.compatibility.test.ts.snap) — Current API surface
62
+
63
+ **Key principle**: Breaking changes require a major version bump and must be documented in Changesets before release.
64
+
65
+ ## Release flow
66
+
67
+ Package releases are managed with Changesets from the repository root:
68
+
69
+ ```bash
70
+ pnpm changeset
71
+ pnpm release:status
72
+ pnpm release:version
73
+ pnpm release:publish
74
+ ```
75
+
76
+ See the repository README for the wider monorepo workflow.
@@ -0,0 +1,480 @@
1
+ declare const INCH_TO_CM: number;
2
+ declare const CM_TO_INCH: number;
3
+ declare const MM_TO_CM: number;
4
+ declare const CM_TO_MM: number;
5
+
6
+ type UnitSystem = "imperial" | "metric";
7
+ interface MetricGauge {
8
+ rowsPer10cm: number;
9
+ stitchesPer10cm: number;
10
+ unit: "metric";
11
+ }
12
+ interface ImperialGauge {
13
+ rowsPer4in: number;
14
+ stitchesPer4in: number;
15
+ unit: "imperial";
16
+ }
17
+ type Gauge = MetricGauge | ImperialGauge;
18
+ /**
19
+ * Get the number of stitches per centimeter based on the gauge.
20
+ *
21
+ * @param gauge - The gauge information.
22
+ * @returns The number of stitches per centimeter.
23
+ */
24
+ declare function stitchesPerCm(gauge: Gauge): number;
25
+ /**
26
+ * Get the number of rows per centimeter based on the gauge.
27
+ *
28
+ * @param gauge - The gauge information.
29
+ * @returns The number of rows per centimeter.
30
+ */
31
+ declare function rowsPerCm(gauge: Gauge): number;
32
+
33
+ /**
34
+ * Convert a centimetre measurement into a rounded stitch count for the given gauge.
35
+ *
36
+ * @param cm - The measurement in centimetres.
37
+ * @param gauge - The gauge definition used for conversion.
38
+ * @returns The nearest whole-number stitch count.
39
+ */
40
+ declare function cmToStitches(cm: number, gauge: Gauge): number;
41
+ /**
42
+ * Convert a centimetre measurement into a rounded row count for the given gauge.
43
+ *
44
+ * @param cm - The measurement in centimetres.
45
+ * @param gauge - The gauge definition used for conversion.
46
+ * @returns The nearest whole-number row count.
47
+ */
48
+ declare function cmToRows(cm: number, gauge: Gauge): number;
49
+
50
+ /**
51
+ * Convert a length value between centimeters and inches.
52
+ *
53
+ * @param value - The length value to convert.
54
+ * @param from - The unit of the input value ("cm" or "in").
55
+ * @param to - The unit to convert to ("cm" or "in").
56
+ * @returns The converted length value.
57
+ */
58
+ declare function convertLength(value: number, from: "cm" | "in", to: "cm" | "in"): number;
59
+ /**
60
+ * Normalise a length measurement to centimeters.
61
+ *
62
+ * @param value - The length value to normalise.
63
+ * @param unit - The unit of the input value ("cm" or "in").
64
+ * @returns The normalised length value in centimeters.
65
+ */
66
+ declare function normaliseMeasurement(value: number, unit: "cm" | "in"): number;
67
+ /**
68
+ * Round a number of stitches to the nearest whole number.
69
+ *
70
+ * @param stitches - The number of stitches to round.
71
+ * @returns The rounded number of stitches.
72
+ */
73
+ declare function roundStitches(stitches: number): number;
74
+
75
+ type StitchType = "knit" | "purl" | "decrease" | "increase";
76
+ type StitchVariant = "inv-l" | "inv-r" | "k1-b" | "k2tog" | "kfb" | "kfbf" | "m1" | "p1-b" | "p2tog" | "pfb" | "psso" | "s2kp" | "sk2p" | "skp" | "sl" | "sl1" | "slip" | "ssp" | "ssk" | "tbl" | "yfon" | "yfrn" | "yo" | "yon" | "yrn";
77
+ type StitchVariantParameterValue = boolean | number | string;
78
+ type StitchVariantParameters = Record<string, StitchVariantParameterValue>;
79
+ interface ShapingElement {
80
+ count: number;
81
+ direction?: "centre" | "left" | "right";
82
+ shapingType: "decrease" | "increase";
83
+ /**
84
+ * The ground stitch type this shaping operates on.
85
+ * When provided, `createInstructionFromShaping` may infer purl-side variants
86
+ * (e.g. `p2tog`, `ssp`) rather than defaulting to knit-side variants.
87
+ */
88
+ stitch?: "knit" | "purl";
89
+ type: "shaping";
90
+ variant?: StitchVariant;
91
+ variantParameters?: StitchVariantParameters;
92
+ }
93
+ type EdgeElement = ShapingElement | StitchInstruction;
94
+ type RowElement = ShapingElement | StitchInstruction | RepeatBlock;
95
+ interface StitchInstruction {
96
+ count: number;
97
+ type: StitchType;
98
+ variant?: StitchVariant;
99
+ variantParameters?: StitchVariantParameters;
100
+ }
101
+ type RepeatBlock = {
102
+ allowPartial?: never;
103
+ maxRepeats?: never;
104
+ remainingStitches?: never;
105
+ sequence: RowElement[];
106
+ times: number;
107
+ toEnd?: never;
108
+ targetStitches?: never;
109
+ type: "repeat";
110
+ } | {
111
+ allowPartial?: boolean;
112
+ maxRepeats?: number;
113
+ remainingStitches?: never;
114
+ sequence: RowElement[];
115
+ times?: never;
116
+ toEnd: true;
117
+ targetStitches?: never;
118
+ type: "repeat";
119
+ } | {
120
+ allowPartial?: never;
121
+ maxRepeats?: number;
122
+ remainingStitches?: never;
123
+ sequence: RowElement[];
124
+ times?: never;
125
+ toEnd?: never;
126
+ targetStitches: number;
127
+ type: "repeat";
128
+ } | {
129
+ allowPartial?: never;
130
+ maxRepeats?: number;
131
+ remainingStitches: number;
132
+ sequence: RowElement[];
133
+ times?: never;
134
+ toEnd?: never;
135
+ targetStitches?: never;
136
+ type: "repeat";
137
+ };
138
+ interface Row {
139
+ edgeEnd?: EdgeElement[];
140
+ edgeStart?: EdgeElement[];
141
+ elements: RowElement[];
142
+ }
143
+ /**
144
+ * Expand a row into a full list of stitch instructions based on the total number of stitches.
145
+ *
146
+ * Internal contract (lightweight):
147
+ * - never mutates input
148
+ * - never consumes more source stitches than totalStitches
149
+ * - deterministic output for identical inputs
150
+ * - throws on invalid structure
151
+ *
152
+ * @param row - The row to expand.
153
+ * @param totalStitches - The total number of stitches in the row.
154
+ * @returns An array of stitch instructions representing the expanded row.
155
+ */
156
+ declare function expandRow(row: Row, totalStitches: number): StitchInstruction[];
157
+ /**
158
+ * Expand a row into a full list of stitch instructions based on the total number of stitches,
159
+ * then compress consecutive stitches of the same type into single instructions with counts.
160
+ *
161
+ * @param row - The row to expand and compress.
162
+ * @param totalStitches - The total number of stitches in the row.
163
+ * @returns An array of stitch instructions representing the expanded and compressed row.
164
+ */
165
+ declare function expandRowToStitches(row: Row, totalStitches: number): StitchInstruction[];
166
+ /**
167
+ * Count the total number of stitches represented by compressed stitch instructions.
168
+ *
169
+ * @param instructions - Instructions to total.
170
+ * @returns The summed stitch count.
171
+ */
172
+ declare function countStitchesInInstructions(instructions: ReadonlyArray<Pick<StitchInstruction, "count">>): number;
173
+ /**
174
+ * Expand a row into a full list of stitch types based on the total number of stitches.
175
+ *
176
+ * @param row - The row to expand.
177
+ * @param totalStitches - The total number of stitches in the row.
178
+ * @returns An array of stitch types representing the expanded row.
179
+ */
180
+ declare function expandRowToStitchTypes(row: Row, totalStitches: number): StitchType[];
181
+
182
+ /**
183
+ * Pattern interface with optional row repeats.
184
+ */
185
+ interface Pattern {
186
+ repeatRows?: number;
187
+ rows: Row[];
188
+ }
189
+ /**
190
+ * Result of expanding a single row when shaping is involved.
191
+ */
192
+ interface ShapedRowResult {
193
+ outputStitches: number;
194
+ stitches: StitchInstruction[];
195
+ }
196
+ type PatternCompileMode = "fixed" | "shaped";
197
+ interface CompilePatternOptions {
198
+ mode?: PatternCompileMode;
199
+ }
200
+ interface RowShapingOperation {
201
+ count: number;
202
+ direction?: "centre" | "left" | "right";
203
+ shapingType: "decrease" | "increase";
204
+ variant?: StitchVariant;
205
+ }
206
+ interface CompiledPatternRow {
207
+ carriedStitches: number;
208
+ hasShaping: boolean;
209
+ inputStitches: number;
210
+ normalisedRowDsl: string;
211
+ outputStitches: number;
212
+ repeatIndex: number;
213
+ rowNumber: number;
214
+ shapingOperations: RowShapingOperation[];
215
+ sourceRowIndex: number;
216
+ stitchDelta: number;
217
+ stitches: StitchInstruction[];
218
+ }
219
+ interface CompiledPattern {
220
+ finalStitches: number;
221
+ initialStitches: number;
222
+ mode: PatternCompileMode;
223
+ rows: CompiledPatternRow[];
224
+ }
225
+ /**
226
+ * Example helper: create a repeat block row
227
+ */
228
+ declare function createRepeatRow(sequence: Row["elements"], times: number): Row;
229
+
230
+ declare function compilePattern(pattern: Pattern, initialStitches: number, options?: CompilePatternOptions): CompiledPattern;
231
+ declare function expandPattern(pattern: Pattern, stitchesPerRow: number): StitchInstruction[][];
232
+ declare function shapedExpandPattern(pattern: Pattern, initialStitches: number): StitchInstruction[][];
233
+ declare function printPattern(pattern: Pattern, stitchesPerRow: number): void;
234
+
235
+ type KnittingStyle = "flat" | "in-the-round";
236
+ type LengthUnit = "cm" | "in";
237
+ interface CastOnInput {
238
+ ease?: number;
239
+ easeUnit?: LengthUnit;
240
+ gauge: Gauge;
241
+ size: number;
242
+ style: KnittingStyle;
243
+ unit: LengthUnit;
244
+ }
245
+ /**
246
+ * Calculate the number of stitches to cast on based on the size and gauge.
247
+ *
248
+ * @param input - The input parameters for the cast-on calculation.
249
+ * @returns The number of stitches to cast on.
250
+ */
251
+ declare function calculateCastOn(input: CastOnInput): number;
252
+ /**
253
+ * Calculate the number of stitches to cast on based on the size, gauge, and ease.
254
+ *
255
+ * @param input - The input parameters for the cast-on calculation.
256
+ * @returns The number of stitches to cast on.
257
+ */
258
+ declare function calculateCastOnStitches(input: CastOnInput): number;
259
+
260
+ type KnittingMathErrorCode = "EXPANSION_ERROR" | "PARSE_ERROR" | "VALIDATION_ERROR";
261
+ interface KnittingMathErrorContext {
262
+ [key: string]: boolean | number | string | undefined;
263
+ }
264
+ declare abstract class KnittingMathError extends Error {
265
+ readonly code: KnittingMathErrorCode;
266
+ readonly context?: KnittingMathErrorContext;
267
+ protected constructor(name: string, code: KnittingMathErrorCode, message: string, context?: KnittingMathErrorContext, cause?: unknown);
268
+ }
269
+ declare class KnittingMathParseError extends KnittingMathError {
270
+ constructor(message: string, context?: KnittingMathErrorContext, cause?: unknown);
271
+ }
272
+ declare class KnittingMathValidationError extends KnittingMathError {
273
+ constructor(message: string, context?: KnittingMathErrorContext, cause?: unknown);
274
+ }
275
+ declare class KnittingMathExpansionError extends KnittingMathError {
276
+ constructor(message: string, context?: KnittingMathErrorContext, cause?: unknown);
277
+ }
278
+ declare function ensureKnittingMathError<TError extends KnittingMathError>(error: unknown, createError: (message: string, cause?: unknown) => TError): TError;
279
+
280
+ interface ResolveOptions {
281
+ /**
282
+ * When true, unknown tokens throw a descriptive error instead of returning null.
283
+ */
284
+ throwOnUnknown?: boolean;
285
+ }
286
+ interface StitchRegistry {
287
+ /**
288
+ * Get the default count for a variant, or 1 if not registered.
289
+ */
290
+ getDefaultCount(variant: string): number;
291
+ /**
292
+ * Check if a token is registered.
293
+ */
294
+ isKnown(token: string): boolean;
295
+ /**
296
+ * Check if a variant locks its count.
297
+ */
298
+ isLockedCountVariant(variant: string): boolean;
299
+ /**
300
+ * Check if a token is specifically a variant abbreviation (not a type alias).
301
+ */
302
+ isVariant(token: string): boolean;
303
+ /**
304
+ * Register a stitch abbreviation (short-form variant token).
305
+ * Example: registerAbbreviation("yo", "increase")
306
+ */
307
+ registerAbbreviation(abbreviation: string, canonicalType: StitchType): void;
308
+ /**
309
+ * Register a stitch variant with default count.
310
+ * Example: registerDefaultCount("k1b", 1)
311
+ */
312
+ registerDefaultCount(variant: string, count: number): void;
313
+ /**
314
+ * Register a variant that locks its count (rejects explicit count suffix).
315
+ * Example: registerLockedCountVariant("k1b")
316
+ */
317
+ registerLockedCountVariant(variant: string): void;
318
+ /**
319
+ * Register a stitch type alias (long form).
320
+ * Example: registerType("knit", "k")
321
+ */
322
+ registerType(alias: string, canonicalType: StitchType): void;
323
+ /**
324
+ * Resolve a token to its canonical stitch type.
325
+ * Returns null if unknown, unless `options.throwOnUnknown` is true.
326
+ * In strict mode the error includes the expected `KnittingPattern::StitchType`
327
+ * tokens and registered abbreviations known to the registry.
328
+ */
329
+ resolve(token: string, options?: ResolveOptions): StitchType | null;
330
+ }
331
+ /**
332
+ * Create a default registry pre-populated with standard stitches.
333
+ */
334
+ declare function createDefaultStitchRegistry(): StitchRegistry;
335
+ /**
336
+ * Create an empty registry for testing.
337
+ * Useful for unit tests that want full control over available stitches.
338
+ */
339
+ declare function createEmptyStitchRegistry(): StitchRegistry;
340
+
341
+ interface RowDslAstEdgeStartElement {
342
+ stitches: EdgeElement[];
343
+ type: "edge-start";
344
+ }
345
+ interface RowDslAstBodyElement {
346
+ elements: RowElement[];
347
+ type: "body";
348
+ }
349
+ interface RowDslAstEdgeEndElement {
350
+ stitches: EdgeElement[];
351
+ type: "edge-end";
352
+ }
353
+ type RowDslAstElement = RowDslAstEdgeStartElement | RowDslAstBodyElement | RowDslAstEdgeEndElement;
354
+ interface RowDslAst {
355
+ elements: RowDslAstElement[];
356
+ }
357
+ /**
358
+ * Non-throwing structural check for AST shape constraints.
359
+ *
360
+ * This helper only validates AST shape invariants:
361
+ * exactly one body node, and at most one edge-start/edge-end node.
362
+ * It does not perform semantic validation of row contents.
363
+ */
364
+ declare function isRowDslAstWellFormed(ast: RowDslAst): boolean;
365
+
366
+ declare function parseRowDsl(input: string, registry?: StitchRegistry): Row;
367
+ declare function parseCompatibleRowDsl(input: string, registry?: StitchRegistry): Row;
368
+ declare function compileRowDsl(input: string, totalStitches: number, registry?: StitchRegistry): StitchInstruction[];
369
+ declare function compileCompatibleRowDsl(input: string, totalStitches: number, registry?: StitchRegistry): StitchInstruction[];
370
+ declare function rowToRowDsl(row: Row): string;
371
+ declare function parseRowDslAst(input: string, registry?: StitchRegistry): RowDslAst;
372
+ declare function parseCompatibleRowDslAst(input: string, registry?: StitchRegistry): RowDslAst;
373
+ declare function resolveRowDslAst(ast: RowDslAst): Row;
374
+
375
+ type ShapingType = "decrease" | "increase";
376
+
377
+ interface ShapeRowInput {
378
+ row: Row;
379
+ shaping: {
380
+ type: ShapingType;
381
+ count: number;
382
+ };
383
+ totalStitches: number;
384
+ }
385
+ interface ShapedStitch {
386
+ isShaping?: boolean;
387
+ operationIndex?: number;
388
+ shapingType?: ShapingType;
389
+ sourceIndex: number;
390
+ type: StitchType;
391
+ }
392
+ interface ShapeRowResult {
393
+ shapedStitches: ShapedStitch[];
394
+ stitches: StitchInstruction[];
395
+ totalStitches: number;
396
+ }
397
+ interface ShapingOperationGroup {
398
+ operationIndex: number;
399
+ outputIndices: number[];
400
+ shapingType: ShapingType;
401
+ sourceIndices: number[];
402
+ stitches: ShapedStitch[];
403
+ }
404
+
405
+ type ShapingDslParseResult = ShapeRowInput;
406
+ type ShapingDslElement = {
407
+ row: Row;
408
+ type: "row";
409
+ } | {
410
+ shapingCount: number;
411
+ shapingType: ShapingType;
412
+ type: "shaping";
413
+ } | {
414
+ totalStitches: number;
415
+ type: "total";
416
+ };
417
+ interface ShapingDslAst {
418
+ elements: ShapingDslElement[];
419
+ }
420
+
421
+ interface ShapingDebugLine {
422
+ legend: string;
423
+ markers: string;
424
+ row: string;
425
+ }
426
+ interface ShapingDebugOptions {
427
+ /**
428
+ * Width of each stitch cell in characters.
429
+ * Defaults to 1.
430
+ */
431
+ cellWidth?: number;
432
+ /**
433
+ * Symbol rendered in the marker line beneath a shaping operation.
434
+ * Defaults to "^".
435
+ */
436
+ markerSymbol?: string;
437
+ /**
438
+ * Override symbols for each stitch type in the row line.
439
+ * Merged with the default symbol map.
440
+ */
441
+ symbols?: Partial<Record<ShapingType | "knit" | "purl", string>>;
442
+ }
443
+ /**
444
+ * Render a shaped stitch stream into a pair of diagnostic strings that make
445
+ * shaping placement visible at a glance.
446
+ *
447
+ * Output has three parts:
448
+ * - `row`: one character (or cell) per output stitch, e.g. `K K \ K K \ K K`
449
+ * - `markers`: `^` beneath each shaping stitch to show exact positions
450
+ * - `legend`: a concise key listing each marker's meaning
451
+ *
452
+ * @param shapedStitches - Stitch stream from `shapeRow`.
453
+ * @param options - Optional rendering overrides.
454
+ * @returns An object with `row`, `markers`, and `legend` strings.
455
+ */
456
+ declare function renderShapingDebug(shapedStitches: ShapedStitch[], options?: ShapingDebugOptions): ShapingDebugLine;
457
+ /**
458
+ * Convenience wrapper that shapes a row and renders debug output in one step.
459
+ *
460
+ * @param input - Standard shapeRow input.
461
+ * @param options - Optional rendering overrides.
462
+ * @returns Rendered debug line data.
463
+ */
464
+ declare function renderShapingDebugForInput(input: ShapeRowInput, options?: ShapingDebugOptions): ShapingDebugLine;
465
+ /**
466
+ * Print a shaping debug diagram to the console.
467
+ *
468
+ * @param shapedStitches - Stitch stream from `shapeRow`.
469
+ * @param label - Optional row label printed above the diagram.
470
+ * @param options - Optional rendering overrides.
471
+ */
472
+ declare function printShapingDebug(shapedStitches: ShapedStitch[], label?: string, options?: ShapingDebugOptions): void;
473
+
474
+ declare function parseShapingDslAst(input: string): ShapingDslAst;
475
+ declare function parseShapingDsl(input: string): ShapingDslParseResult;
476
+ declare function compileShapingDsl(input: string): ShapeRowResult;
477
+ declare function shapeRow(input: ShapeRowInput): ShapeRowResult;
478
+ declare function groupShapedStitchesByOperation(shapedStitches: ShapedStitch[]): ShapingOperationGroup[];
479
+
480
+ export { CM_TO_INCH, CM_TO_MM, type CastOnInput, type CompilePatternOptions, type CompiledPattern, type CompiledPatternRow, type EdgeElement, type Gauge, INCH_TO_CM, type ImperialGauge, KnittingMathError, type KnittingMathErrorCode, type KnittingMathErrorContext, KnittingMathExpansionError, KnittingMathParseError, KnittingMathValidationError, MM_TO_CM, type MetricGauge, type Pattern, type PatternCompileMode, type RepeatBlock, type ResolveOptions, type Row, type RowDslAst, type RowDslAstElement, type RowElement, type RowShapingOperation, type ShapeRowInput, type ShapeRowResult, type ShapedRowResult, type ShapedStitch, type ShapingDebugLine, type ShapingDebugOptions, type ShapingDslAst, type ShapingDslElement, type ShapingDslParseResult, type ShapingElement, type ShapingOperationGroup, type StitchInstruction, type StitchRegistry, type StitchType, type StitchVariant, type StitchVariantParameterValue, type StitchVariantParameters, type UnitSystem, calculateCastOn, calculateCastOnStitches, cmToRows, cmToStitches, compileCompatibleRowDsl, compilePattern, compileRowDsl, compileShapingDsl, convertLength, countStitchesInInstructions, createDefaultStitchRegistry, createEmptyStitchRegistry, createRepeatRow, ensureKnittingMathError, expandPattern, expandRow, expandRowToStitchTypes, expandRowToStitches, groupShapedStitchesByOperation, isRowDslAstWellFormed, normaliseMeasurement, parseCompatibleRowDsl, parseCompatibleRowDslAst, parseRowDsl, parseRowDslAst, parseShapingDsl, parseShapingDslAst, printPattern, printShapingDebug, renderShapingDebug, renderShapingDebugForInput, resolveRowDslAst, roundStitches, rowToRowDsl, rowsPerCm, shapeRow, shapedExpandPattern, stitchesPerCm };