Add initial project files
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { ModuleFieldOption } from '#services/module_generator/types'
|
||||
|
||||
interface FieldOption {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface ComboboxOptionGroup {
|
||||
label?: string
|
||||
options: FieldOption[]
|
||||
}
|
||||
|
||||
export interface MultiSelectOptionGroup {
|
||||
heading: string
|
||||
options: FieldOption[]
|
||||
}
|
||||
|
||||
export function hasGroupedOptions(options: ModuleFieldOption[]): boolean {
|
||||
return options.some((option) => option.group?.trim())
|
||||
}
|
||||
|
||||
export function toFlatOptions(options: ModuleFieldOption[]): FieldOption[] {
|
||||
return options.map((option) => ({ label: option.label, value: option.value }))
|
||||
}
|
||||
|
||||
export function toComboboxGroups(options: ModuleFieldOption[]): ComboboxOptionGroup[] {
|
||||
const groups = new Map<string, ComboboxOptionGroup>()
|
||||
|
||||
for (const option of options) {
|
||||
const key = option.group?.trim() ?? ''
|
||||
const group = groups.get(key) ?? { label: key || undefined, options: [] }
|
||||
group.options.push({ label: option.label, value: option.value })
|
||||
groups.set(key, group)
|
||||
}
|
||||
|
||||
return [...groups.values()]
|
||||
}
|
||||
|
||||
export function toMultiSelectOptions(
|
||||
options: ModuleFieldOption[]
|
||||
): FieldOption[] | MultiSelectOptionGroup[] {
|
||||
if (!hasGroupedOptions(options)) {
|
||||
return toFlatOptions(options)
|
||||
}
|
||||
|
||||
return toComboboxGroups(options).map((group) => ({
|
||||
heading: group.label ?? '',
|
||||
options: group.options,
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
type SourceChunk = string | null | false | undefined
|
||||
|
||||
const EMPTY_JSX_TEXT_EXPRESSION_REGEX = /\{\s*'\s*'\s*\}/g
|
||||
|
||||
function normalizeSource(value: string): string {
|
||||
const trimmed = value.replace(/^\n/, '').replace(/\n\s*$/, '')
|
||||
const lines = trimmed.split('\n')
|
||||
const indents = lines
|
||||
.filter((line) => line.trim().length > 0)
|
||||
.map((line) => line.match(/^\s*/)?.[0].length ?? 0)
|
||||
|
||||
const minIndent = indents.length > 0 ? Math.min(...indents) : 0
|
||||
|
||||
return lines
|
||||
.map((line) => line.slice(Math.min(line.match(/^\s*/)?.[0].length ?? 0, minIndent)))
|
||||
.join('\n')
|
||||
.replace(EMPTY_JSX_TEXT_EXPRESSION_REGEX, '')
|
||||
.trim()
|
||||
}
|
||||
|
||||
export function source(value: string): string {
|
||||
return normalizeSource(value)
|
||||
}
|
||||
|
||||
export function indentSource(value: string, spaces: number): string {
|
||||
const prefix = ' '.repeat(spaces)
|
||||
|
||||
return normalizeSource(value)
|
||||
.split('\n')
|
||||
.map((line) => (line.length > 0 ? `${prefix}${line}` : line))
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
export class SourceFile {
|
||||
private readonly imports = new Set<string>()
|
||||
private readonly sections: string[] = []
|
||||
|
||||
addImport(value: SourceChunk): this {
|
||||
if (value) {
|
||||
this.imports.add(normalizeSource(value))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
addImports(values: SourceChunk[]): this {
|
||||
values.forEach((value) => this.addImport(value))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
addSection(value: SourceChunk): this {
|
||||
if (value) {
|
||||
this.sections.push(normalizeSource(value))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return [Array.from(this.imports).join('\n'), this.sections.join('\n\n')]
|
||||
.filter((section) => section.length > 0)
|
||||
.join('\n\n')
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user