Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions packages/core/src/examples/custom-font-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bun
import { createCliRenderer, ASCIIFontRenderable, BoxRenderable, fonts, type FontDefinition } from ".."

// Example of importing an external font
// Users would do: import hugeFont from "./fonts/huge.json"
// For demo, we'll use the built-in fonts and show how to use custom ones

async function main() {
const renderer = await createCliRenderer({
exitOnCtrlC: true,
useMouse: true,
useAlternateScreen: true,
})

const container = new BoxRenderable("container", {
width: "100%",
height: "100%",
borderStyle: "rounded",
borderColor: "#3498db",
padding: 2,
flexDirection: "column",
gap: 2,
})

// Using built-in font (default)
const title1 = new ASCIIFontRenderable("title1", {
text: "TINY FONT",
font: fonts.tiny, // Explicitly passing FontDefinition
fg: "#ffffff",
})

// Using different built-in font
const title2 = new ASCIIFontRenderable("title2", {
text: "BLOCK",
font: fonts.block,
fg: "#00ff00",
})

// Using another built-in font
const title3 = new ASCIIFontRenderable("title3", {
text: "SHADE",
font: fonts.shade,
fg: "#ff00ff",
})

// Using slick font
const title4 = new ASCIIFontRenderable("title4", {
text: "SLICK",
font: fonts.slick,
fg: "#ffff00",
})

// Example of how users would use custom fonts:
// import customFont from "./my-custom-font.json"
// const customTitle = new ASCIIFontRenderable("custom", {
// text: "CUSTOM",
// font: customFont as FontDefinition,
// fg: "#00ffff",
// })

container.add(title1)
container.add(title2)
container.add(title3)
container.add(title4)

renderer.root.add(container)
renderer.start()

// Exit on escape
renderer.on("key", (key) => {
if (key.name === "escape") {
renderer.destroy()
process.exit(0)
}
})
}

main().catch(console.error)
53 changes: 53 additions & 0 deletions packages/core/src/examples/external-font-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bun
import { createCliRenderer, ASCIIFontRenderable, BoxRenderable, fonts, type FontDefinition } from ".."

// Import external font - demonstrating how users can add custom fonts
import gridFont from "./grid-font.json"

async function main() {
const renderer = await createCliRenderer({
exitOnCtrlC: true,
useMouse: true,
useAlternateScreen: true,
})

const container = new BoxRenderable("container", {
width: "100%",
height: "100%",
borderStyle: "rounded",
borderColor: "#3498db",
padding: 2,
flexDirection: "column",
gap: 2,
})

// Using built-in font
const title1 = new ASCIIFontRenderable("title1", {
text: "BUILT-IN",
font: fonts.block,
fg: "#00ff00",
})

// Using external font loaded from JSON file
const title2 = new ASCIIFontRenderable("title2", {
text: "CUSTOM",
font: gridFont as FontDefinition,
fg: "#ff00ff",
})

container.add(title1)
container.add(title2)

renderer.root.add(container)
renderer.start()

// Exit on escape
renderer.on("key", (key) => {
if (key.name === "escape") {
renderer.destroy()
process.exit(0)
}
})
}

main().catch(console.error)
133 changes: 133 additions & 0 deletions packages/core/src/examples/font-validation-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env bun
import { createCliRenderer, ASCIIFontRenderable, BoxRenderable, type FontDefinition, validateFontDefinition } from ".."

// Test invalid font definitions
const invalidFonts = [
{
name: "Missing lines",
font: {
name: "invalid1",
letterspace_size: 1,
letterspace: [" "],
chars: { "A": ["A"] }
}
},
{
name: "Wrong letterspace length",
font: {
name: "invalid2",
lines: 2,
letterspace_size: 1,
letterspace: [" "], // Should be 2 items
chars: { "A": ["▄", "█"] }
}
},
{
name: "Character line count mismatch",
font: {
name: "invalid3",
lines: 2,
letterspace_size: 1,
letterspace: [" ", " "],
chars: { "A": ["▄"] } // Should have 2 lines
}
},
{
name: "Invalid colors",
font: {
name: "invalid4",
lines: 1,
letterspace_size: 1,
letterspace: [" "],
colors: -1, // Must be positive
chars: { "A": ["A"] }
}
}
]

// Valid font definition
const validFont: FontDefinition = {
name: "valid",
lines: 2,
letterspace_size: 1,
letterspace: [" ", " "],
chars: {
"T": ["▀█▀", " █ "],
"E": ["█▀▀", "██▄"],
"S": ["█▀▀", "▄▄█"],
" ": [" ", " "]
}
}

async function main() {
console.log("Testing font validation...\n")

// Test invalid fonts
for (const { name, font } of invalidFonts) {
try {
validateFontDefinition(font)
console.log(`❌ ${name}: Should have failed but didn't`)
} catch (error) {
console.log(`✅ ${name}: Correctly rejected - ${error.message}`)
}
}

// Test valid font
try {
validateFontDefinition(validFont)
console.log(`✅ Valid font: Correctly accepted`)
} catch (error) {
console.log(`❌ Valid font: Should have passed but failed - ${error.message}`)
}

console.log("\nTesting ASCIIFontRenderable with invalid font...")

const renderer = await createCliRenderer({
exitOnCtrlC: true,
useAlternateScreen: true,
})

const container = new BoxRenderable("container", {
width: "100%",
height: "100%",
padding: 2,
flexDirection: "column",
gap: 2,
})

// This should work - valid font
try {
const validText = new ASCIIFontRenderable("valid", {
text: "TEST",
font: validFont,
fg: "#00ff00"
})
container.add(validText)
console.log("✅ ASCIIFontRenderable accepted valid font")
} catch (error) {
console.log(`❌ ASCIIFontRenderable rejected valid font: ${error.message}`)
}

// This should fail - invalid font
try {
const invalidText = new ASCIIFontRenderable("invalid", {
text: "FAIL",
font: invalidFonts[0].font as FontDefinition,
fg: "#ff0000"
})
container.add(invalidText)
console.log("❌ ASCIIFontRenderable accepted invalid font")
} catch (error) {
console.log(`✅ ASCIIFontRenderable correctly rejected invalid font`)
}

renderer.root.add(container)
renderer.start()

setTimeout(() => {
renderer.destroy()
process.exit(0)
}, 2000)
}

main().catch(console.error)
Loading