Added plan.md with complete architecture for format-agnostic content generation: - Support for Markdown, HTML, Plain Text, JSON formats - New FormatExporter module with neutral data structure - Integration strategy with existing ContentAssembly and ArticleStorage - Bonus features: SEO metadata generation, readability scoring, WordPress Gutenberg format - Implementation roadmap with 4 phases (6h total estimated) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
82 lines
3.3 KiB
JavaScript
82 lines
3.3 KiB
JavaScript
import test from 'node:test';
|
||
import assert from 'node:assert';
|
||
import { safeImport } from '../_helpers/path.js';
|
||
import { MemoryArticleStorage } from '../_helpers/memoryStorage.js';
|
||
import { MockLLMManager } from '../_helpers/mockLLMManager.js';
|
||
|
||
function skip(msg) { console.warn('[SKIP]', msg); }
|
||
|
||
test('Pipeline dry-run with mock LLM returns structured article', async (t) => {
|
||
const extr = safeImport('ElementExtraction');
|
||
const gen = safeImport('ContentGeneration');
|
||
const asm = safeImport('ContentAssembly');
|
||
const enh = safeImport('SelectiveEnhancement');
|
||
const miss = safeImport('MissingKeywords');
|
||
const utils= safeImport('Utils');
|
||
const stor = new MemoryArticleStorage();
|
||
const llm = new MockLLMManager();
|
||
|
||
if (![extr,gen,asm,enh,miss].every(r=>r.ok)) {
|
||
skip('One or more pipeline modules missing; dry-run skipped.');
|
||
return;
|
||
}
|
||
|
||
const ElementExtraction = extr.mod;
|
||
const ContentGeneration = gen.mod;
|
||
const ContentAssembly = asm.mod;
|
||
const SelectiveEnh = enh.mod;
|
||
const MissingKeywords = miss.mod;
|
||
|
||
// Inputs minimaux (adapte selon tes contrats)
|
||
const inputs = {
|
||
instructions: 'Write about hunting jackets: materials, weatherproofing, sizes.',
|
||
persona: { name: 'Persona A', tone: 'pragmatic' },
|
||
template: '<article><h1>{{title}}</h1>{{body}}</article>',
|
||
seed: 42
|
||
};
|
||
|
||
// Étape 1: extraction
|
||
const elements = await (ElementExtraction.extractElements
|
||
? ElementExtraction.extractElements(inputs)
|
||
: { topics: ['materials', 'weatherproofing', 'sizes'] });
|
||
|
||
assert.ok(elements, 'elements should be produced');
|
||
|
||
// Étape 2: génération (mock via injection simple si API supporte un client)
|
||
// Si ContentGeneration accepte un LLM param, on l’utilise, sinon on simule simple:
|
||
const parts = await (ContentGeneration.generateArticleParts
|
||
? ContentGeneration.generateArticleParts({ inputs, elements, llm })
|
||
: (Array.isArray(elements.topics) ? elements.topics : Object.keys(elements))
|
||
.map(t => ({ key:String(t), text:`MOCK SECTION ${t}` })));
|
||
|
||
|
||
assert.ok(parts && Array.isArray(parts), 'parts array expected');
|
||
assert.ok(parts.length > 0, 'non-empty parts');
|
||
|
||
// Étape 3: enhancement sélectif (facultatif)
|
||
const enhanced = await (SelectiveEnh.enhanceParts
|
||
? SelectiveEnh.enhanceParts({ parts, llm })
|
||
: parts);
|
||
|
||
assert.ok(enhanced && Array.isArray(enhanced), 'enhanced parts array');
|
||
|
||
// Étape 4: missing keywords
|
||
const completed = await (MissingKeywords.fillMissingKeywords
|
||
? MissingKeywords.fillMissingKeywords({ parts: enhanced, targetKeywords:['chasse','imperméable'] , llm })
|
||
: enhanced);
|
||
|
||
// Étape 5: assemblage
|
||
const html = await (ContentAssembly.assembleArticle
|
||
? ContentAssembly.assembleArticle({ template: inputs.template, parts: completed, meta:{title:'Veste de chasse: guide complet'} })
|
||
: `<article>${completed.map(p=>`<section>${p.text}</section>`).join('')}</article>`);
|
||
|
||
assert.equal(typeof html, 'string');
|
||
assert.ok(html.includes('<article'), 'html should be article-like');
|
||
|
||
// “Stockage final” simulé
|
||
const key = JSON.stringify(inputs); // simplifié
|
||
await stor.writeFinal(key, { html });
|
||
|
||
assert.ok(await stor.hasFinal(key), 'final should be stored');
|
||
});
|