formatferry 0.1.4 → 1.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/dist/commands/auth.d.ts +17 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +102 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/batch.d.ts +10 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +92 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/convert.d.ts +26 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +198 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/config-store.d.ts +27 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +58 -0
- package/dist/config-store.js.map +1 -0
- package/dist/entitlement.d.ts +11 -0
- package/dist/entitlement.d.ts.map +1 -0
- package/dist/entitlement.js +91 -0
- package/dist/entitlement.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -0
- package/dist/packages/cli/src/commands/auth.d.ts +17 -0
- package/dist/packages/cli/src/commands/auth.d.ts.map +1 -0
- package/dist/packages/cli/src/commands/auth.js +102 -0
- package/dist/packages/cli/src/commands/auth.js.map +1 -0
- package/dist/packages/cli/src/commands/batch.d.ts +10 -0
- package/dist/packages/cli/src/commands/batch.d.ts.map +1 -0
- package/dist/packages/cli/src/commands/batch.js +92 -0
- package/dist/packages/cli/src/commands/batch.js.map +1 -0
- package/dist/packages/cli/src/commands/convert.d.ts +26 -0
- package/dist/packages/cli/src/commands/convert.d.ts.map +1 -0
- package/dist/packages/cli/src/commands/convert.js +198 -0
- package/dist/packages/cli/src/commands/convert.js.map +1 -0
- package/dist/packages/cli/src/config-store.d.ts +27 -0
- package/dist/packages/cli/src/config-store.d.ts.map +1 -0
- package/dist/packages/cli/src/config-store.js +58 -0
- package/dist/packages/cli/src/config-store.js.map +1 -0
- package/dist/packages/cli/src/entitlement.d.ts +11 -0
- package/dist/packages/cli/src/entitlement.d.ts.map +1 -0
- package/dist/packages/cli/src/entitlement.js +91 -0
- package/dist/packages/cli/src/entitlement.js.map +1 -0
- package/dist/packages/cli/src/index.d.ts +2 -0
- package/dist/packages/cli/src/index.d.ts.map +1 -0
- package/dist/packages/cli/src/index.js +28 -0
- package/dist/packages/cli/src/index.js.map +1 -0
- package/dist/packages/cli/src/shim.d.ts +2 -0
- package/dist/packages/cli/src/shim.d.ts.map +1 -0
- package/dist/packages/cli/src/shim.js +21 -0
- package/dist/packages/cli/src/shim.js.map +1 -0
- package/dist/shim.d.ts +2 -0
- package/dist/shim.d.ts.map +1 -0
- package/dist/shim.js +21 -0
- package/dist/shim.js.map +1 -0
- package/dist/src/shared/adapters/docx-adapter.d.ts +85 -0
- package/dist/src/shared/adapters/docx-adapter.d.ts.map +1 -0
- package/dist/src/shared/adapters/docx-adapter.js +164 -0
- package/dist/src/shared/adapters/docx-adapter.js.map +1 -0
- package/dist/src/shared/adapters/pdf-adapter.d.ts +94 -0
- package/dist/src/shared/adapters/pdf-adapter.d.ts.map +1 -0
- package/dist/src/shared/adapters/pdf-adapter.js +322 -0
- package/dist/src/shared/adapters/pdf-adapter.js.map +1 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.d.ts +98 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.d.ts.map +1 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.js +424 -0
- package/dist/src/shared/adapters/spreadsheet-adapter.js.map +1 -0
- package/dist/src/shared/atlassian-detector.d.ts +6 -0
- package/dist/src/shared/atlassian-detector.d.ts.map +1 -0
- package/dist/src/shared/atlassian-detector.js +23 -0
- package/dist/src/shared/atlassian-detector.js.map +1 -0
- package/dist/src/shared/conversion-engine.d.ts +114 -0
- package/dist/src/shared/conversion-engine.d.ts.map +1 -0
- package/dist/src/shared/conversion-engine.js +790 -0
- package/dist/src/shared/conversion-engine.js.map +1 -0
- package/dist/src/shared/entitlement-service.d.ts +42 -0
- package/dist/src/shared/entitlement-service.d.ts.map +1 -0
- package/dist/src/shared/entitlement-service.js +38 -0
- package/dist/src/shared/entitlement-service.js.map +1 -0
- package/dist/src/shared/input-sanitizer.d.ts +93 -0
- package/dist/src/shared/input-sanitizer.d.ts.map +1 -0
- package/dist/src/shared/input-sanitizer.js +527 -0
- package/dist/src/shared/input-sanitizer.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI auth command — license key management.
|
|
3
|
+
*
|
|
4
|
+
* Sub-commands (via options):
|
|
5
|
+
* formatferry auth --license-key <KEY> Validate + store license key (Req 9.1, 9.3, 9.4)
|
|
6
|
+
* formatferry auth --status Show current tier/expiry/features (Req 9.6)
|
|
7
|
+
* formatferry auth --logout Remove stored license key (Req 9.7)
|
|
8
|
+
*
|
|
9
|
+
* License Server: POST https://formatferry.vibingfun.com/v1/licenses/validate
|
|
10
|
+
*/
|
|
11
|
+
export interface AuthOptions {
|
|
12
|
+
licenseKey?: string;
|
|
13
|
+
status?: boolean;
|
|
14
|
+
logout?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function authCommand(options: AuthOptions): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgBH,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAUrE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI auth command — license key management.
|
|
3
|
+
*
|
|
4
|
+
* Sub-commands (via options):
|
|
5
|
+
* formatferry auth --license-key <KEY> Validate + store license key (Req 9.1, 9.3, 9.4)
|
|
6
|
+
* formatferry auth --status Show current tier/expiry/features (Req 9.6)
|
|
7
|
+
* formatferry auth --logout Remove stored license key (Req 9.7)
|
|
8
|
+
*
|
|
9
|
+
* License Server: POST https://formatferry.vibingfun.com/v1/licenses/validate
|
|
10
|
+
*/
|
|
11
|
+
import { readConfig, writeConfig, clearConfig } from '../config-store.js';
|
|
12
|
+
const LICENSE_SERVER_URL = 'https://formatferry.vibingfun.com';
|
|
13
|
+
const VALIDATE_ENDPOINT = `${LICENSE_SERVER_URL}/v1/licenses/validate`;
|
|
14
|
+
const TIMEOUT_MS = 10_000;
|
|
15
|
+
export async function authCommand(options) {
|
|
16
|
+
if (options.licenseKey) {
|
|
17
|
+
await handleLicenseKey(options.licenseKey);
|
|
18
|
+
}
|
|
19
|
+
else if (options.status) {
|
|
20
|
+
handleStatus();
|
|
21
|
+
}
|
|
22
|
+
else if (options.logout) {
|
|
23
|
+
handleLogout();
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
handleStatus();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// ─── --license-key ────────────────────────────────────────────────────────────
|
|
30
|
+
async function handleLicenseKey(key) {
|
|
31
|
+
let data;
|
|
32
|
+
try {
|
|
33
|
+
const controller = new AbortController();
|
|
34
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
35
|
+
const response = await fetch(VALIDATE_ENDPOINT, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' },
|
|
38
|
+
body: JSON.stringify({ key }),
|
|
39
|
+
signal: controller.signal,
|
|
40
|
+
});
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
data = (await response.json());
|
|
43
|
+
if (!response.ok && !data.valid) {
|
|
44
|
+
process.stderr.write(`Error: Invalid license key. Please check your key and try again.\n`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
50
|
+
process.stderr.write(`Error: Could not reach license server — ${msg}\n`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
if (data.revoked) {
|
|
54
|
+
process.stderr.write(`Error: This license key has been revoked.\n`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
if (!data.valid) {
|
|
58
|
+
process.stderr.write(`Error: Invalid license key. Please check your key and try again.\n`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
writeConfig({
|
|
62
|
+
licenseKey: key,
|
|
63
|
+
tier: data.tier ?? 'premium',
|
|
64
|
+
features: data.features ?? [],
|
|
65
|
+
expiresAt: data.expiresAt ?? null,
|
|
66
|
+
lastValidated: new Date().toISOString(),
|
|
67
|
+
});
|
|
68
|
+
const features = data.features ?? [];
|
|
69
|
+
process.stdout.write(`License activated successfully!\n`);
|
|
70
|
+
process.stdout.write(`Tier: ${data.tier ?? 'premium'}\n`);
|
|
71
|
+
if (data.expiresAt) {
|
|
72
|
+
process.stdout.write(`Expires: ${data.expiresAt}\n`);
|
|
73
|
+
}
|
|
74
|
+
if (features.length > 0) {
|
|
75
|
+
process.stdout.write(`Unlocked features: ${features.join(', ')}\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// ─── --status ─────────────────────────────────────────────────────────────────
|
|
79
|
+
function handleStatus() {
|
|
80
|
+
const config = readConfig();
|
|
81
|
+
if (!config || !config.licenseKey) {
|
|
82
|
+
process.stdout.write(`Tier: free\n`);
|
|
83
|
+
process.stdout.write(`No license key configured.\n`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const tier = config.tier ?? 'free';
|
|
87
|
+
const features = config.features ?? [];
|
|
88
|
+
const expiresAt = config.expiresAt ?? null;
|
|
89
|
+
process.stdout.write(`Tier: ${tier}\n`);
|
|
90
|
+
if (expiresAt) {
|
|
91
|
+
process.stdout.write(`Expires: ${expiresAt}\n`);
|
|
92
|
+
}
|
|
93
|
+
if (features.length > 0) {
|
|
94
|
+
process.stdout.write(`Features: ${features.join(', ')}\n`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ─── --logout ─────────────────────────────────────────────────────────────────
|
|
98
|
+
function handleLogout() {
|
|
99
|
+
clearConfig();
|
|
100
|
+
process.stdout.write(`Logged out. License key removed.\n`);
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface BatchOptions {
|
|
2
|
+
batch?: string;
|
|
3
|
+
outputDir?: string;
|
|
4
|
+
format?: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
/** Derive the output .md path. Req 8.2 (same dir) / Req 8.3 (outputDir) */
|
|
8
|
+
export declare function getOutputPath(filePath: string, outputDir?: string): string;
|
|
9
|
+
export declare function batchCommand(options: BatchOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/commands/batch.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1E;AAkCD,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCvE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI batch command
|
|
3
|
+
*
|
|
4
|
+
* Batch-converts files matching a glob pattern to Markdown.
|
|
5
|
+
* Supports --output-dir for writing all outputs to a single directory.
|
|
6
|
+
* Gated behind the 'batch' Premium entitlement.
|
|
7
|
+
*
|
|
8
|
+
* Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6
|
|
9
|
+
*/
|
|
10
|
+
import fg from 'fast-glob';
|
|
11
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
12
|
+
import { extname, basename, dirname, join } from 'path';
|
|
13
|
+
import { resolveEntitlement } from '../entitlement.js';
|
|
14
|
+
import { ConversionEngine } from '../src/shared/conversion-engine.js';
|
|
15
|
+
import { sanitizeHTML } from '../src/shared/input-sanitizer.js';
|
|
16
|
+
import { docxAdapter } from '../src/shared/adapters/docx-adapter.js';
|
|
17
|
+
import { pdfAdapter } from '../src/shared/adapters/pdf-adapter.js';
|
|
18
|
+
import { spreadsheetAdapter } from '../src/shared/adapters/spreadsheet-adapter.js';
|
|
19
|
+
const SUPPORTED_EXTENSIONS = new Set(['.html', '.htm', '.docx', '.pdf', '.xlsx', '.csv']);
|
|
20
|
+
/** Derive the output .md path. Req 8.2 (same dir) / Req 8.3 (outputDir) */
|
|
21
|
+
export function getOutputPath(filePath, outputDir) {
|
|
22
|
+
const ext = extname(filePath);
|
|
23
|
+
const stem = basename(filePath, ext);
|
|
24
|
+
if (outputDir)
|
|
25
|
+
return join(outputDir, `${stem}.md`);
|
|
26
|
+
return join(dirname(filePath), `${stem}.md`);
|
|
27
|
+
}
|
|
28
|
+
async function convertFile(filePath, format) {
|
|
29
|
+
const ext = extname(filePath).toLowerCase();
|
|
30
|
+
if (!SUPPORTED_EXTENSIONS.has(ext))
|
|
31
|
+
throw new Error(`Unsupported file type: ${ext}`);
|
|
32
|
+
const buffer = readFileSync(filePath);
|
|
33
|
+
const engine = new ConversionEngine();
|
|
34
|
+
if (ext === '.html' || ext === '.htm') {
|
|
35
|
+
const result = await engine.convert(sanitizeHTML(buffer.toString('utf8')), {
|
|
36
|
+
format, preserveTables: true, preserveLists: true, customRules: [],
|
|
37
|
+
});
|
|
38
|
+
return result.markdown;
|
|
39
|
+
}
|
|
40
|
+
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
41
|
+
if (ext === '.docx') {
|
|
42
|
+
const r = await docxAdapter.parseToHtml(arrayBuffer);
|
|
43
|
+
const c = await engine.convert(sanitizeHTML(r.html), { format, preserveTables: true, preserveLists: true, customRules: [] });
|
|
44
|
+
return c.markdown;
|
|
45
|
+
}
|
|
46
|
+
if (ext === '.pdf') {
|
|
47
|
+
const r = await pdfAdapter.parseToText(arrayBuffer);
|
|
48
|
+
const c = await engine.convert(sanitizeHTML(r.html), { format, preserveTables: true, preserveLists: true, customRules: [] });
|
|
49
|
+
return c.markdown;
|
|
50
|
+
}
|
|
51
|
+
// .xlsx / .csv
|
|
52
|
+
const r = await spreadsheetAdapter.parseToHtml(arrayBuffer, ext.slice(1), 0);
|
|
53
|
+
const c = await engine.convert(sanitizeHTML(r.html), { format, preserveTables: true, preserveLists: true, customRules: [] });
|
|
54
|
+
return c.markdown;
|
|
55
|
+
}
|
|
56
|
+
export async function batchCommand(options) {
|
|
57
|
+
// Req 8.4: entitlement check
|
|
58
|
+
const provider = await resolveEntitlement();
|
|
59
|
+
if (!provider.hasFeature('batch')) {
|
|
60
|
+
process.stderr.write('Error: Batch processing requires a Premium license.\n' +
|
|
61
|
+
'Run `formatferry auth --license-key <KEY>` to activate your license.\n');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
const glob = options.batch;
|
|
65
|
+
if (!glob) {
|
|
66
|
+
process.stderr.write('Error: --batch <glob> is required\n');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const files = await fg(glob, { absolute: true });
|
|
70
|
+
if (files.length === 0) {
|
|
71
|
+
process.stderr.write(`No files matched: ${glob}\n`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const format = options.format ?? 'github';
|
|
75
|
+
if (options.outputDir)
|
|
76
|
+
mkdirSync(options.outputDir, { recursive: true });
|
|
77
|
+
let successful = 0, failed = 0;
|
|
78
|
+
for (const filePath of files) {
|
|
79
|
+
try {
|
|
80
|
+
const markdown = await convertFile(filePath, format);
|
|
81
|
+
writeFileSync(getOutputPath(filePath, options.outputDir), markdown, 'utf8');
|
|
82
|
+
successful++;
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
process.stderr.write(`Error processing ${filePath}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
86
|
+
failed++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Req 8.5: summary
|
|
90
|
+
process.stderr.write(`\nBatch complete: ${successful} succeeded, ${failed} failed, ${files.length} total\n`);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/commands/batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type MarkdownFormat } from '../src/shared/conversion-engine.js';
|
|
2
|
+
/** Supported input file types */
|
|
3
|
+
type InputType = 'html' | 'docx' | 'pdf' | 'xlsx' | 'csv';
|
|
4
|
+
/**
|
|
5
|
+
* Detect input type from file extension.
|
|
6
|
+
* Writes error to stderr and exits with code 1 on unsupported extension.
|
|
7
|
+
*/
|
|
8
|
+
export declare function detectInputType(filePath: string): InputType;
|
|
9
|
+
/**
|
|
10
|
+
* Validate the --format flag value.
|
|
11
|
+
* Writes error to stderr and exits with code 1 on unknown format.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateFormat(format: string): MarkdownFormat;
|
|
14
|
+
/** Options passed by Commander to the convert action */
|
|
15
|
+
export interface ConvertOptions {
|
|
16
|
+
input?: string;
|
|
17
|
+
output?: string;
|
|
18
|
+
format?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Main convert command action.
|
|
22
|
+
* Called by Commander when the user runs `formatferry [options]`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function convertCommand(options: ConvertOptions): Promise<void>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"AAUA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAQtF,iCAAiC;AACjC,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAW1D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAkB3D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAQ7D;AA8FD,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAoE3E"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI convert command
|
|
3
|
+
*
|
|
4
|
+
* Handles stdin → stdout, file input, file output, format selection,
|
|
5
|
+
* and binary file processing (DOCX, PDF, XLSX/CSV).
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 7.3, 7.4, 7.5, 7.6, 7.7, 7.10, 11.1, 11.2, 11.3, 11.5
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
10
|
+
import { extname } from 'path';
|
|
11
|
+
import { ConversionEngine } from '../src/shared/conversion-engine.js';
|
|
12
|
+
import { docxAdapter } from '../src/shared/adapters/docx-adapter.js';
|
|
13
|
+
import { pdfAdapter } from '../src/shared/adapters/pdf-adapter.js';
|
|
14
|
+
import { spreadsheetAdapter } from '../src/shared/adapters/spreadsheet-adapter.js';
|
|
15
|
+
import { sanitizeHTML, normalizeAtlassianHTML } from '../src/shared/input-sanitizer.js';
|
|
16
|
+
import { isAtlassianHTML } from '../src/shared/atlassian-detector.js';
|
|
17
|
+
import { resolveEntitlement } from '../entitlement.js';
|
|
18
|
+
/** Valid markdown format values */
|
|
19
|
+
const VALID_FORMATS = [
|
|
20
|
+
'github',
|
|
21
|
+
'commonmark',
|
|
22
|
+
'discord',
|
|
23
|
+
'reddit',
|
|
24
|
+
'rmarkdown',
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Detect input type from file extension.
|
|
28
|
+
* Writes error to stderr and exits with code 1 on unsupported extension.
|
|
29
|
+
*/
|
|
30
|
+
export function detectInputType(filePath) {
|
|
31
|
+
const ext = extname(filePath).toLowerCase();
|
|
32
|
+
const map = {
|
|
33
|
+
'.html': 'html',
|
|
34
|
+
'.htm': 'html',
|
|
35
|
+
'.docx': 'docx',
|
|
36
|
+
'.pdf': 'pdf',
|
|
37
|
+
'.xlsx': 'xlsx',
|
|
38
|
+
'.csv': 'csv',
|
|
39
|
+
};
|
|
40
|
+
const type = map[ext];
|
|
41
|
+
if (!type) {
|
|
42
|
+
process.stderr.write(`Unsupported file type: ${ext}\nSupported: .html, .htm, .docx, .pdf, .xlsx, .csv\n`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
return type;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validate the --format flag value.
|
|
49
|
+
* Writes error to stderr and exits with code 1 on unknown format.
|
|
50
|
+
*/
|
|
51
|
+
export function validateFormat(format) {
|
|
52
|
+
if (VALID_FORMATS.includes(format)) {
|
|
53
|
+
return format;
|
|
54
|
+
}
|
|
55
|
+
process.stderr.write(`Unknown format: "${format}"\nSupported formats: ${VALID_FORMATS.join(', ')}\n`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Read all data from stdin as a string.
|
|
60
|
+
*/
|
|
61
|
+
function readStdin() {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
let data = '';
|
|
64
|
+
process.stdin.setEncoding('utf8');
|
|
65
|
+
process.stdin.on('data', (chunk) => { data += chunk; });
|
|
66
|
+
process.stdin.on('end', () => resolve(data));
|
|
67
|
+
process.stdin.on('error', reject);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Convert HTML string to Markdown using ConversionEngine.
|
|
72
|
+
* Applies Atlassian normalization if the HTML is Atlassian and the user has the feature.
|
|
73
|
+
* Req 2.3, 2.4
|
|
74
|
+
*/
|
|
75
|
+
async function htmlToMarkdown(html, format, applyAtlassianNormalization = false) {
|
|
76
|
+
const processedHtml = applyAtlassianNormalization ? normalizeAtlassianHTML(html) : html;
|
|
77
|
+
const engine = new ConversionEngine();
|
|
78
|
+
const result = await engine.convert(processedHtml, {
|
|
79
|
+
format,
|
|
80
|
+
preserveTables: true,
|
|
81
|
+
preserveLists: true,
|
|
82
|
+
customRules: [],
|
|
83
|
+
});
|
|
84
|
+
return result.markdown;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Convert a binary file (DOCX/PDF/XLSX/CSV) buffer to Markdown.
|
|
88
|
+
* Req 11.1, 11.2, 11.3, 11.5
|
|
89
|
+
*/
|
|
90
|
+
async function binaryToMarkdown(buffer, type, format) {
|
|
91
|
+
// Convert Buffer → ArrayBuffer (Req 11.5: read as Buffer, not UTF-8)
|
|
92
|
+
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
93
|
+
const engine = new ConversionEngine();
|
|
94
|
+
switch (type) {
|
|
95
|
+
case 'docx': {
|
|
96
|
+
// Req 11.1: use mammoth integration
|
|
97
|
+
const result = await docxAdapter.parseToHtml(arrayBuffer);
|
|
98
|
+
const sanitized = sanitizeHTML(result.html);
|
|
99
|
+
const converted = await engine.convert(sanitized, {
|
|
100
|
+
format,
|
|
101
|
+
preserveTables: true,
|
|
102
|
+
preserveLists: true,
|
|
103
|
+
customRules: [],
|
|
104
|
+
});
|
|
105
|
+
return converted.markdown;
|
|
106
|
+
}
|
|
107
|
+
case 'pdf': {
|
|
108
|
+
// Req 11.2: use pdfjs-dist integration
|
|
109
|
+
const result = await pdfAdapter.parseToText(arrayBuffer);
|
|
110
|
+
const sanitized = sanitizeHTML(result.html);
|
|
111
|
+
const converted = await engine.convert(sanitized, {
|
|
112
|
+
format,
|
|
113
|
+
preserveTables: true,
|
|
114
|
+
preserveLists: true,
|
|
115
|
+
customRules: [],
|
|
116
|
+
});
|
|
117
|
+
return converted.markdown;
|
|
118
|
+
}
|
|
119
|
+
case 'xlsx':
|
|
120
|
+
case 'csv': {
|
|
121
|
+
// Req 11.3: use spreadsheet processing
|
|
122
|
+
const result = await spreadsheetAdapter.parseToHtml(arrayBuffer, type, 0);
|
|
123
|
+
const sanitized = sanitizeHTML(result.html);
|
|
124
|
+
const converted = await engine.convert(sanitized, {
|
|
125
|
+
format,
|
|
126
|
+
preserveTables: true,
|
|
127
|
+
preserveLists: true,
|
|
128
|
+
customRules: [],
|
|
129
|
+
});
|
|
130
|
+
return converted.markdown;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Main convert command action.
|
|
136
|
+
* Called by Commander when the user runs `formatferry [options]`.
|
|
137
|
+
*/
|
|
138
|
+
export async function convertCommand(options) {
|
|
139
|
+
// Validate format (default: github)
|
|
140
|
+
const format = validateFormat(options.format ?? 'github');
|
|
141
|
+
let markdown;
|
|
142
|
+
if (options.input) {
|
|
143
|
+
// File input mode (Req 7.4, 7.10)
|
|
144
|
+
let fileBuffer;
|
|
145
|
+
try {
|
|
146
|
+
fileBuffer = readFileSync(options.input);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
process.stderr.write(`Error: Cannot read file "${options.input}"\n`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const inputType = detectInputType(options.input);
|
|
153
|
+
if (inputType === 'html') {
|
|
154
|
+
// Text file — decode as UTF-8
|
|
155
|
+
const html = fileBuffer.toString('utf8');
|
|
156
|
+
// Req 2.3, 2.4: Atlassian entitlement check
|
|
157
|
+
let applyAtlassian = false;
|
|
158
|
+
if (isAtlassianHTML(html)) {
|
|
159
|
+
const provider = await resolveEntitlement();
|
|
160
|
+
if (!provider.hasFeature('atlassian')) {
|
|
161
|
+
process.stderr.write('Error: Atlassian HTML detected. A Premium license is required to process Atlassian content.\n' +
|
|
162
|
+
'Run `formatferry auth --license-key <KEY>` to activate your license.\n');
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
applyAtlassian = true;
|
|
166
|
+
}
|
|
167
|
+
markdown = await htmlToMarkdown(html, format, applyAtlassian);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Binary file — pass Buffer directly (Req 11.5)
|
|
171
|
+
markdown = await binaryToMarkdown(fileBuffer, inputType, format);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// Stdin mode (Req 7.3)
|
|
176
|
+
const html = await readStdin();
|
|
177
|
+
// Req 2.3, 2.4: Atlassian entitlement check for stdin
|
|
178
|
+
let applyAtlassian = false;
|
|
179
|
+
if (isAtlassianHTML(html)) {
|
|
180
|
+
const provider = await resolveEntitlement();
|
|
181
|
+
if (!provider.hasFeature('atlassian')) {
|
|
182
|
+
process.stderr.write('Error: Atlassian HTML detected. A Premium license is required to process Atlassian content.\n' +
|
|
183
|
+
'Run `formatferry auth --license-key <KEY>` to activate your license.\n');
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
applyAtlassian = true;
|
|
187
|
+
}
|
|
188
|
+
markdown = await htmlToMarkdown(html, format, applyAtlassian);
|
|
189
|
+
}
|
|
190
|
+
// Output (Req 7.5)
|
|
191
|
+
if (options.output) {
|
|
192
|
+
writeFileSync(options.output, markdown, 'utf8');
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
process.stdout.write(markdown);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare let CONFIG_PATH: string;
|
|
2
|
+
/** Override the config path (for testing only). */
|
|
3
|
+
export declare function _setConfigPathForTesting(p: string): void;
|
|
4
|
+
export interface StoredConfig {
|
|
5
|
+
licenseKey?: string;
|
|
6
|
+
tier?: 'free' | 'premium';
|
|
7
|
+
features?: string[];
|
|
8
|
+
expiresAt?: string | null;
|
|
9
|
+
lastValidated?: string;
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Read the stored config. Returns `null` if the file is missing or corrupted.
|
|
14
|
+
* Silently discards errors so the CLI always falls back to free tier (Req 10.7).
|
|
15
|
+
*/
|
|
16
|
+
export declare function readConfig(): StoredConfig | null;
|
|
17
|
+
/**
|
|
18
|
+
* Persist config to disk. Creates parent directories as needed.
|
|
19
|
+
* Sets mode 0o600 on POSIX (owner read/write only) per Req 9.5.
|
|
20
|
+
*/
|
|
21
|
+
export declare function writeConfig(config: StoredConfig): void;
|
|
22
|
+
/**
|
|
23
|
+
* Reset the config to an empty object (effectively clearing all stored values).
|
|
24
|
+
* Silently ignores errors (e.g. if the file doesn't exist yet).
|
|
25
|
+
*/
|
|
26
|
+
export declare function clearConfig(): void;
|
|
27
|
+
//# sourceMappingURL=config-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"AAsBA,eAAO,IAAI,WAAW,QAAgC,CAAC;AAEvD,mDAAmD;AACnD,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAExD;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG,IAAI,CAOhD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAGtD;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAKlC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform config store for FormatFerry CLI.
|
|
3
|
+
*
|
|
4
|
+
* Config path:
|
|
5
|
+
* - POSIX: ~/.config/formatferry/config.json (Req 9.2)
|
|
6
|
+
* - Windows: %APPDATA%\formatferry\config.json (Req 9.2)
|
|
7
|
+
*
|
|
8
|
+
* File permissions:
|
|
9
|
+
* - POSIX: 0o600 (owner read/write only) (Req 9.5)
|
|
10
|
+
* - Windows: 0o600 is silently ignored by Node.js — security relies on
|
|
11
|
+
* %APPDATA% being inside the user's profile directory, which is protected
|
|
12
|
+
* by Windows NTFS user account ACLs. No additional code is needed.
|
|
13
|
+
*
|
|
14
|
+
* Corrupted or missing config → returns null → Free tier (Req 10.7)
|
|
15
|
+
*/
|
|
16
|
+
import envPaths from 'env-paths';
|
|
17
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
18
|
+
import { dirname } from 'path';
|
|
19
|
+
const paths = envPaths('formatferry', { suffix: '' });
|
|
20
|
+
// Exported so tests can override via module-level patching
|
|
21
|
+
export let CONFIG_PATH = `${paths.config}/config.json`;
|
|
22
|
+
/** Override the config path (for testing only). */
|
|
23
|
+
export function _setConfigPathForTesting(p) {
|
|
24
|
+
CONFIG_PATH = p;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read the stored config. Returns `null` if the file is missing or corrupted.
|
|
28
|
+
* Silently discards errors so the CLI always falls back to free tier (Req 10.7).
|
|
29
|
+
*/
|
|
30
|
+
export function readConfig() {
|
|
31
|
+
try {
|
|
32
|
+
const raw = readFileSync(CONFIG_PATH, 'utf-8');
|
|
33
|
+
return JSON.parse(raw);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null; // Missing or corrupted → Free tier
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Persist config to disk. Creates parent directories as needed.
|
|
41
|
+
* Sets mode 0o600 on POSIX (owner read/write only) per Req 9.5.
|
|
42
|
+
*/
|
|
43
|
+
export function writeConfig(config) {
|
|
44
|
+
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
45
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Reset the config to an empty object (effectively clearing all stored values).
|
|
49
|
+
* Silently ignores errors (e.g. if the file doesn't exist yet).
|
|
50
|
+
*/
|
|
51
|
+
export function clearConfig() {
|
|
52
|
+
try {
|
|
53
|
+
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
54
|
+
writeFileSync(CONFIG_PATH, '{}', { mode: 0o600 });
|
|
55
|
+
}
|
|
56
|
+
catch { /* ignore */ }
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;AAEtD,2DAA2D;AAC3D,MAAM,CAAC,IAAI,WAAW,GAAG,GAAG,KAAK,CAAC,MAAM,cAAc,CAAC;AAEvD,mDAAmD;AACnD,MAAM,UAAU,wBAAwB,CAAC,CAAS;IAChD,WAAW,GAAG,CAAC,CAAC;AAClB,CAAC;AAWD;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,mCAAmC;IAClD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC9C,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,aAAa,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI startup license validation with caching (Design §5.5)
|
|
3
|
+
* Validates: Requirements 10.1–10.7
|
|
4
|
+
*/
|
|
5
|
+
import { type EntitlementProvider } from '../../../src/shared/entitlement-service.js';
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the entitlement provider for the current CLI session.
|
|
8
|
+
* Called once at CLI startup before any command runs.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveEntitlement(): Promise<EntitlementProvider>;
|
|
11
|
+
//# sourceMappingURL=entitlement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlement.d.ts","sourceRoot":"","sources":["../src/entitlement.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAGL,KAAK,mBAAmB,EAGzB,MAAM,4CAA4C,CAAC;AAepD;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CA0FvE"}
|