mirror of
https://github.com/voson-wang/toon.git
synced 2026-01-29 23:34:10 +08:00
refactor: encoder functions deduplications
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
|||||||
parseKeyToken,
|
parseKeyToken,
|
||||||
parsePrimitiveToken,
|
parsePrimitiveToken,
|
||||||
} from './parser'
|
} from './parser'
|
||||||
import { findClosingQuote } from './string-utils'
|
import { findClosingQuote } from './utils'
|
||||||
import {
|
import {
|
||||||
assertExpectedCount,
|
assertExpectedCount,
|
||||||
validateNoExtraListItems,
|
validateNoExtraListItems,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
TAB,
|
TAB,
|
||||||
TRUE_LITERAL,
|
TRUE_LITERAL,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
import { findClosingQuote, hasUnquotedChar } from './string-utils'
|
import { findClosingQuote, hasUnquotedChar } from './utils'
|
||||||
|
|
||||||
// #region Array header parsing
|
// #region Array header parsing
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {
|
|||||||
JsonValue,
|
JsonValue,
|
||||||
ResolvedEncodeOptions,
|
ResolvedEncodeOptions,
|
||||||
} from './types'
|
} from './types'
|
||||||
import { LIST_ITEM_MARKER, LIST_ITEM_PREFIX } from './constants'
|
import { LIST_ITEM_MARKER } from './constants'
|
||||||
import {
|
import {
|
||||||
isArrayOfArrays,
|
isArrayOfArrays,
|
||||||
isArrayOfObjects,
|
isArrayOfObjects,
|
||||||
@@ -95,7 +95,8 @@ export function encodeArray(
|
|||||||
|
|
||||||
// Primitive array
|
// Primitive array
|
||||||
if (isArrayOfPrimitives(value)) {
|
if (isArrayOfPrimitives(value)) {
|
||||||
encodeInlinePrimitiveArray(key, value, writer, depth, options)
|
const formatted = encodeInlineArrayLine(value, options.delimiter, key, options.lengthMarker)
|
||||||
|
writer.push(depth, formatted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,21 +127,6 @@ export function encodeArray(
|
|||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Primitive array encoding (inline)
|
|
||||||
|
|
||||||
export function encodeInlinePrimitiveArray(
|
|
||||||
prefix: string | undefined,
|
|
||||||
values: readonly JsonPrimitive[],
|
|
||||||
writer: LineWriter,
|
|
||||||
depth: Depth,
|
|
||||||
options: ResolvedEncodeOptions,
|
|
||||||
): void {
|
|
||||||
const formatted = encodeInlineArrayLine(values, options.delimiter, prefix, options.lengthMarker)
|
|
||||||
writer.push(depth, formatted)
|
|
||||||
}
|
|
||||||
|
|
||||||
// #endregion
|
|
||||||
|
|
||||||
// #region Array of arrays (expanded format)
|
// #region Array of arrays (expanded format)
|
||||||
|
|
||||||
export function encodeArrayOfArraysAsListItems(
|
export function encodeArrayOfArraysAsListItems(
|
||||||
@@ -156,7 +142,7 @@ export function encodeArrayOfArraysAsListItems(
|
|||||||
for (const arr of values) {
|
for (const arr of values) {
|
||||||
if (isArrayOfPrimitives(arr)) {
|
if (isArrayOfPrimitives(arr)) {
|
||||||
const inline = encodeInlineArrayLine(arr, options.delimiter, undefined, options.lengthMarker)
|
const inline = encodeInlineArrayLine(arr, options.delimiter, undefined, options.lengthMarker)
|
||||||
writer.push(depth + 1, `${LIST_ITEM_PREFIX}${inline}`)
|
writer.pushListItem(depth + 1, inline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,21 +244,7 @@ export function encodeMixedArrayAsListItems(
|
|||||||
writer.push(depth, header)
|
writer.push(depth, header)
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (isJsonPrimitive(item)) {
|
encodeListItemValue(item, writer, depth + 1, options)
|
||||||
// Direct primitive as list item
|
|
||||||
writer.push(depth + 1, `${LIST_ITEM_PREFIX}${encodePrimitive(item, options.delimiter)}`)
|
|
||||||
}
|
|
||||||
else if (isJsonArray(item)) {
|
|
||||||
// Direct array as list item
|
|
||||||
if (isArrayOfPrimitives(item)) {
|
|
||||||
const inline = encodeInlineArrayLine(item, options.delimiter, undefined, options.lengthMarker)
|
|
||||||
writer.push(depth + 1, `${LIST_ITEM_PREFIX}${inline}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isJsonObject(item)) {
|
|
||||||
// Object as list item
|
|
||||||
encodeObjectAsListItem(item, writer, depth + 1, options)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,13 +261,13 @@ export function encodeObjectAsListItem(obj: JsonObject, writer: LineWriter, dept
|
|||||||
const firstValue = obj[firstKey]!
|
const firstValue = obj[firstKey]!
|
||||||
|
|
||||||
if (isJsonPrimitive(firstValue)) {
|
if (isJsonPrimitive(firstValue)) {
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${encodedKey}: ${encodePrimitive(firstValue, options.delimiter)}`)
|
writer.pushListItem(depth, `${encodedKey}: ${encodePrimitive(firstValue, options.delimiter)}`)
|
||||||
}
|
}
|
||||||
else if (isJsonArray(firstValue)) {
|
else if (isJsonArray(firstValue)) {
|
||||||
if (isArrayOfPrimitives(firstValue)) {
|
if (isArrayOfPrimitives(firstValue)) {
|
||||||
// Inline format for primitive arrays
|
// Inline format for primitive arrays
|
||||||
const formatted = encodeInlineArrayLine(firstValue, options.delimiter, firstKey, options.lengthMarker)
|
const formatted = encodeInlineArrayLine(firstValue, options.delimiter, firstKey, options.lengthMarker)
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${formatted}`)
|
writer.pushListItem(depth, formatted)
|
||||||
}
|
}
|
||||||
else if (isArrayOfObjects(firstValue)) {
|
else if (isArrayOfObjects(firstValue)) {
|
||||||
// Check if array of objects can use tabular format
|
// Check if array of objects can use tabular format
|
||||||
@@ -303,12 +275,12 @@ export function encodeObjectAsListItem(obj: JsonObject, writer: LineWriter, dept
|
|||||||
if (header) {
|
if (header) {
|
||||||
// Tabular format for uniform arrays of objects
|
// Tabular format for uniform arrays of objects
|
||||||
const headerStr = formatHeader(firstValue.length, { key: firstKey, fields: header, delimiter: options.delimiter, lengthMarker: options.lengthMarker })
|
const headerStr = formatHeader(firstValue.length, { key: firstKey, fields: header, delimiter: options.delimiter, lengthMarker: options.lengthMarker })
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${headerStr}`)
|
writer.pushListItem(depth, headerStr)
|
||||||
writeTabularRows(firstValue, header, writer, depth + 1, options)
|
writeTabularRows(firstValue, header, writer, depth + 1, options)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Fall back to list format for non-uniform arrays of objects
|
// Fall back to list format for non-uniform arrays of objects
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${encodedKey}[${firstValue.length}]:`)
|
writer.pushListItem(depth, `${encodedKey}[${firstValue.length}]:`)
|
||||||
for (const item of firstValue) {
|
for (const item of firstValue) {
|
||||||
encodeObjectAsListItem(item, writer, depth + 1, options)
|
encodeObjectAsListItem(item, writer, depth + 1, options)
|
||||||
}
|
}
|
||||||
@@ -316,30 +288,21 @@ export function encodeObjectAsListItem(obj: JsonObject, writer: LineWriter, dept
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Complex arrays on separate lines (array of arrays, etc.)
|
// Complex arrays on separate lines (array of arrays, etc.)
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${encodedKey}[${firstValue.length}]:`)
|
writer.pushListItem(depth, `${encodedKey}[${firstValue.length}]:`)
|
||||||
|
|
||||||
// Encode array contents at depth + 1
|
// Encode array contents at depth + 1
|
||||||
for (const item of firstValue) {
|
for (const item of firstValue) {
|
||||||
if (isJsonPrimitive(item)) {
|
encodeListItemValue(item, writer, depth + 1, options)
|
||||||
writer.push(depth + 1, `${LIST_ITEM_PREFIX}${encodePrimitive(item, options.delimiter)}`)
|
|
||||||
}
|
|
||||||
else if (isJsonArray(item) && isArrayOfPrimitives(item)) {
|
|
||||||
const inline = encodeInlineArrayLine(item, options.delimiter, undefined, options.lengthMarker)
|
|
||||||
writer.push(depth + 1, `${LIST_ITEM_PREFIX}${inline}`)
|
|
||||||
}
|
|
||||||
else if (isJsonObject(item)) {
|
|
||||||
encodeObjectAsListItem(item, writer, depth + 1, options)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isJsonObject(firstValue)) {
|
else if (isJsonObject(firstValue)) {
|
||||||
const nestedKeys = Object.keys(firstValue)
|
const nestedKeys = Object.keys(firstValue)
|
||||||
if (nestedKeys.length === 0) {
|
if (nestedKeys.length === 0) {
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${encodedKey}:`)
|
writer.pushListItem(depth, `${encodedKey}:`)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writer.push(depth, `${LIST_ITEM_PREFIX}${encodedKey}:`)
|
writer.pushListItem(depth, `${encodedKey}:`)
|
||||||
encodeObject(firstValue, writer, depth + 2, options)
|
encodeObject(firstValue, writer, depth + 2, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,3 +315,25 @@ export function encodeObjectAsListItem(obj: JsonObject, writer: LineWriter, dept
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
// #region List item encoding helpers
|
||||||
|
|
||||||
|
function encodeListItemValue(
|
||||||
|
value: JsonValue,
|
||||||
|
writer: LineWriter,
|
||||||
|
depth: Depth,
|
||||||
|
options: ResolvedEncodeOptions,
|
||||||
|
): void {
|
||||||
|
if (isJsonPrimitive(value)) {
|
||||||
|
writer.pushListItem(depth, encodePrimitive(value, options.delimiter))
|
||||||
|
}
|
||||||
|
else if (isJsonArray(value) && isArrayOfPrimitives(value)) {
|
||||||
|
const inline = encodeInlineArrayLine(value, options.delimiter, undefined, options.lengthMarker)
|
||||||
|
writer.pushListItem(depth, inline)
|
||||||
|
}
|
||||||
|
else if (isJsonObject(value)) {
|
||||||
|
encodeObjectAsListItem(value, writer, depth, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import type {
|
|||||||
} from './types'
|
} from './types'
|
||||||
import { DEFAULT_DELIMITER } from './constants'
|
import { DEFAULT_DELIMITER } from './constants'
|
||||||
import { decodeValueFromLines } from './decode/decoders'
|
import { decodeValueFromLines } from './decode/decoders'
|
||||||
|
import { LineCursor, toParsedLines } from './decode/scanner'
|
||||||
import { encodeValue } from './encoders'
|
import { encodeValue } from './encoders'
|
||||||
import { normalizeValue } from './normalize'
|
import { normalizeValue } from './normalize'
|
||||||
import { LineCursor, toParsedLines } from './decode/scanner'
|
|
||||||
|
|
||||||
export { DEFAULT_DELIMITER, DELIMITERS } from './constants'
|
export { DEFAULT_DELIMITER, DELIMITERS } from './constants'
|
||||||
export type {
|
export type {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Depth } from './types'
|
import type { Depth } from './types'
|
||||||
|
import { LIST_ITEM_PREFIX } from './constants'
|
||||||
|
|
||||||
export class LineWriter {
|
export class LineWriter {
|
||||||
private readonly lines: string[] = []
|
private readonly lines: string[] = []
|
||||||
@@ -13,6 +14,10 @@ export class LineWriter {
|
|||||||
this.lines.push(indent + content)
|
this.lines.push(indent + content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushListItem(depth: Depth, content: string): void {
|
||||||
|
this.push(depth, `${LIST_ITEM_PREFIX}${content}`)
|
||||||
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return this.lines.join('\n')
|
return this.lines.join('\n')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user