make-pptx
npx skills add https://github.com/window-ook/fit-checker --skill make-pptx
Agent 安装分布
Skill 文档
PPTX ìì± ì¤í¬
HTML íë ì í ì´ì ì PPTXë¡ ë³ííê±°ë, PptxGenJS를 ì§ì íì©íì¬ PowerPoint íì¼ì ìì±í©ëë¤.
íì ì구ì¬í
Pretendard í°í¸
모ë PPTX íì¼ì ë°ëì Pretendard í°í¸ë¥¼ ì¬ì©í´ì¼ í©ëë¤.
ìì¤í ì Pretendardê° ìë ê²½ì°:
- https://github.com/orioncactus/pretendard ìì ë¤ì´ë¡ë
- ìì¤í ì í°í¸ ì¤ì¹
ìì¡´ì±
npm install pptxgenjs sharp
ìí¬íë¡ì°
ìµì 1: PptxGenJS ì§ì ì¬ì© (ê¶ì¥)
PptxGenJS를 ì¬ì©íì¬ íë¡ê·¸ë매í±íê² PPTX를 ìì±í©ëë¤.
기본 구조
const PptxGenJS = require('pptxgenjs');
// íë ì í
ì´ì
ìì±
const pptx = new PptxGenJS();
// ë©íë°ì´í° ì¤ì
pptx.author = 'Fit Checker';
pptx.title = 'ì í©ì± ë¶ì 리í¬í¸';
pptx.subject = '[íì¬ëª
] x [ì§ììëª
]';
// ë ì´ìì ì¤ì (16:9)
pptx.defineLayout({ name: 'CUSTOM', width: 13.33, height: 7.5 });
pptx.layout = 'CUSTOM';
ì¬ë¼ì´ë 1: íì´í & 매ì¹ì¨
const slide1 = pptx.addSlide();
// ë°°ê²½ì
slide1.background = { color: 'F9FAFB' };
// íì´í
slide1.addText('[íì¬ëª
] x [ì§ììëª
]', {
x: 0.5,
y: 0.5,
w: '90%',
h: 1,
fontSize: 40,
fontFace: 'Pretendard',
bold: true,
color: '111827',
align: 'center',
});
// ìë¸íì´í
slide1.addText('ì í©ì± ë¶ì 리í¬í¸', {
x: 0.5,
y: 1.3,
w: '90%',
h: 0.5,
fontSize: 24,
fontFace: 'Pretendard',
color: '6B7280',
align: 'center',
});
// 매ì¹ì¨ ìí (ëë ì°¨í¸)
slide1.addChart(
pptx.ChartType.doughnut,
[
{
name: 'Match',
labels: ['매ì¹', 'ë머ì§'],
values: [78, 22], // 매ì¹ì¨ì ë°ë¼ ì¡°ì
},
],
{
x: 4.5,
y: 2,
w: 4,
h: 4,
chartColors: ['10B981', 'E5E7EB'],
showLegend: false,
showTitle: false,
holeSize: 70,
}
);
// 매ì¹ì¨ í
ì¤í¸ (ì°¨í¸ ì¤ì)
slide1.addText('78%', {
x: 5.5,
y: 3.5,
w: 2,
h: 1,
fontSize: 48,
fontFace: 'Pretendard',
bold: true,
color: '10B981',
align: 'center',
});
ì¬ë¼ì´ë 2: ì ë§ë ì
const slide2 = pptx.addSlide();
slide2.addText('â
ì ë§ë ì ', {
x: 0.5,
y: 0.3,
w: '90%',
fontSize: 32,
fontFace: 'Pretendard',
bold: true,
color: '111827',
});
// í
ì´ë¸ ë°ì´í°
const tableData = [
[
{ text: 'í목', options: { bold: true, fill: '2563EB', color: 'FFFFFF' } },
{
text: 'íì¬ ì구ì¬í',
options: { bold: true, fill: '2563EB', color: 'FFFFFF' },
},
{
text: 'ì§ìì ë³´ì ìë',
options: { bold: true, fill: '2563EB', color: 'FFFFFF' },
},
{
text: 'ì í©ë',
options: { bold: true, fill: '2563EB', color: 'FFFFFF' },
},
],
[
{ text: '기ì ì¤í' },
{ text: 'React, TypeScript' },
{ text: 'Next.js, React, TypeScript' },
{ text: 'â
ìë²½ ì¼ì¹', options: { color: '10B981' } },
],
// ì¶ê° í...
];
slide2.addTable(tableData, {
x: 0.5,
y: 1,
w: 12,
fontFace: 'Pretendard',
fontSize: 14,
border: { type: 'solid', pt: 1, color: 'E5E7EB' },
align: 'left',
valign: 'middle',
});
ì¬ë¼ì´ë 3: ë§ì§ ìë ì
const slide3 = pptx.addSlide();
slide3.addText('â ï¸ ë§ì§ ìë ì ', {
x: 0.5,
y: 0.3,
w: '90%',
fontSize: 32,
fontFace: 'Pretendard',
bold: true,
color: '111827',
});
// ì¹´ë ì¤íì¼ ë°ì¤
slide3.addShape(pptx.ShapeType.rect, {
x: 0.5,
y: 1,
w: 5.5,
h: 2.5,
fill: 'FEF2F2',
line: { color: 'EF4444', pt: 2, dashType: 'solid' },
});
slide3.addText('â ê²½ë ¥ ìê±´', {
x: 0.7,
y: 1.2,
w: 5,
fontSize: 20,
fontFace: 'Pretendard',
bold: true,
color: 'EF4444',
});
slide3.addText('ì구: 3ë
ì´ì\në³´ì : ì ì
', {
x: 0.7,
y: 1.8,
w: 5,
fontSize: 16,
fontFace: 'Pretendard',
color: '111827',
});
ì¬ë¼ì´ë 4: ë³´ì í¬ì¸í¸
const slide4 = pptx.addSlide();
slide4.addText('ð¡ ë³´ì í¬ì¸í¸', {
x: 0.5,
y: 0.3,
w: '90%',
fontSize: 32,
fontFace: 'Pretendard',
bold: true,
color: '111827',
});
// ì°ì ìì ë°°ì§
slide4.addShape(pptx.ShapeType.roundRect, {
x: 0.5,
y: 1,
w: 1.2,
h: 0.4,
fill: 'FEE2E2',
});
slide4.addText('ëì', {
x: 0.5,
y: 1,
w: 1.2,
h: 0.4,
fontSize: 12,
fontFace: 'Pretendard',
bold: true,
color: '991B1B',
align: 'center',
valign: 'middle',
});
// ë³´ì í목 ë´ì©
slide4.addText('[ë³´ì í목ëª
]', {
x: 2,
y: 1,
w: 10,
fontSize: 18,
fontFace: 'Pretendard',
bold: true,
color: '111827',
});
slide4.addText('ð 근거: [ì±ì© ê³µê³ ìì ë°ì·í 근거]', {
x: 2,
y: 1.6,
w: 10,
fontSize: 14,
fontFace: 'Pretendard',
color: '6B7280',
});
íì¼ ì ì¥
// íì¼ë¡ ì ì¥ (Node.js)
pptx
.writeFile({ fileName: 'output/fit-result.pptx' })
.then((fileName) => console.log(`Created: ${fileName}`));
// ëë Bufferë¡ ë°í
const buffer = await pptx.write({ outputType: 'nodebuffer' });
ìµì 2: HTML to PPTX ë³í
HTML íì¼ì PPTXë¡ ë³íí´ì¼ íë ê²½ì°, html2pptx.md 참조 문ì를 íì¸íì¸ì.
ì¤ì 주ìì¬í
1. ìì ì½ë
PptxGenJSìì # ìì´ ì¬ì©í´ì¼ í©ëë¤.
// â
ì¬ë°ë¦
{
color: '10B981';
}
{
fill: 'F9FAFB';
}
// â ìëª»ë¨ (íì¼ ìì ê°ë¥)
{
color: '#10B981';
}
{
fill: '#F9FAFB';
}
2. í°í¸ ì§ì
모ë í ì¤í¸ ììì Pretendard í°í¸ë¥¼ ëª ìì ì¼ë¡ ì§ì :
{
fontFace: 'Pretendard',
// ...
}
3. íê¸ í ì¤í¸
íê¸ í
ì¤í¸ë ìëì¼ë¡ ì²ë¦¬ëì§ë§, ì¤ë°ê¿ì´ íìí ê²½ì° \n ì¬ì©:
slide.addText('첫 ë²ì§¸ ì¤\në ë²ì§¸ ì¤', { ... });
4. ì´ëª¨ì§ ì¬ì©
ì´ëª¨ì§ë ì¼ë¶ íê²½ìì íìëì§ ìì ì ììµëë¤. ì¤ìí ì ë³´ë ì´ëª¨ì§ ì¸ì í ì¤í¸ë¡ë íííì¸ì.
ì¶ë ¥ íì¼
결과물ì output/ ëë í 리ì ì ì¥:
output/
âââ fit-check-result-YYYY-MM-DD.pptx
âââ fit-check-result-YYYY-MM-DD.html (ë°±ì
ì©)
ì»¬ë¬ íë í¸ ì°¸ì¡°
| ì©ë | ìì ì½ë | ì¤ëª |
|---|---|---|
| Primary | 2563EB |
주ì ê°ì¡°ì |
| Success | 10B981 |
ê¸ì ì /ìë£ |
| Warning | F59E0B |
주ì/ì í¸ |
| Danger | EF4444 |
ë¶ì ì /íì 미충족 |
| Neutral | 6B7280 |
ì¤ë¦½/ë³´ì¡° í ì¤í¸ |
| Background | F9FAFB |
ë°°ê²½ì |
| Text Primary | 111827 |
주ì í ì¤í¸ |
| Text Secondary | 6B7280 |
ë³´ì¡° í ì¤í¸ |
| Border | E5E7EB |
í ë리/구ë¶ì |
ì¶ê° 참조 문ì
ìì¸í 기ì ì ë³´ë ë¤ì 문ì를 참조íì¸ì:
html2pptx.md– HTML to PPTX ë³í ìì¸ ê°ì´ëooxml.md– OOXML ì§ì ì¡°ì 기ì 참조