diff --git a/asset/official-single-page-footer.css b/asset/official-single-page-footer.css
index dce1754..25a1930 100644
--- a/asset/official-single-page-footer.css
+++ b/asset/official-single-page-footer.css
@@ -8,15 +8,9 @@ footer {
padding-top: 30px !important;
text-align: center;
font-size: 20px;
- letter-spacing: 2px;
line-height: 1.5em;
font-weight: bold;
height: auto !important;
padding-bottom: 30px !important;
border-bottom: 1px solid #333 !important;
}
-
-footer::after {
- content: "O O O O O O\AO O O O O O O";
- white-space: pre;
-}
\ No newline at end of file
diff --git a/lib/index.d.ts b/lib/index.d.ts
index 3dcb5f5..f5603aa 100644
--- a/lib/index.d.ts
+++ b/lib/index.d.ts
@@ -1,4 +1,5 @@
/** @format */
+///
import { Command, flags } from "@oclif/command";
declare class Zigzi extends Command {
static description: string;
@@ -19,6 +20,8 @@ declare class Zigzi extends Command {
marp(): Promise;
toHtml(): Promise;
toPdf(): Promise;
+ toPdfOfficial(): Promise;
+ mergePdfBuffers(target1: Buffer, target2: Buffer): Promise;
setVSCodeSetting(): Promise;
}
export = Zigzi;
diff --git a/lib/index.js b/lib/index.js
index ae19ae5..851c163 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -6,8 +6,12 @@ const child_process = require("child_process");
const marked = require("marked");
const puppeteer = require("puppeteer");
const shell = require("shelljs");
+const pdfParse = require("pdf-parse");
+const opentype = require("opentype.js");
+const fm = require("front-matter");
const command_1 = require("@oclif/command");
const fs_1 = require("fs");
+const pdf_lib_1 = require("pdf-lib");
const convertCss = {
zb_ppt: __dirname + "/../asset/ppt.css",
zb_ppt_large: __dirname + "/../asset/ppt-large.css",
@@ -36,7 +40,12 @@ class Zigzi extends command_1.Command {
else {
await this.toHtml();
if (output === "pdf") {
- await this.toPdf();
+ if (flags.template === "zb_official") {
+ await this.toPdfOfficial();
+ }
+ else {
+ await this.toPdf();
+ }
}
}
}
@@ -44,7 +53,9 @@ class Zigzi extends command_1.Command {
async marp() {
const { args, flags } = this.parse(Zigzi);
let md = fs.readFileSync(this.file, "utf8");
- const cssFile = (md.indexOf("theme: ppt-large") > 0) ? convertCss["zb_ppt_large"] : convertCss["zb_ppt"];
+ const cssFile = md.indexOf("theme: ppt-large") > 0
+ ? convertCss["zb_ppt_large"]
+ : convertCss["zb_ppt"];
const pdfFileName = `${this.file.replace(".md", ".pdf")}`;
await child_process.execSync(`npx @marp-team/marp-cli@latest --allow-local-files ${this.file} -o ${pdfFileName} --theme ${cssFile}`);
}
@@ -52,19 +63,25 @@ class Zigzi extends command_1.Command {
const { flags } = this.parse(Zigzi);
const cssType = convertCss[this.converType];
const htmlFileName = `${this.file.replace(".md", ".html")}`;
- let md = fs.readFileSync(this.file, "utf8");
+ const md = fs.readFileSync(this.file, "utf8");
+ let css = fs.readFileSync(cssType, "utf8");
const pageBreak = //g;
- md = md.replace(pageBreak, `
`);
- md = md.replace(RegExp(//g), "");
+ const modifiedMd = md
+ .replace(pageBreak, `
`)
+ .replace(RegExp(//g), "")
+ .replace(/^---$.*^---$/ms, "");
let markedHtml;
if (flags.template === "zb_official") {
- markedHtml = ` ${marked(md)}`;
+ const { attributes: { 주소, 전화번호 } = { 주소: "", 전화번호: "" }, } = fm(md);
+ markedHtml = ` ${marked(modifiedMd)}`;
+ css += `header::after{
+ content: "${주소}\\ATel) ${전화번호}"
+ }`;
}
else {
- markedHtml = marked(md);
+ markedHtml = marked(modifiedMd);
}
- const css = fs.readFileSync(cssType, "utf8");
const html = `
@@ -84,9 +101,6 @@ class Zigzi extends command_1.Command {
const { flags } = this.parse(Zigzi);
const htmlFileName = `${this.file.replace(".md", ".html")}`;
const pdfFileName = `${this.file.replace(".md", ".pdf")}`;
- const headerFooterTemplate = (flags.template === "zb_doc") ? {
- displayHeaderFooter: true
- } : {};
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(`file://${path.resolve(htmlFileName)}`, {
@@ -99,7 +113,7 @@ class Zigzi extends command_1.Command {
printBackground: true,
headerTemplate: ``,
footerTemplate: ``,
- displayHeaderFooter: (flags.template === "zb_doc"),
+ displayHeaderFooter: flags.template === "zb_doc",
margin: {
top: 50,
bottom: 50,
@@ -110,13 +124,111 @@ class Zigzi extends command_1.Command {
await browser.close();
await fs.unlinkSync(`${htmlFileName}`);
}
+ async toPdfOfficial() {
+ const md = fs.readFileSync(this.file, "utf8");
+ const { attributes: { footer = [] }, } = fm(md);
+ const htmlFileName = `${this.file.replace(".md", ".html")}`;
+ const pdfFileName = `${this.file.replace(".md", ".pdf")}`;
+ const browser = await puppeteer.launch();
+ const page = await browser.newPage();
+ await page.goto(`file://${path.resolve(htmlFileName)}`, {
+ waitUntil: "networkidle2",
+ timeout: 60000 * 2,
+ });
+ await page.emulateMediaType("screen");
+ const font = opentype.loadSync(path.resolve(__dirname, "../asset/SpoqaHanSansBold.ttf"));
+ const footerSvg = footer
+ .map((str) => {
+ const p = font.getPath(str, 0, 0, 21);
+ const { x1, x2, y1, y2 } = p.getBoundingBox();
+ const height = y2 - y1;
+ const width = x2 - x1;
+ const svgPath = p.toSVG(2);
+ return ``;
+ })
+ .join("");
+ const headerTemplate = "";
+ const footerTemplate = `
+
+
+ `;
+ const baseOpt = {
+ format: "a4",
+ path: `${path.resolve(pdfFileName)}`,
+ headerTemplate,
+ footerTemplate,
+ displayHeaderFooter: true,
+ margin: {
+ top: 50,
+ bottom: 50,
+ left: 58,
+ right: 58,
+ },
+ timeout: 1000 * 60 * 10,
+ };
+ await page.pdf(baseOpt);
+ const dataBuffer = fs.readFileSync(path.resolve(pdfFileName));
+ const pdfInfo = await pdfParse(dataBuffer);
+ const numPages = pdfInfo.numpages;
+ if (numPages === 1) {
+ await page.addStyleTag({
+ path: path.resolve(__dirname, "../asset/official-single-page-footer.css"),
+ });
+ await page.addStyleTag({
+ content: `
+ footer::after {
+ content: "${footer.join("\\A")}";
+ white-space: pre;
+ }`,
+ });
+ await page.pdf(Object.assign(Object.assign({}, baseOpt), { displayHeaderFooter: false }));
+ }
+ else {
+ const restBuffer = await page.pdf(Object.assign(Object.assign({}, baseOpt), { displayHeaderFooter: false, pageRanges: `-${numPages - 1}` }));
+ const lastPdfName = `${pdfFileName}-last.pdf`;
+ const lastBuffer = await page.pdf(Object.assign(Object.assign({}, baseOpt), { displayHeaderFooter: true, pageRanges: `${numPages}`, path: lastPdfName }));
+ await fs.unlinkSync(lastPdfName);
+ const mergedPdfBuffer = await this.mergePdfBuffers(restBuffer, lastBuffer);
+ await fs.writeFileSync(`${path.resolve(pdfFileName)}`, mergedPdfBuffer);
+ }
+ await browser.close();
+ await fs.unlinkSync(`${htmlFileName}`);
+ }
+ async mergePdfBuffers(target1, target2) {
+ const pdf1 = await pdf_lib_1.PDFDocument.load(target1);
+ const pdf2 = await pdf_lib_1.PDFDocument.load(target2);
+ const mergedPdf = await pdf_lib_1.PDFDocument.create();
+ const copiedPagesA = await mergedPdf.copyPages(pdf1, pdf1.getPageIndices());
+ copiedPagesA.forEach((page) => mergedPdf.addPage(page));
+ const copiedPagesB = await mergedPdf.copyPages(pdf2, pdf2.getPageIndices());
+ copiedPagesB.forEach((page) => mergedPdf.addPage(page));
+ return await mergedPdf.save();
+ }
async setVSCodeSetting() {
const location = shell.exec("pwd");
- const setting_location = process.platform === "win32" ? "%APPDATA%\/Code\/User\/" : "~/Library/Application Support/Code/User/";
+ const setting_location = process.platform === "win32"
+ ? "%APPDATA%/Code/User/"
+ : "~/Library/Application Support/Code/User/";
JSON.stringify;
shell.cd(setting_location);
shell.exec("pwd");
- const settingsBuffer = await (0, fs_1.readFileSync)("settings.json", { encoding: "utf8" });
+ const settingsBuffer = await (0, fs_1.readFileSync)("settings.json", {
+ encoding: "utf8",
+ });
let settings = settingsBuffer;
const css = `
"https://zigbang.github.io/zigzi/asset/ppt.css",
@@ -151,7 +263,7 @@ Zigzi.flags = {
}),
vscode: command_1.flags.boolean({
description: "vscode markdown template setting",
- })
+ }),
};
Zigzi.args = [
{
diff --git a/package.json b/package.json
index 501d975..1ae15c5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "zigzi",
- "version": "1.0.6",
+ "version": "1.0.11",
"author": "ZIGBANG Co., Ltd.",
"keywords": [
"zigbang",
diff --git a/sample/official.md b/sample/official.md
index ed5add1..cd16221 100644
--- a/sample/official.md
+++ b/sample/official.md
@@ -30,13 +30,10 @@ _-- 아래 --_
붙임 :
- 붙임 내용
-
-
# test 1
테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트
-
# test 2
diff --git a/sample/official.pdf b/sample/official.pdf
index 82456a6..5775f76 100644
Binary files a/sample/official.pdf and b/sample/official.pdf differ
diff --git a/src/index.ts b/src/index.ts
index 6af9e8e..d37a99f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -202,15 +202,15 @@ class Zigzi extends Command {
const footerTemplate = `