@typescript-calendar-lib/cli 0.5.4 → 0.6.1

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 CHANGED
@@ -88,7 +88,7 @@ typescript-calendar-lib --range 2026-01-01 2026-03-31 # months in a date range
88
88
  --color Enable ANSI colors (auto-detected for TTY)
89
89
  --no-color Disable ANSI colors
90
90
  --locale <lang> Language: en | ja | es | de | fr | ko | zh (default: en)
91
- --holiday-locale <lang> Holiday rules: currently only ja (default: ja)
91
+ --holiday-locale <lang> Holiday rules: en | ja | es | de | fr | ko | zh (default: ja)
92
92
  --week-start <day> First weekday: sunday | monday (default: sunday)
93
93
  --week-numbers Print the week number at the start of each row
94
94
  --highlight <YYYY-MM-DD> Highlight a date (e.g. 2026-09-08)
package/dist/bin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { i as ColorSchemeName, s as ThemeName } from "./theme-rvXGNLpG.js";
2
- import { HighlightStyle, Locale, WeekStart } from "@typescript-calendar-lib/core";
2
+ import { HighlightStyle, HolidayLocale, Locale, WeekStart } from "@typescript-calendar-lib/core";
3
3
  //#region src/bin.d.ts
4
4
  export interface CliArgs {
5
5
  year?: number;
@@ -9,7 +9,7 @@ export interface CliArgs {
9
9
  color?: boolean;
10
10
  noColor?: boolean;
11
11
  locale?: Locale;
12
- holidayLocale?: Locale;
12
+ holidayLocale?: HolidayLocale;
13
13
  weekStart?: WeekStart;
14
14
  weekNumbers?: boolean;
15
15
  highlight?: Date;
package/dist/bin.js CHANGED
@@ -187,7 +187,7 @@ Options:
187
187
  --color Enable ANSI colors (auto-detected for TTY)
188
188
  --no-color Disable ANSI colors
189
189
  --locale <lang> Language: ${LOCALE_LIST.join(" | ")} (default: en)
190
- --holiday-locale <lang> Holiday rules: currently only ja (default: ja)
190
+ --holiday-locale <lang> Holiday rules: en | ja | es | de | fr | ko | zh (default: ja)
191
191
  --week-start <day> First weekday: sunday | monday (default: sunday)
192
192
  --week-numbers Print the week number at the start of each row
193
193
  --highlight <YYYY-MM-DD> Highlight a date (e.g. 2026-09-08)
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from \"node:module\";\nimport type {\n HighlightStyle,\n Locale,\n WeekStart,\n} from \"@typescript-calendar-lib/core\";\nimport {\n createDate,\n LOCALES,\n MAX_YEAR,\n MIN_YEAR,\n} from \"@typescript-calendar-lib/core\";\nimport { calendar, calendarRange, calendarYear } from \"./calendar.ts\";\nimport type { ColorSchemeName, ThemeName } from \"./theme.ts\";\n\nexport interface CliArgs {\n year?: number;\n month?: number;\n theme?: ThemeName;\n colorScheme?: ColorSchemeName;\n color?: boolean;\n noColor?: boolean;\n locale?: Locale;\n holidayLocale?: Locale;\n weekStart?: WeekStart;\n weekNumbers?: boolean;\n highlight?: Date;\n highlightStyle?: HighlightStyle;\n today?: Date;\n yearView?: boolean;\n range?: { from: Date; to: Date };\n}\n\nexport interface ParseResult {\n args: CliArgs;\n error?: string;\n help?: boolean;\n version?: boolean;\n}\n\nconst THEMES: readonly ThemeName[] = [\"default\", \"modern\"];\nconst COLOR_SCHEMES: readonly ColorSchemeName[] = [\n \"default\",\n \"ocean\",\n \"forest\",\n \"sunset\",\n \"mono\",\n];\nconst LOCALE_LIST: readonly string[] = Object.keys(LOCALES);\nconst WEEK_STARTS: readonly WeekStart[] = [\"sunday\", \"monday\"];\nconst HIGHLIGHT_STYLES: readonly HighlightStyle[] = [\"bracket\", \"reverse\"];\n\nconst _require = createRequire(import.meta.url);\n\n/** package.json からバージョンを取得する */\nexport function getVersion(): string {\n return (_require(\"../package.json\") as { version: string }).version;\n}\n\n/**\n * CLI フラグ・環境変数・TTY 状態から最終的な color フラグを解決する。\n * 優先順位: --no-color > --color > NO_COLOR > FORCE_COLOR > TTY\n */\nexport function resolveColor(\n colorFlag: boolean | undefined,\n noColorFlag: boolean | undefined,\n env: Record<string, string | undefined>,\n isTTY: boolean,\n): boolean {\n if (noColorFlag) return false;\n if (colorFlag) return true;\n if (env.NO_COLOR) return false;\n if (env.FORCE_COLOR) return true;\n return isTTY;\n}\n\n/** 値を一つ取るオプションと、代入先のフィールド名 */\nconst VALUE_OPTIONS: Record<string, keyof CliArgs> = {\n \"--theme\": \"theme\",\n \"--color-scheme\": \"colorScheme\",\n \"--locale\": \"locale\",\n \"--holiday-locale\": \"holidayLocale\",\n \"--week-start\": \"weekStart\",\n \"--highlight-style\": \"highlightStyle\",\n};\n\n/** YYYY-MM-DD 形式の日付文字列をパースする */\nexport function parseDate(value: string): Date | null {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value);\n if (!match) return null;\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (\n year < MIN_YEAR ||\n year > MAX_YEAR ||\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > 31\n ) {\n return null;\n }\n const date = createDate(year, month - 1, day);\n if (\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return null;\n }\n return date;\n}\n\n/**\n * CLI 引数をパースする。テスト可能なように副作用を分離している。\n */\nexport function parseArgs(args: readonly string[]): ParseResult {\n const result: CliArgs = {};\n const error = (message: string): ParseResult => ({\n args: result,\n error: message,\n });\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === \"-h\" || arg === \"--help\") {\n return { args: result, help: true };\n }\n if (arg === \"-v\" || arg === \"--version\") {\n return { args: result, version: true };\n }\n if (arg === \"--color\") {\n result.color = true;\n continue;\n }\n if (arg === \"--no-color\") {\n result.noColor = true;\n continue;\n }\n if (arg === \"--year\") {\n result.yearView = true;\n continue;\n }\n if (arg === \"--week-numbers\") {\n result.weekNumbers = true;\n continue;\n }\n if (arg === \"--highlight\") {\n const value = args[++i];\n if (value === undefined) {\n return error(\"Missing value for option: --highlight\");\n }\n const parsed = parseDate(value);\n if (parsed === null) {\n return error(\n `Invalid --highlight date: \"${value}\" (expected YYYY-MM-DD, e.g. 2026-09-08)`,\n );\n }\n result.highlight = parsed;\n continue;\n }\n if (arg === \"--today\") {\n const value = args[++i];\n if (value === undefined) {\n return error(\"Missing value for option: --today\");\n }\n const parsed = parseDate(value);\n if (parsed === null) {\n return error(\n `Invalid --today date: \"${value}\" (expected YYYY-MM-DD, e.g. 2026-09-08)`,\n );\n }\n result.today = parsed;\n continue;\n }\n if (arg === \"--range\") {\n const fromStr = args[++i];\n const toStr = args[++i];\n if (fromStr === undefined || toStr === undefined) {\n return error(\n \"--range requires two dates (YYYY-MM-DD), e.g. --range 2026-01-01 2026-03-31\",\n );\n }\n const from = parseDate(fromStr);\n const to = parseDate(toStr);\n if (from === null || to === null) {\n return error(\"Invalid --range date (expected YYYY-MM-DD)\");\n }\n if (from.getTime() > to.getTime()) {\n return error(\"--range: from date must not be after to date\");\n }\n result.range = { from, to };\n continue;\n }\n\n const key = VALUE_OPTIONS[arg];\n if (key !== undefined) {\n const value = args[++i];\n if (value === undefined) {\n return error(`Missing value for option: ${arg}`);\n }\n (result as Record<string, unknown>)[key] = value;\n continue;\n }\n\n const numeric = /^-?\\d+$/.test(arg);\n if (arg.startsWith(\"-\") && !numeric) {\n return error(`Unknown option: ${arg}`);\n }\n if (!numeric) {\n return error(\n `Invalid argument: \"${arg}\" (expected a year or month number)`,\n );\n }\n if (result.year === undefined) {\n result.year = Number(arg);\n } else if (result.month === undefined) {\n result.month = Number(arg);\n } else {\n return error(`Too many arguments: \"${arg}\"`);\n }\n }\n\n // 値のバリデーション\n if (\n result.year !== undefined &&\n (result.year < MIN_YEAR || result.year > MAX_YEAR)\n ) {\n return error(\n `Invalid year: ${result.year} (expected ${MIN_YEAR}–${MAX_YEAR})`,\n );\n }\n if (result.month !== undefined && (result.month < 1 || result.month > 12)) {\n return error(`Invalid month: ${result.month} (expected 1–12)`);\n }\n\n const choiceTable: Array<[string | undefined, readonly string[], string]> = [\n [result.theme, THEMES, \"theme\"],\n [result.colorScheme, COLOR_SCHEMES, \"color-scheme\"],\n [result.locale, LOCALE_LIST, \"locale\"],\n [result.holidayLocale, LOCALE_LIST, \"holiday-locale\"],\n [result.weekStart, WEEK_STARTS, \"week-start\"],\n [result.highlightStyle, HIGHLIGHT_STYLES, \"highlight-style\"],\n ];\n for (const [value, choices, name] of choiceTable) {\n if (value !== undefined && !choices.includes(value)) {\n return error(\n `Invalid ${name}: \"${value}\" (expected: ${choices.join(\" | \")})`,\n );\n }\n }\n\n // 相互排他チェック\n if (result.yearView && result.range) {\n return error(\"--year and --range cannot be used together\");\n }\n if (result.yearView && result.month !== undefined) {\n return error(\"Month cannot be used with --year (use --year YYYY instead)\");\n }\n if (\n result.range &&\n (result.year !== undefined || result.month !== undefined)\n ) {\n return error(\"Positional arguments cannot be used with --range\");\n }\n\n return { args: result };\n}\n\nexport function printUsage(): string {\n return `Usage: typescript-calendar-lib [YYYY] [MM] [options]\n\n typescript-calendar-lib Render the current month\n typescript-calendar-lib 2026 Render the current month of 2026\n typescript-calendar-lib 2026 9 Render September 2026\n typescript-calendar-lib --year Render the current year (4×3 grid)\n typescript-calendar-lib 2026 --year Render 2026 as a year grid\n typescript-calendar-lib --range 2026-01-01 2026-03-31\n Render months from Jan to Mar 2026\n\nOptions:\n --theme <name> Look: default | modern (default: default)\n --color-scheme <name> Colors: default | ocean | forest | sunset | mono (default: default)\n --color Enable ANSI colors (auto-detected for TTY)\n --no-color Disable ANSI colors\n --locale <lang> Language: ${LOCALE_LIST.join(\" | \")} (default: en)\n --holiday-locale <lang> Holiday rules: currently only ja (default: ja)\n --week-start <day> First weekday: sunday | monday (default: sunday)\n --week-numbers Print the week number at the start of each row\n --highlight <YYYY-MM-DD> Highlight a date (e.g. 2026-09-08)\n --highlight-style <style> Highlight style: bracket | reverse (default: bracket)\n --today <YYYY-MM-DD> Override today (marks the date, defaults year/month)\n --year Render the whole year as a 4×3 grid\n --range <FROM> <TO> Render months from FROM to TO (YYYY-MM-DD)\n -v, --version Show version\n -h, --help Show this help\n\nColor:\n --color / --no-color win over the environment. NO_COLOR and FORCE_COLOR are\n honoured next, and a TTY is used as the final fallback.\n`;\n}\n\nif (import.meta.main) {\n const { args, error, help, version } = parseArgs(process.argv.slice(2));\n\n if (version) {\n console.log(getVersion());\n process.exit(0);\n }\n if (help) {\n console.log(printUsage());\n process.exit(0);\n }\n if (error) {\n console.error(`Error: ${error}`);\n console.error(printUsage());\n process.exit(1);\n }\n\n const color = resolveColor(\n args.color,\n args.noColor,\n process.env,\n process.stdout.isTTY === true,\n );\n\n const now = args.today ?? new Date();\n const year = args.year ?? now.getFullYear();\n const month = args.month ?? now.getMonth() + 1;\n\n const common = {\n theme: args.theme,\n colorScheme: args.colorScheme,\n color,\n locale: args.locale,\n holidayLocale: args.holidayLocale,\n weekStart: args.weekStart,\n showWeekNumbers: args.weekNumbers,\n highlight: args.highlight,\n highlightStyle: args.highlightStyle,\n today: args.today,\n };\n\n let output: string;\n if (args.range) {\n output = calendarRange({\n ...common,\n from: args.range.from,\n to: args.range.to,\n });\n } else if (args.yearView) {\n output = calendarYear({ ...common, year });\n } else {\n output = calendar({ ...common, year, month });\n }\n\n console.log(output);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from \"node:module\";\nimport type {\n HighlightStyle,\n HolidayLocale,\n Locale,\n WeekStart,\n} from \"@typescript-calendar-lib/core\";\nimport {\n createDate,\n LOCALES,\n MAX_YEAR,\n MIN_YEAR,\n} from \"@typescript-calendar-lib/core\";\nimport { calendar, calendarRange, calendarYear } from \"./calendar.ts\";\nimport type { ColorSchemeName, ThemeName } from \"./theme.ts\";\n\nexport interface CliArgs {\n year?: number;\n month?: number;\n theme?: ThemeName;\n colorScheme?: ColorSchemeName;\n color?: boolean;\n noColor?: boolean;\n locale?: Locale;\n holidayLocale?: HolidayLocale;\n weekStart?: WeekStart;\n weekNumbers?: boolean;\n highlight?: Date;\n highlightStyle?: HighlightStyle;\n today?: Date;\n yearView?: boolean;\n range?: { from: Date; to: Date };\n}\n\nexport interface ParseResult {\n args: CliArgs;\n error?: string;\n help?: boolean;\n version?: boolean;\n}\n\nconst THEMES: readonly ThemeName[] = [\"default\", \"modern\"];\nconst COLOR_SCHEMES: readonly ColorSchemeName[] = [\n \"default\",\n \"ocean\",\n \"forest\",\n \"sunset\",\n \"mono\",\n];\nconst LOCALE_LIST: readonly string[] = Object.keys(LOCALES);\nconst WEEK_STARTS: readonly WeekStart[] = [\"sunday\", \"monday\"];\nconst HIGHLIGHT_STYLES: readonly HighlightStyle[] = [\"bracket\", \"reverse\"];\n\nconst _require = createRequire(import.meta.url);\n\n/** package.json からバージョンを取得する */\nexport function getVersion(): string {\n return (_require(\"../package.json\") as { version: string }).version;\n}\n\n/**\n * CLI フラグ・環境変数・TTY 状態から最終的な color フラグを解決する。\n * 優先順位: --no-color > --color > NO_COLOR > FORCE_COLOR > TTY\n */\nexport function resolveColor(\n colorFlag: boolean | undefined,\n noColorFlag: boolean | undefined,\n env: Record<string, string | undefined>,\n isTTY: boolean,\n): boolean {\n if (noColorFlag) return false;\n if (colorFlag) return true;\n if (env.NO_COLOR) return false;\n if (env.FORCE_COLOR) return true;\n return isTTY;\n}\n\n/** 値を一つ取るオプションと、代入先のフィールド名 */\nconst VALUE_OPTIONS: Record<string, keyof CliArgs> = {\n \"--theme\": \"theme\",\n \"--color-scheme\": \"colorScheme\",\n \"--locale\": \"locale\",\n \"--holiday-locale\": \"holidayLocale\",\n \"--week-start\": \"weekStart\",\n \"--highlight-style\": \"highlightStyle\",\n};\n\n/** YYYY-MM-DD 形式の日付文字列をパースする */\nexport function parseDate(value: string): Date | null {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value);\n if (!match) return null;\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n if (\n year < MIN_YEAR ||\n year > MAX_YEAR ||\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > 31\n ) {\n return null;\n }\n const date = createDate(year, month - 1, day);\n if (\n date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return null;\n }\n return date;\n}\n\n/**\n * CLI 引数をパースする。テスト可能なように副作用を分離している。\n */\nexport function parseArgs(args: readonly string[]): ParseResult {\n const result: CliArgs = {};\n const error = (message: string): ParseResult => ({\n args: result,\n error: message,\n });\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n\n if (arg === \"-h\" || arg === \"--help\") {\n return { args: result, help: true };\n }\n if (arg === \"-v\" || arg === \"--version\") {\n return { args: result, version: true };\n }\n if (arg === \"--color\") {\n result.color = true;\n continue;\n }\n if (arg === \"--no-color\") {\n result.noColor = true;\n continue;\n }\n if (arg === \"--year\") {\n result.yearView = true;\n continue;\n }\n if (arg === \"--week-numbers\") {\n result.weekNumbers = true;\n continue;\n }\n if (arg === \"--highlight\") {\n const value = args[++i];\n if (value === undefined) {\n return error(\"Missing value for option: --highlight\");\n }\n const parsed = parseDate(value);\n if (parsed === null) {\n return error(\n `Invalid --highlight date: \"${value}\" (expected YYYY-MM-DD, e.g. 2026-09-08)`,\n );\n }\n result.highlight = parsed;\n continue;\n }\n if (arg === \"--today\") {\n const value = args[++i];\n if (value === undefined) {\n return error(\"Missing value for option: --today\");\n }\n const parsed = parseDate(value);\n if (parsed === null) {\n return error(\n `Invalid --today date: \"${value}\" (expected YYYY-MM-DD, e.g. 2026-09-08)`,\n );\n }\n result.today = parsed;\n continue;\n }\n if (arg === \"--range\") {\n const fromStr = args[++i];\n const toStr = args[++i];\n if (fromStr === undefined || toStr === undefined) {\n return error(\n \"--range requires two dates (YYYY-MM-DD), e.g. --range 2026-01-01 2026-03-31\",\n );\n }\n const from = parseDate(fromStr);\n const to = parseDate(toStr);\n if (from === null || to === null) {\n return error(\"Invalid --range date (expected YYYY-MM-DD)\");\n }\n if (from.getTime() > to.getTime()) {\n return error(\"--range: from date must not be after to date\");\n }\n result.range = { from, to };\n continue;\n }\n\n const key = VALUE_OPTIONS[arg];\n if (key !== undefined) {\n const value = args[++i];\n if (value === undefined) {\n return error(`Missing value for option: ${arg}`);\n }\n (result as Record<string, unknown>)[key] = value;\n continue;\n }\n\n const numeric = /^-?\\d+$/.test(arg);\n if (arg.startsWith(\"-\") && !numeric) {\n return error(`Unknown option: ${arg}`);\n }\n if (!numeric) {\n return error(\n `Invalid argument: \"${arg}\" (expected a year or month number)`,\n );\n }\n if (result.year === undefined) {\n result.year = Number(arg);\n } else if (result.month === undefined) {\n result.month = Number(arg);\n } else {\n return error(`Too many arguments: \"${arg}\"`);\n }\n }\n\n // 値のバリデーション\n if (\n result.year !== undefined &&\n (result.year < MIN_YEAR || result.year > MAX_YEAR)\n ) {\n return error(\n `Invalid year: ${result.year} (expected ${MIN_YEAR}–${MAX_YEAR})`,\n );\n }\n if (result.month !== undefined && (result.month < 1 || result.month > 12)) {\n return error(`Invalid month: ${result.month} (expected 1–12)`);\n }\n\n const choiceTable: Array<[string | undefined, readonly string[], string]> = [\n [result.theme, THEMES, \"theme\"],\n [result.colorScheme, COLOR_SCHEMES, \"color-scheme\"],\n [result.locale, LOCALE_LIST, \"locale\"],\n [result.holidayLocale, LOCALE_LIST, \"holiday-locale\"],\n [result.weekStart, WEEK_STARTS, \"week-start\"],\n [result.highlightStyle, HIGHLIGHT_STYLES, \"highlight-style\"],\n ];\n for (const [value, choices, name] of choiceTable) {\n if (value !== undefined && !choices.includes(value)) {\n return error(\n `Invalid ${name}: \"${value}\" (expected: ${choices.join(\" | \")})`,\n );\n }\n }\n\n // 相互排他チェック\n if (result.yearView && result.range) {\n return error(\"--year and --range cannot be used together\");\n }\n if (result.yearView && result.month !== undefined) {\n return error(\"Month cannot be used with --year (use --year YYYY instead)\");\n }\n if (\n result.range &&\n (result.year !== undefined || result.month !== undefined)\n ) {\n return error(\"Positional arguments cannot be used with --range\");\n }\n\n return { args: result };\n}\n\nexport function printUsage(): string {\n return `Usage: typescript-calendar-lib [YYYY] [MM] [options]\n\n typescript-calendar-lib Render the current month\n typescript-calendar-lib 2026 Render the current month of 2026\n typescript-calendar-lib 2026 9 Render September 2026\n typescript-calendar-lib --year Render the current year (4×3 grid)\n typescript-calendar-lib 2026 --year Render 2026 as a year grid\n typescript-calendar-lib --range 2026-01-01 2026-03-31\n Render months from Jan to Mar 2026\n\nOptions:\n --theme <name> Look: default | modern (default: default)\n --color-scheme <name> Colors: default | ocean | forest | sunset | mono (default: default)\n --color Enable ANSI colors (auto-detected for TTY)\n --no-color Disable ANSI colors\n --locale <lang> Language: ${LOCALE_LIST.join(\" | \")} (default: en)\n --holiday-locale <lang> Holiday rules: en | ja | es | de | fr | ko | zh (default: ja)\n --week-start <day> First weekday: sunday | monday (default: sunday)\n --week-numbers Print the week number at the start of each row\n --highlight <YYYY-MM-DD> Highlight a date (e.g. 2026-09-08)\n --highlight-style <style> Highlight style: bracket | reverse (default: bracket)\n --today <YYYY-MM-DD> Override today (marks the date, defaults year/month)\n --year Render the whole year as a 4×3 grid\n --range <FROM> <TO> Render months from FROM to TO (YYYY-MM-DD)\n -v, --version Show version\n -h, --help Show this help\n\nColor:\n --color / --no-color win over the environment. NO_COLOR and FORCE_COLOR are\n honoured next, and a TTY is used as the final fallback.\n`;\n}\n\nif (import.meta.main) {\n const { args, error, help, version } = parseArgs(process.argv.slice(2));\n\n if (version) {\n console.log(getVersion());\n process.exit(0);\n }\n if (help) {\n console.log(printUsage());\n process.exit(0);\n }\n if (error) {\n console.error(`Error: ${error}`);\n console.error(printUsage());\n process.exit(1);\n }\n\n const color = resolveColor(\n args.color,\n args.noColor,\n process.env,\n process.stdout.isTTY === true,\n );\n\n const now = args.today ?? new Date();\n const year = args.year ?? now.getFullYear();\n const month = args.month ?? now.getMonth() + 1;\n\n const common = {\n theme: args.theme,\n colorScheme: args.colorScheme,\n color,\n locale: args.locale,\n holidayLocale: args.holidayLocale,\n weekStart: args.weekStart,\n showWeekNumbers: args.weekNumbers,\n highlight: args.highlight,\n highlightStyle: args.highlightStyle,\n today: args.today,\n };\n\n let output: string;\n if (args.range) {\n output = calendarRange({\n ...common,\n from: args.range.from,\n to: args.range.to,\n });\n } else if (args.yearView) {\n output = calendarYear({ ...common, year });\n } else {\n output = calendar({ ...common, year, month });\n }\n\n console.log(output);\n}\n"],"mappings":";;;;;AA0CA,MAAM,SAA+B,CAAC,WAAW,QAAQ;AACzD,MAAM,gBAA4C;CAChD;CACA;CACA;CACA;CACA;AACF;AACA,MAAM,cAAiC,OAAO,KAAK,OAAO;AAC1D,MAAM,cAAoC,CAAC,UAAU,QAAQ;AAC7D,MAAM,mBAA8C,CAAC,WAAW,SAAS;AAEzE,MAAM,WAAW,cAAc,YAAY,GAAG;;AAG9C,SAAgB,aAAqB;CACnC,OAAQ,SAAS,iBAAiB,CAAC,CAAyB;AAC9D;;;;;AAMA,SAAgB,aACd,WACA,aACA,KACA,OACS;CACT,IAAI,aAAa,OAAO;CACxB,IAAI,WAAW,OAAO;CACtB,IAAI,IAAI,UAAU,OAAO;CACzB,IAAI,IAAI,aAAa,OAAO;CAC5B,OAAO;AACT;;AAGA,MAAM,gBAA+C;CACnD,WAAW;CACX,kBAAkB;CAClB,YAAY;CACZ,oBAAoB;CACpB,gBAAgB;CAChB,qBAAqB;AACvB;;AAGA,SAAgB,UAAU,OAA4B;CACpD,MAAM,QAAQ,4BAA4B,KAAK,KAAK;CACpD,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,OAAO,OAAO,MAAM,EAAE;CAC5B,MAAM,QAAQ,OAAO,MAAM,EAAE;CAC7B,MAAM,MAAM,OAAO,MAAM,EAAE;CAC3B,IACE,OAAO,YACP,OAAO,YACP,QAAQ,KACR,QAAQ,MACR,MAAM,KACN,MAAM,IAEN,OAAO;CAET,MAAM,OAAO,WAAW,MAAM,QAAQ,GAAG,GAAG;CAC5C,IACE,KAAK,YAAY,MAAM,QACvB,KAAK,SAAS,MAAM,QAAQ,KAC5B,KAAK,QAAQ,MAAM,KAEnB,OAAO;CAET,OAAO;AACT;;;;AAKA,SAAgB,UAAU,MAAsC;CAC9D,MAAM,SAAkB,CAAC;CACzB,MAAM,SAAS,aAAkC;EAC/C,MAAM;EACN,OAAO;CACT;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,MAAM,KAAK;EAEjB,IAAI,QAAQ,QAAQ,QAAQ,UAC1B,OAAO;GAAE,MAAM;GAAQ,MAAM;EAAK;EAEpC,IAAI,QAAQ,QAAQ,QAAQ,aAC1B,OAAO;GAAE,MAAM;GAAQ,SAAS;EAAK;EAEvC,IAAI,QAAQ,WAAW;GACrB,OAAO,QAAQ;GACf;EACF;EACA,IAAI,QAAQ,cAAc;GACxB,OAAO,UAAU;GACjB;EACF;EACA,IAAI,QAAQ,UAAU;GACpB,OAAO,WAAW;GAClB;EACF;EACA,IAAI,QAAQ,kBAAkB;GAC5B,OAAO,cAAc;GACrB;EACF;EACA,IAAI,QAAQ,eAAe;GACzB,MAAM,QAAQ,KAAK,EAAE;GACrB,IAAI,UAAU,KAAA,GACZ,OAAO,MAAM,uCAAuC;GAEtD,MAAM,SAAS,UAAU,KAAK;GAC9B,IAAI,WAAW,MACb,OAAO,MACL,8BAA8B,MAAM,yCACtC;GAEF,OAAO,YAAY;GACnB;EACF;EACA,IAAI,QAAQ,WAAW;GACrB,MAAM,QAAQ,KAAK,EAAE;GACrB,IAAI,UAAU,KAAA,GACZ,OAAO,MAAM,mCAAmC;GAElD,MAAM,SAAS,UAAU,KAAK;GAC9B,IAAI,WAAW,MACb,OAAO,MACL,0BAA0B,MAAM,yCAClC;GAEF,OAAO,QAAQ;GACf;EACF;EACA,IAAI,QAAQ,WAAW;GACrB,MAAM,UAAU,KAAK,EAAE;GACvB,MAAM,QAAQ,KAAK,EAAE;GACrB,IAAI,YAAY,KAAA,KAAa,UAAU,KAAA,GACrC,OAAO,MACL,6EACF;GAEF,MAAM,OAAO,UAAU,OAAO;GAC9B,MAAM,KAAK,UAAU,KAAK;GAC1B,IAAI,SAAS,QAAQ,OAAO,MAC1B,OAAO,MAAM,4CAA4C;GAE3D,IAAI,KAAK,QAAQ,IAAI,GAAG,QAAQ,GAC9B,OAAO,MAAM,8CAA8C;GAE7D,OAAO,QAAQ;IAAE;IAAM;GAAG;GAC1B;EACF;EAEA,MAAM,MAAM,cAAc;EAC1B,IAAI,QAAQ,KAAA,GAAW;GACrB,MAAM,QAAQ,KAAK,EAAE;GACrB,IAAI,UAAU,KAAA,GACZ,OAAO,MAAM,6BAA6B,KAAK;GAEjD,OAAoC,OAAO;GAC3C;EACF;EAEA,MAAM,UAAU,UAAU,KAAK,GAAG;EAClC,IAAI,IAAI,WAAW,GAAG,KAAK,CAAC,SAC1B,OAAO,MAAM,mBAAmB,KAAK;EAEvC,IAAI,CAAC,SACH,OAAO,MACL,sBAAsB,IAAI,oCAC5B;EAEF,IAAI,OAAO,SAAS,KAAA,GAClB,OAAO,OAAO,OAAO,GAAG;OACnB,IAAI,OAAO,UAAU,KAAA,GAC1B,OAAO,QAAQ,OAAO,GAAG;OAEzB,OAAO,MAAM,wBAAwB,IAAI,EAAE;CAE/C;CAGA,IACE,OAAO,SAAS,KAAA,MACf,OAAO,OAAO,YAAY,OAAO,OAAO,WAEzC,OAAO,MACL,iBAAiB,OAAO,KAAK,aAAa,SAAS,GAAG,SAAS,EACjE;CAEF,IAAI,OAAO,UAAU,KAAA,MAAc,OAAO,QAAQ,KAAK,OAAO,QAAQ,KACpE,OAAO,MAAM,kBAAkB,OAAO,MAAM,iBAAiB;CAG/D,MAAM,cAAsE;EAC1E;GAAC,OAAO;GAAO;GAAQ;EAAO;EAC9B;GAAC,OAAO;GAAa;GAAe;EAAc;EAClD;GAAC,OAAO;GAAQ;GAAa;EAAQ;EACrC;GAAC,OAAO;GAAe;GAAa;EAAgB;EACpD;GAAC,OAAO;GAAW;GAAa;EAAY;EAC5C;GAAC,OAAO;GAAgB;GAAkB;EAAiB;CAC7D;CACA,KAAK,MAAM,CAAC,OAAO,SAAS,SAAS,aACnC,IAAI,UAAU,KAAA,KAAa,CAAC,QAAQ,SAAS,KAAK,GAChD,OAAO,MACL,WAAW,KAAK,KAAK,MAAM,eAAe,QAAQ,KAAK,KAAK,EAAE,EAChE;CAKJ,IAAI,OAAO,YAAY,OAAO,OAC5B,OAAO,MAAM,4CAA4C;CAE3D,IAAI,OAAO,YAAY,OAAO,UAAU,KAAA,GACtC,OAAO,MAAM,4DAA4D;CAE3E,IACE,OAAO,UACN,OAAO,SAAS,KAAA,KAAa,OAAO,UAAU,KAAA,IAE/C,OAAO,MAAM,kDAAkD;CAGjE,OAAO,EAAE,MAAM,OAAO;AACxB;AAEA,SAAgB,aAAqB;CACnC,OAAO;;;;;;;;;;;;;;;uCAe8B,YAAY,KAAK,KAAK,EAAE;;;;;;;;;;;;;;;;AAgB/D;AAEA,IAAI,YAAY,MAAM;CACpB,MAAM,EAAE,MAAM,OAAO,MAAM,YAAY,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;CAEtE,IAAI,SAAS;EACX,QAAQ,IAAI,WAAW,CAAC;EACxB,QAAQ,KAAK,CAAC;CAChB;CACA,IAAI,MAAM;EACR,QAAQ,IAAI,WAAW,CAAC;EACxB,QAAQ,KAAK,CAAC;CAChB;CACA,IAAI,OAAO;EACT,QAAQ,MAAM,UAAU,OAAO;EAC/B,QAAQ,MAAM,WAAW,CAAC;EAC1B,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,QAAQ,aACZ,KAAK,OACL,KAAK,SACL,QAAQ,KACR,QAAQ,OAAO,UAAU,IAC3B;CAEA,MAAM,MAAM,KAAK,yBAAS,IAAI,KAAK;CACnC,MAAM,OAAO,KAAK,QAAQ,IAAI,YAAY;CAC1C,MAAM,QAAQ,KAAK,SAAS,IAAI,SAAS,IAAI;CAE7C,MAAM,SAAS;EACb,OAAO,KAAK;EACZ,aAAa,KAAK;EAClB;EACA,QAAQ,KAAK;EACb,eAAe,KAAK;EACpB,WAAW,KAAK;EAChB,iBAAiB,KAAK;EACtB,WAAW,KAAK;EAChB,gBAAgB,KAAK;EACrB,OAAO,KAAK;CACd;CAEA,IAAI;CACJ,IAAI,KAAK,OACP,SAAS,cAAc;EACrB,GAAG;EACH,MAAM,KAAK,MAAM;EACjB,IAAI,KAAK,MAAM;CACjB,CAAC;MACI,IAAI,KAAK,UACd,SAAS,aAAa;EAAE,GAAG;EAAQ;CAAK,CAAC;MAEzC,SAAS,SAAS;EAAE,GAAG;EAAQ;EAAM;CAAM,CAAC;CAG9C,QAAQ,IAAI,MAAM;AACpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-calendar-lib/cli",
3
- "version": "0.5.4",
3
+ "version": "0.6.1",
4
4
  "description": "Terminal calendar renderer with themes and ANSI color schemes",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,9 +30,18 @@
30
30
  ],
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@typescript-calendar-lib/core": "^0.5.4",
34
- "@typescript-calendar-lib/tui": "^0.5.4"
33
+ "@typescript-calendar-lib/core": "^0.6.1",
34
+ "@typescript-calendar-lib/tui": "^0.6.1"
35
35
  },
36
+ "author": "nazozokc",
37
+ "homepage": "https://github.com/nazozokc/typescript-calendar-lib#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/nazozokc/typescript-calendar-lib/issues"
40
+ },
41
+ "engines": {
42
+ "node": ">=22"
43
+ },
44
+ "sideEffects": false,
36
45
  "scripts": {
37
46
  "build": "tsdown"
38
47
  }