@neobiotechlabs/neobiotech-dev-agent 0.1.16 → 0.1.18
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -2
- package/dist/fonts/LICENSE.txt +94 -0
- package/dist/fonts/Pretendard-Bold.ttf +0 -0
- package/dist/fonts/Pretendard-Regular.ttf +0 -0
- package/dist/index.js +122 -122
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/vendor/dev-docs-templates/templates/mdr_docs/PA/configuration-management-plan.md +112 -0
- package/vendor/dev-docs-templates/templates/mdr_docs/PA/security-management-plan.md +101 -0
- package/vendor/dev-docs-templates/templates/mdr_docs/PA/software-development-maintenance-plan.md +12 -24
package/dist/index.js
CHANGED
|
@@ -3780,6 +3780,7 @@ var require_fast_uri = __commonJS({
|
|
|
3780
3780
|
return uriTokens.join("");
|
|
3781
3781
|
}
|
|
3782
3782
|
var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
3783
|
+
var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
|
|
3783
3784
|
function getParseError(parsed, matches) {
|
|
3784
3785
|
if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
|
|
3785
3786
|
return 'URI path must start with "/" when authority is present.';
|
|
@@ -3809,6 +3810,11 @@ var require_fast_uri = __commonJS({
|
|
|
3809
3810
|
uri = "//" + uri;
|
|
3810
3811
|
}
|
|
3811
3812
|
}
|
|
3813
|
+
const authorityMatch = uri.match(AUTHORITY_PREFIX);
|
|
3814
|
+
if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
|
|
3815
|
+
parsed.error = "URI authority must not contain a literal backslash.";
|
|
3816
|
+
malformedAuthorityOrPort = true;
|
|
3817
|
+
}
|
|
3812
3818
|
const matches = uri.match(URI_PARSE);
|
|
3813
3819
|
if (matches) {
|
|
3814
3820
|
parsed.scheme = matches[1];
|
|
@@ -17100,8 +17106,8 @@ var require_adm_zip = __commonJS({
|
|
|
17100
17106
|
return null;
|
|
17101
17107
|
}
|
|
17102
17108
|
function fixPath(zipPath) {
|
|
17103
|
-
const { join:
|
|
17104
|
-
return
|
|
17109
|
+
const { join: join5, normalize, sep } = pth.posix;
|
|
17110
|
+
return join5(pth.isAbsolute(zipPath) ? "/" : ".", normalize(sep + zipPath.split("\\").join(sep) + sep));
|
|
17105
17111
|
}
|
|
17106
17112
|
function filenameFilter(filterfn) {
|
|
17107
17113
|
if (filterfn instanceof RegExp) {
|
|
@@ -160536,7 +160542,7 @@ var PA_DOCUMENTS = [
|
|
|
160536
160542
|
"[Classification]",
|
|
160537
160543
|
"[SW Development Plan]",
|
|
160538
160544
|
"[Risk Management Plan]",
|
|
160539
|
-
"[Security
|
|
160545
|
+
"[Security Management Plan]",
|
|
160540
160546
|
"[Configuration Management Plan]"
|
|
160541
160547
|
];
|
|
160542
160548
|
var EA_DOCUMENTS = [
|
|
@@ -160741,7 +160747,7 @@ var TOOL_CATALOG = [
|
|
|
160741
160747
|
{ name: "jira_init_project", description: "\uD504\uB85C\uC81D\uD2B8 \uD3F4\uB354\uC5D0 Jira \uD504\uB85C\uC81D\uD2B8 \uD0A4 \uCD08\uAE30 \uC124\uC815 (CLAUDE.md \uC5C5\uB370\uC774\uD2B8)", category: "\uCD08\uAE30 \uC124\uC815" },
|
|
160742
160748
|
{ name: "help", description: "\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB3C4\uAD6C \uCE74\uD0C8\uB85C\uADF8\uC640 \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uAC00\uC774\uB4DC \uC870\uD68C (topic \uC9C0\uC815 \uAC00\uB2A5)", category: "\uB3C4\uC6C0\uB9D0" },
|
|
160743
160749
|
// 문서 첨부 — 마크다운 → PDF 변환 + Jira 첨부
|
|
160744
|
-
{ name: "markdown_to_pdf", description: "\uB9C8\uD06C\uB2E4\uC6B4 \u2192 PDF \uBCC0\uD658 (\
|
|
160750
|
+
{ name: "markdown_to_pdf", description: "\uB9C8\uD06C\uB2E4\uC6B4 \u2192 PDF \uBCC0\uD658 (\uBC88\uB4E4 Pretendard Regular+Bold, \uD45C\uC9C0/\uBA38\uB9AC\uB9D0\xB7\uAF2C\uB9AC\uB9D0 \uC635\uC158)", category: "\uBB38\uC11C \uCCA8\uBD80" },
|
|
160745
160751
|
{ name: "jira_attach_file", description: "Jira \uC774\uC288\uC5D0 \uD30C\uC77C \uCCA8\uBD80 (file_path \uB610\uB294 base64 \uC785\uB825, 50MB \uCD08\uACFC \uC2DC warning, 100MB \uCD08\uACFC \uC2DC hard limit)", category: "\uBB38\uC11C \uCCA8\uBD80" },
|
|
160746
160752
|
{ name: "jira_attach_pdf_from_markdown", description: "\uB9C8\uD06C\uB2E4\uC6B4 \u2192 PDF \u2192 Jira \uCCA8\uBD80 \uC6D0\uC0F7 (description \uBBF8\uC218\uC815, summary \uCF54\uBA58\uD2B8 \uC635\uC158)", category: "\uBB38\uC11C \uCCA8\uBD80" },
|
|
160747
160753
|
{
|
|
@@ -160771,7 +160777,7 @@ var WORKFLOWS = {
|
|
|
160771
160777
|
"4. [Classification] \u2192 \uBD84\uB958 \uD2F0\uCF13 (MDR Class \uD310\uC815)",
|
|
160772
160778
|
"5. [SW Development Plan] \u2192 \uAC1C\uBC1C \uACC4\uD68D\uC11C \uC791\uC131",
|
|
160773
160779
|
"6. [Risk Management Plan] \u2192 \uB9AC\uC2A4\uD06C \uAD00\uB9AC \uACC4\uD68D\uC11C \uC791\uC131",
|
|
160774
|
-
"7. [Security
|
|
160780
|
+
"7. [Security Management Plan] \u2192 \uBCF4\uC548 \uAD00\uB9AC \uACC4\uD68D\uC11C (IEC 81001-5-1)",
|
|
160775
160781
|
"8. [Configuration Management Plan] \u2192 \uD615\uC0C1 \uAD00\uB9AC \uACC4\uD68D\uC11C",
|
|
160776
160782
|
"",
|
|
160777
160783
|
"\uC0AC\uC6A9\uC131 \uACF5\uD559 (IEC 62366-1)\uB3C4 PA \uB2E8\uACC4\uC5D0\uC11C \uC2DC\uC791:",
|
|
@@ -161471,6 +161477,8 @@ var TEMPLATE_PATHS = {
|
|
|
161471
161477
|
risk_management_plan: { path: "mdr_docs/PA/risk-management-plan.md", mode: "freeform", domain: "mdr", gate: "PA" },
|
|
161472
161478
|
mdr_classification_document: { path: "mdr_docs/PA/mdr-classification-document.md", mode: "freeform", domain: "mdr", gate: "PA" },
|
|
161473
161479
|
software_development_maintenance_plan: { path: "mdr_docs/PA/software-development-maintenance-plan.md", mode: "freeform", domain: "mdr", gate: "PA" },
|
|
161480
|
+
configuration_management_plan: { path: "mdr_docs/PA/configuration-management-plan.md", mode: "freeform", domain: "mdr", gate: "PA" },
|
|
161481
|
+
security_management_plan: { path: "mdr_docs/PA/security-management-plan.md", mode: "freeform", domain: "mdr", gate: "PA" },
|
|
161474
161482
|
// mdr_docs — EA gate (IEC 62304 Evolutionary Assessment 산출물)
|
|
161475
161483
|
software_requirements_list: { path: "mdr_docs/EA/software-requirements-list.md", mode: "freeform", domain: "mdr", gate: "EA" },
|
|
161476
161484
|
software_architecture_description: { path: "mdr_docs/EA/software-architecture-description.md", mode: "freeform", domain: "mdr", gate: "EA" },
|
|
@@ -161481,7 +161489,7 @@ var TEMPLATE_PATHS = {
|
|
|
161481
161489
|
list_of_hazard_related_use_scenarios: { path: "mdr_docs/EA/list-of-hazard-related-use-scenarios.md", mode: "freeform", domain: "mdr", gate: "EA" }
|
|
161482
161490
|
};
|
|
161483
161491
|
var TEMPLATE_NAMES = Object.keys(TEMPLATE_PATHS);
|
|
161484
|
-
var TEMPLATE_VERSION = "
|
|
161492
|
+
var TEMPLATE_VERSION = "b1dbcb6";
|
|
161485
161493
|
|
|
161486
161494
|
// src/tools/doc-render.ts
|
|
161487
161495
|
init_adf();
|
|
@@ -161493,7 +161501,7 @@ var registerDocRenderTools = (ctx2) => {
|
|
|
161493
161501
|
"doc_render",
|
|
161494
161502
|
"dev_docs(PRD/Spec/Plan/Tasks)\xB7mdr_docs(PA/EA gate \uBB38\uC11C \uC804\uCCB4) \uD15C\uD50C\uB9BF\uC744 \uBAA8\uB4DC \uAE30\uBC18 \uACB0\uC815\uC801 \uB80C\uB354(freeform). \uD2F0\uCF13 \uBA54\uD0C0({TICKET_ID}/{DATE} \uB4F1)\uB9CC \uCE58\uD658\uD558\uACE0, \uC790\uC720 \uD14D\uC2A4\uD2B8/\uAEBE\uC1E0 placeholder/AI \uC9C0\uCE68/\uBE48 \uB370\uC774\uD130 \uD45C\uB294 consumer\uAC00 \uCC44\uC6B0\uB3C4\uB85D \uBC18\uD658. (\uB808\uC774\uC5B4 \u2461 \u2014 LLM \uD638\uCD9C \uC5C6\uC74C)",
|
|
161495
161503
|
{
|
|
161496
|
-
template: external_exports.enum(TEMPLATE_NAMES).describe("\uB80C\uB354\uD560 \uD15C\uD50C\uB9BF \u2014 dev: prd|spec|plan|tasks / PA gate: intended_use|system_requirements_spec|risk_management_plan|mdr_classification_document|software_development_maintenance_plan / EA gate: software_requirements_list|software_architecture_description|risk_table_fmea|soup_list|usability_evaluation_plan|clinical_evaluation_plan|list_of_hazard_related_use_scenarios"),
|
|
161504
|
+
template: external_exports.enum(TEMPLATE_NAMES).describe("\uB80C\uB354\uD560 \uD15C\uD50C\uB9BF \u2014 dev: prd|spec|plan|tasks / PA gate: intended_use|system_requirements_spec|risk_management_plan|mdr_classification_document|software_development_maintenance_plan|configuration_management_plan|security_management_plan / EA gate: software_requirements_list|software_architecture_description|risk_table_fmea|soup_list|usability_evaluation_plan|clinical_evaluation_plan|list_of_hazard_related_use_scenarios"),
|
|
161497
161505
|
ticket_key: external_exports.string().describe("Jira \uD2F0\uCF13 \uD0A4 (\uC608: ER-123). description/\uBA54\uD0C0 fetch\uC5D0 \uC0AC\uC6A9"),
|
|
161498
161506
|
feature_slug: external_exports.string().optional().describe("{FEATURE_SLUG} \uCE58\uD658\uC6A9 (\uC608: add-login). \uBBF8\uC81C\uACF5 \uC2DC placeholder\uB85C \uB0A8\uC74C")
|
|
161499
161507
|
},
|
|
@@ -161574,13 +161582,13 @@ var registerDocRenderTools = (ctx2) => {
|
|
|
161574
161582
|
};
|
|
161575
161583
|
|
|
161576
161584
|
// src/tools/jira-attach.ts
|
|
161577
|
-
import { readFileSync as
|
|
161585
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
161578
161586
|
import { execFileSync } from "child_process";
|
|
161579
161587
|
|
|
161580
161588
|
// src/utils/markdownToPdf.ts
|
|
161581
|
-
import {
|
|
161589
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
161582
161590
|
import { tmpdir } from "os";
|
|
161583
|
-
import { join as
|
|
161591
|
+
import { join as join4 } from "path";
|
|
161584
161592
|
import { randomUUID } from "crypto";
|
|
161585
161593
|
|
|
161586
161594
|
// node_modules/pdfkit/js/pdfkit.es.js
|
|
@@ -183629,45 +183637,59 @@ PDFDocument.LineWrapper = LineWrapper;
|
|
|
183629
183637
|
|
|
183630
183638
|
// src/utils/markdownToPdf.ts
|
|
183631
183639
|
init_marked_esm();
|
|
183632
|
-
|
|
183633
|
-
|
|
183634
|
-
|
|
183640
|
+
|
|
183641
|
+
// src/utils/pdf-fonts.ts
|
|
183642
|
+
import { existsSync as existsSync2 } from "fs";
|
|
183643
|
+
import { join as join3, dirname } from "path";
|
|
183644
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
183645
|
+
var BUNDLED_FONT_FAMILY = "BodyFont";
|
|
183646
|
+
var BUNDLED_FONT_FAMILY_BOLD = "BodyFont-Bold";
|
|
183647
|
+
var DEFAULT_FAMILY = "BodyFont";
|
|
183648
|
+
function bundledFontPaths() {
|
|
183649
|
+
const here = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath2(import.meta.url));
|
|
183650
|
+
const rootFromSrc = join3(here, "..", "..");
|
|
183651
|
+
const candidates = [join3(here, "fonts"), join3(rootFromSrc, "dist", "fonts")];
|
|
183652
|
+
const fontsDir = candidates.find(
|
|
183653
|
+
(d2) => existsSync2(join3(d2, "Pretendard-Regular.ttf")) && existsSync2(join3(d2, "Pretendard-Bold.ttf"))
|
|
183654
|
+
);
|
|
183655
|
+
const dir = fontsDir || candidates[0];
|
|
183656
|
+
return {
|
|
183657
|
+
regular: join3(dir, "Pretendard-Regular.ttf"),
|
|
183658
|
+
bold: join3(dir, "Pretendard-Bold.ttf")
|
|
183659
|
+
};
|
|
183635
183660
|
}
|
|
183636
|
-
function
|
|
183637
|
-
|
|
183638
|
-
|
|
183639
|
-
|
|
183640
|
-
|
|
183641
|
-
|
|
183642
|
-
|
|
183643
|
-
|
|
183644
|
-
{ path: join3(fontsDir, "arial.ttf"), family: "Arial", isCjk: false, source: "arial" }
|
|
183645
|
-
];
|
|
183661
|
+
function resolveFonts(opts) {
|
|
183662
|
+
const familyName = opts.fontFamilyName || DEFAULT_FAMILY;
|
|
183663
|
+
if (opts.fontPath) {
|
|
183664
|
+
return {
|
|
183665
|
+
regularFamily: familyName,
|
|
183666
|
+
boldFamily: familyName,
|
|
183667
|
+
regularPath: opts.fontPath
|
|
183668
|
+
};
|
|
183646
183669
|
}
|
|
183647
|
-
|
|
183648
|
-
|
|
183649
|
-
|
|
183650
|
-
|
|
183651
|
-
|
|
183652
|
-
|
|
183670
|
+
const paths = bundledFontPaths();
|
|
183671
|
+
if (existsSync2(paths.regular) && existsSync2(paths.bold)) {
|
|
183672
|
+
return {
|
|
183673
|
+
regularFamily: BUNDLED_FONT_FAMILY,
|
|
183674
|
+
boldFamily: BUNDLED_FONT_FAMILY_BOLD,
|
|
183675
|
+
regularPath: paths.regular,
|
|
183676
|
+
boldPath: paths.bold
|
|
183677
|
+
};
|
|
183653
183678
|
}
|
|
183654
|
-
|
|
183655
|
-
|
|
183656
|
-
|
|
183657
|
-
|
|
183658
|
-
|
|
183659
|
-
|
|
183660
|
-
|
|
183679
|
+
const warning = `[pdf-fonts] Bundled Pretendard font not found at ${paths.regular}. Falling back to pdfkit default (Helvetica). CJK characters will render as missing glyphs. Run \`npm run build\` to copy fonts.`;
|
|
183680
|
+
console.error(warning);
|
|
183681
|
+
return {
|
|
183682
|
+
regularFamily: "Helvetica",
|
|
183683
|
+
boldFamily: "Helvetica",
|
|
183684
|
+
warning
|
|
183685
|
+
};
|
|
183661
183686
|
}
|
|
183662
|
-
|
|
183663
|
-
|
|
183664
|
-
|
|
183665
|
-
|
|
183666
|
-
|
|
183667
|
-
}
|
|
183668
|
-
return null;
|
|
183687
|
+
|
|
183688
|
+
// src/utils/markdownToPdf.ts
|
|
183689
|
+
var FRONTMATTER_RE2 = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/;
|
|
183690
|
+
function stripFrontmatter2(md) {
|
|
183691
|
+
return md.replace(FRONTMATTER_RE2, "");
|
|
183669
183692
|
}
|
|
183670
|
-
var FONT_FAMILY_DEFAULT = "BodyFont";
|
|
183671
183693
|
var PAGE_SIZE_DEFAULT = "A4";
|
|
183672
183694
|
var MARGIN_DEFAULT = 56;
|
|
183673
183695
|
async function markdownToPdf(md, opts = {}) {
|
|
@@ -183677,7 +183699,7 @@ async function markdownToPdf(md, opts = {}) {
|
|
|
183677
183699
|
includeCover = false,
|
|
183678
183700
|
author = "jira-mcp-server",
|
|
183679
183701
|
fontPath,
|
|
183680
|
-
fontFamilyName
|
|
183702
|
+
fontFamilyName,
|
|
183681
183703
|
pageSize = PAGE_SIZE_DEFAULT,
|
|
183682
183704
|
margin = {},
|
|
183683
183705
|
language = "en",
|
|
@@ -183689,19 +183711,8 @@ async function markdownToPdf(md, opts = {}) {
|
|
|
183689
183711
|
const right = margin.right ?? MARGIN_DEFAULT;
|
|
183690
183712
|
const resolvedTitle = title || sourceRef || "Document";
|
|
183691
183713
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
183692
|
-
|
|
183693
|
-
let fontWarning;
|
|
183694
|
-
if (fontPath) {
|
|
183695
|
-
fontFamily = fontFamilyName;
|
|
183696
|
-
} else {
|
|
183697
|
-
const detected = detectSystemFont();
|
|
183698
|
-
if (detected) {
|
|
183699
|
-
fontFamily = detected.familyName;
|
|
183700
|
-
} else {
|
|
183701
|
-
fontWarning = `[markdownToPdf] No CJK-capable system font detected; using pdfkit default (Helvetica). CJK characters will render as missing glyphs. Pass fontPath to override.`;
|
|
183702
|
-
console.error(fontWarning);
|
|
183703
|
-
}
|
|
183704
|
-
}
|
|
183714
|
+
const resolved = resolveFonts({ fontPath, fontFamilyName });
|
|
183715
|
+
let fontWarning = resolved.warning;
|
|
183705
183716
|
const doc = new PDFDocument({
|
|
183706
183717
|
info: { Title: resolvedTitle, Author: author, CreationDate: /* @__PURE__ */ new Date() },
|
|
183707
183718
|
size: pageSize,
|
|
@@ -183710,35 +183721,29 @@ async function markdownToPdf(md, opts = {}) {
|
|
|
183710
183721
|
// 머리말/꼬리말 후 페이지 사후 그리기 + bufferedPageRange() 사용
|
|
183711
183722
|
});
|
|
183712
183723
|
void language;
|
|
183713
|
-
if (
|
|
183724
|
+
if (resolved.regularPath) {
|
|
183714
183725
|
try {
|
|
183715
|
-
doc.registerFont(
|
|
183716
|
-
doc.font(
|
|
183717
|
-
fontFamily = fontFamilyName;
|
|
183726
|
+
doc.registerFont(resolved.regularFamily, resolved.regularPath);
|
|
183727
|
+
doc.font(resolved.regularFamily);
|
|
183718
183728
|
} catch (err) {
|
|
183719
|
-
fontWarning = `[markdownToPdf] Failed to register font "${
|
|
183729
|
+
fontWarning = `[markdownToPdf] Failed to register regular font "${resolved.regularPath}": ${err?.message ?? err}. Falling back to pdfkit default.`;
|
|
183720
183730
|
console.error(fontWarning);
|
|
183721
|
-
|
|
183722
|
-
|
|
183731
|
+
resolved.regularFamily = "Helvetica";
|
|
183732
|
+
resolved.boldFamily = "Helvetica";
|
|
183723
183733
|
}
|
|
183724
|
-
}
|
|
183725
|
-
|
|
183726
|
-
|
|
183727
|
-
|
|
183728
|
-
|
|
183729
|
-
|
|
183730
|
-
|
|
183731
|
-
|
|
183732
|
-
|
|
183733
|
-
console.error(fontWarning);
|
|
183734
|
-
doc.font("Helvetica");
|
|
183735
|
-
fontFamily = "Helvetica";
|
|
183736
|
-
}
|
|
183734
|
+
}
|
|
183735
|
+
if (resolved.boldPath && resolved.boldFamily !== resolved.regularFamily) {
|
|
183736
|
+
try {
|
|
183737
|
+
doc.registerFont(resolved.boldFamily, resolved.boldPath);
|
|
183738
|
+
doc.font(resolved.boldFamily);
|
|
183739
|
+
} catch (err) {
|
|
183740
|
+
fontWarning = `[markdownToPdf] Failed to register bold font "${resolved.boldPath}": ${err?.message ?? err}. Bold falls back to regular.`;
|
|
183741
|
+
console.error(fontWarning);
|
|
183742
|
+
resolved.boldFamily = resolved.regularFamily;
|
|
183737
183743
|
}
|
|
183738
|
-
} else {
|
|
183739
|
-
doc.font("Helvetica");
|
|
183740
|
-
fontFamily = "Helvetica";
|
|
183741
183744
|
}
|
|
183745
|
+
doc.font(resolved.regularFamily);
|
|
183746
|
+
const fonts = resolved;
|
|
183742
183747
|
if (includeCover) {
|
|
183743
183748
|
doc.moveDown(8);
|
|
183744
183749
|
doc.fontSize(28).fillColor("#000").text(resolvedTitle, { align: "left" });
|
|
@@ -183758,7 +183763,7 @@ async function markdownToPdf(md, opts = {}) {
|
|
|
183758
183763
|
const body = stripFrontmatter2(md ?? "");
|
|
183759
183764
|
const tokens = g.lexer(body);
|
|
183760
183765
|
for (const tok of tokens) {
|
|
183761
|
-
renderToken(doc, tok,
|
|
183766
|
+
renderToken(doc, tok, fonts);
|
|
183762
183767
|
}
|
|
183763
183768
|
if (tokens.length === 0) {
|
|
183764
183769
|
doc.fontSize(11).fillColor("#000").text("");
|
|
@@ -183854,26 +183859,26 @@ function lineHeightOf(doc) {
|
|
|
183854
183859
|
const size = doc._fontSize ?? 11;
|
|
183855
183860
|
return size * 1.2;
|
|
183856
183861
|
}
|
|
183857
|
-
function renderToken(doc, tok,
|
|
183862
|
+
function renderToken(doc, tok, fonts) {
|
|
183858
183863
|
if (!tok || typeof tok !== "object") return;
|
|
183859
183864
|
switch (tok.type) {
|
|
183860
183865
|
case "heading":
|
|
183861
|
-
renderHeading(doc, tok,
|
|
183866
|
+
renderHeading(doc, tok, fonts);
|
|
183862
183867
|
return;
|
|
183863
183868
|
case "paragraph":
|
|
183864
|
-
renderParagraph(doc, tok,
|
|
183869
|
+
renderParagraph(doc, tok, fonts);
|
|
183865
183870
|
return;
|
|
183866
183871
|
case "code":
|
|
183867
183872
|
renderCodeBlock(doc, tok);
|
|
183868
183873
|
return;
|
|
183869
183874
|
case "blockquote":
|
|
183870
|
-
renderBlockquote(doc, tok,
|
|
183875
|
+
renderBlockquote(doc, tok, fonts);
|
|
183871
183876
|
return;
|
|
183872
183877
|
case "list":
|
|
183873
|
-
renderList(doc, tok,
|
|
183878
|
+
renderList(doc, tok, fonts, 0);
|
|
183874
183879
|
return;
|
|
183875
183880
|
case "table":
|
|
183876
|
-
renderTable(doc, tok,
|
|
183881
|
+
renderTable(doc, tok, fonts);
|
|
183877
183882
|
return;
|
|
183878
183883
|
case "hr":
|
|
183879
183884
|
renderHr(doc);
|
|
@@ -183883,18 +183888,18 @@ function renderToken(doc, tok, fontFamily) {
|
|
|
183883
183888
|
return;
|
|
183884
183889
|
default:
|
|
183885
183890
|
if (tok.text) {
|
|
183886
|
-
doc.fontSize(BODY_FONT_SIZE).fillColor("#000").font(
|
|
183891
|
+
doc.fontSize(BODY_FONT_SIZE).fillColor("#000").font(fonts.regularFamily).text(String(tok.text));
|
|
183887
183892
|
}
|
|
183888
183893
|
}
|
|
183889
183894
|
}
|
|
183890
|
-
function renderHeading(doc, tok,
|
|
183895
|
+
function renderHeading(doc, tok, fonts) {
|
|
183891
183896
|
const level = Math.min(Math.max(Number(tok.depth) || 1, 1), 6);
|
|
183892
183897
|
const size = HEADING_SIZES[level - 1];
|
|
183893
183898
|
const text = tok.text ?? "";
|
|
183894
183899
|
const marginL = doc.page.margins.left;
|
|
183895
183900
|
const marginR = doc.page.margins.right;
|
|
183896
183901
|
const width = doc.page.width - marginL - marginR;
|
|
183897
|
-
doc.fontSize(size).fillColor("#111").font(
|
|
183902
|
+
doc.fontSize(size).fillColor("#111").font(fonts.boldFamily);
|
|
183898
183903
|
const before = level === 1 ? SPACE2.H1_BEFORE : level === 2 ? SPACE2.H2_BEFORE : level === 3 ? SPACE2.H3_BEFORE : SPACE2.H4_H6_BEFORE;
|
|
183899
183904
|
doc.y += before;
|
|
183900
183905
|
const lineHeight = lineHeightOf(doc);
|
|
@@ -183907,12 +183912,12 @@ function renderHeading(doc, tok, fontFamily) {
|
|
|
183907
183912
|
doc.y += after;
|
|
183908
183913
|
void lines;
|
|
183909
183914
|
}
|
|
183910
|
-
function renderParagraph(doc, tok,
|
|
183915
|
+
function renderParagraph(doc, tok, fonts) {
|
|
183911
183916
|
const marginL = doc.page.margins.left;
|
|
183912
183917
|
const marginR = doc.page.margins.right;
|
|
183913
183918
|
const width = doc.page.width - marginL - marginR;
|
|
183914
183919
|
const text = inlineToPlainText(tok.tokens ?? [{ type: "text", text: tok.text ?? "" }]);
|
|
183915
|
-
doc.fontSize(BODY_FONT_SIZE).fillColor("#222").font(
|
|
183920
|
+
doc.fontSize(BODY_FONT_SIZE).fillColor("#222").font(fonts.regularFamily);
|
|
183916
183921
|
doc.y += SPACE2.PARAGRAPH_BEFORE;
|
|
183917
183922
|
const lineHeight = lineHeightOf(doc);
|
|
183918
183923
|
if (text) {
|
|
@@ -183975,13 +183980,13 @@ function renderCodeBlock(doc, tok) {
|
|
|
183975
183980
|
doc.fillColor("#000");
|
|
183976
183981
|
doc.y = boxY + blockHeight + SPACE2.CODE_AFTER;
|
|
183977
183982
|
}
|
|
183978
|
-
function renderBlockquote(doc, tok,
|
|
183983
|
+
function renderBlockquote(doc, tok, fonts) {
|
|
183979
183984
|
const marginL = doc.page.margins.left;
|
|
183980
183985
|
const marginR = doc.page.margins.right;
|
|
183981
183986
|
const indent = 20;
|
|
183982
183987
|
const width = doc.page.width - marginL - marginR - indent;
|
|
183983
183988
|
doc.y += SPACE2.BLOCKQUOTE_BEFORE;
|
|
183984
|
-
doc.fontSize(BODY_FONT_SIZE).fillColor("#555").font(
|
|
183989
|
+
doc.fontSize(BODY_FONT_SIZE).fillColor("#555").font(fonts.regularFamily);
|
|
183985
183990
|
const flat = (tok.tokens ?? []).map(extractInlineText).filter(Boolean).join(" ");
|
|
183986
183991
|
if (flat) {
|
|
183987
183992
|
const lineHeight = lineHeightOf(doc);
|
|
@@ -184003,7 +184008,7 @@ function extractInlineText(node) {
|
|
|
184003
184008
|
if (Array.isArray(node.tokens)) return node.tokens.map(extractInlineText).join("");
|
|
184004
184009
|
return "";
|
|
184005
184010
|
}
|
|
184006
|
-
function renderList(doc, tok,
|
|
184011
|
+
function renderList(doc, tok, fonts, depth) {
|
|
184007
184012
|
const items = tok.items ?? [];
|
|
184008
184013
|
const ordered = !!tok.ordered;
|
|
184009
184014
|
const marginL = doc.page.margins.left;
|
|
@@ -184018,43 +184023,38 @@ function renderList(doc, tok, fontFamily, depth) {
|
|
|
184018
184023
|
for (const item of items) {
|
|
184019
184024
|
const marker = ordered ? `${counter}. ` : "\u2022 ";
|
|
184020
184025
|
counter += 1;
|
|
184021
|
-
doc.fontSize(BODY_FONT_SIZE).fillColor("#222").font(
|
|
184026
|
+
doc.fontSize(BODY_FONT_SIZE).fillColor("#222").font(fonts.regularFamily);
|
|
184022
184027
|
const markerX = marginL + indent;
|
|
184023
184028
|
doc.text(marker, markerX, doc.y, { width: markerWidth, continued: false });
|
|
184024
184029
|
doc.x = markerX + markerWidth;
|
|
184025
184030
|
const bodyStartY = doc.y - lineHeightOf(doc);
|
|
184026
184031
|
doc.y = bodyStartY;
|
|
184027
184032
|
const subs = Array.isArray(item.tokens) ? item.tokens : [];
|
|
184028
|
-
let firstInline = true;
|
|
184029
184033
|
let drewAnything = false;
|
|
184030
184034
|
for (const sub of subs) {
|
|
184031
184035
|
if (sub?.type === "text" && Array.isArray(sub.tokens)) {
|
|
184032
|
-
drawInlineInBox(doc, sub.tokens,
|
|
184036
|
+
drawInlineInBox(doc, sub.tokens, fonts, doc.x, bodyStartY, itemWidth - markerWidth);
|
|
184033
184037
|
drewAnything = true;
|
|
184034
|
-
firstInline = false;
|
|
184035
184038
|
} else if (sub?.type === "paragraph") {
|
|
184036
184039
|
drawInlineInBox(
|
|
184037
184040
|
doc,
|
|
184038
184041
|
sub.tokens ?? [{ type: "text", text: sub.text ?? "" }],
|
|
184039
|
-
|
|
184042
|
+
fonts,
|
|
184040
184043
|
doc.x,
|
|
184041
184044
|
bodyStartY,
|
|
184042
184045
|
itemWidth - markerWidth
|
|
184043
184046
|
);
|
|
184044
184047
|
drewAnything = true;
|
|
184045
|
-
firstInline = false;
|
|
184046
184048
|
} else if (sub?.type === "list") {
|
|
184047
184049
|
doc.x = marginL + indent + 12;
|
|
184048
184050
|
doc.y = doc.y + SPACE2.LIST_ITEM_BEFORE;
|
|
184049
|
-
renderList(doc, sub,
|
|
184050
|
-
firstInline = false;
|
|
184051
|
+
renderList(doc, sub, fonts, depth + 1);
|
|
184051
184052
|
} else {
|
|
184052
|
-
renderToken(doc, sub,
|
|
184053
|
-
firstInline = false;
|
|
184053
|
+
renderToken(doc, sub, fonts);
|
|
184054
184054
|
}
|
|
184055
184055
|
}
|
|
184056
184056
|
if (!drewAnything && item.text) {
|
|
184057
|
-
doc.font(
|
|
184057
|
+
doc.font(fonts.regularFamily).text(String(item.text), doc.x, doc.y, {
|
|
184058
184058
|
width: itemWidth - markerWidth
|
|
184059
184059
|
});
|
|
184060
184060
|
doc.y += lineHeightOf(doc);
|
|
@@ -184065,9 +184065,9 @@ function renderList(doc, tok, fontFamily, depth) {
|
|
|
184065
184065
|
}
|
|
184066
184066
|
doc.y += SPACE2.LIST_AFTER;
|
|
184067
184067
|
}
|
|
184068
|
-
function drawInlineInBox(doc, tokens,
|
|
184068
|
+
function drawInlineInBox(doc, tokens, fonts, x3, y2, width) {
|
|
184069
184069
|
const text = inlineToPlainText(tokens);
|
|
184070
|
-
doc.fontSize(BODY_FONT_SIZE).fillColor("#222").font(
|
|
184070
|
+
doc.fontSize(BODY_FONT_SIZE).fillColor("#222").font(fonts.regularFamily);
|
|
184071
184071
|
if (!text) return;
|
|
184072
184072
|
const lineHeight = lineHeightOf(doc);
|
|
184073
184073
|
const height = doc.heightOfString(text, { width });
|
|
@@ -184076,7 +184076,7 @@ function drawInlineInBox(doc, tokens, fontFamily, x3, y2, width) {
|
|
|
184076
184076
|
doc.y += lineHeight;
|
|
184077
184077
|
void lines;
|
|
184078
184078
|
}
|
|
184079
|
-
function renderTable(doc, tok,
|
|
184079
|
+
function renderTable(doc, tok, fonts) {
|
|
184080
184080
|
const header = tok.header ?? [];
|
|
184081
184081
|
const rows = tok.rows ?? [];
|
|
184082
184082
|
if (!header.length && !rows.length) return;
|
|
@@ -184095,7 +184095,7 @@ function renderTable(doc, tok, fontFamily) {
|
|
|
184095
184095
|
if (totalColWidth > width) colWidth = width / colCount;
|
|
184096
184096
|
const cellPadding = 4;
|
|
184097
184097
|
const rowMinHeight = 14;
|
|
184098
|
-
doc.fontSize(10).font(
|
|
184098
|
+
doc.fontSize(10).font(fonts.regularFamily).fillColor("#222");
|
|
184099
184099
|
doc.y += SPACE2.TABLE_BEFORE;
|
|
184100
184100
|
const drawRow = (cells, y3, isHeader) => {
|
|
184101
184101
|
const texts = [];
|
|
@@ -184151,7 +184151,7 @@ function renderHr(doc) {
|
|
|
184151
184151
|
doc.y = y2 + SPACE2.HR_AFTER;
|
|
184152
184152
|
}
|
|
184153
184153
|
function writePdfToTempFile(buffer) {
|
|
184154
|
-
const path3 =
|
|
184154
|
+
const path3 = join4(tmpdir(), `${randomUUID()}.pdf`);
|
|
184155
184155
|
writeFileSync3(path3, buffer);
|
|
184156
184156
|
return path3;
|
|
184157
184157
|
}
|
|
@@ -184192,7 +184192,7 @@ var registerJiraAttachTools = (ctx2) => {
|
|
|
184192
184192
|
const { server: server2, jira: jira2 } = ctx2;
|
|
184193
184193
|
server2.tool(
|
|
184194
184194
|
"markdown_to_pdf",
|
|
184195
|
-
"\uB9C8\uD06C\uB2E4\uC6B4\uC744 PDF\uB85C \uBCC0\uD658 (\
|
|
184195
|
+
"\uB9C8\uD06C\uB2E4\uC6B4\uC744 PDF\uB85C \uBCC0\uD658 (\uBC88\uB4E4 Pretendard Regular+Bold, \uD45C\uC9C0/\uBA38\uB9AC\uB9D0\xB7\uAF2C\uB9AC\uB9D0 \uC635\uC158). Jira \uCCA8\uBD80 \uC5C6\uC774 PDF \uACB0\uACFC\uB9CC \uBC18\uD658.",
|
|
184196
184196
|
{
|
|
184197
184197
|
markdown: external_exports.string().optional().describe("PDF\uB85C \uBCC0\uD658\uD560 \uB9C8\uD06C\uB2E4\uC6B4 \uBCF8\uBB38 (inline). markdown_file\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
|
|
184198
184198
|
markdown_file: external_exports.string().optional().describe("\uB85C\uCEEC \uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uACBD\uB85C. \uD070 \uBB38\uC11C(25KB+)\uB294 \uBAA8\uB378 \uD234 \uD638\uCD9C \uCD9C\uB825 \uD55C\uACC4\uB85C inline markdown \uC778\uC790\uAC00 \uC798\uB9B4 \uC218 \uC788\uC5B4 \uD30C\uC77C \uC9C1\uC811 \uC77D\uAE30 \uAD8C\uC7A5. markdown\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
|
|
@@ -184200,7 +184200,7 @@ var registerJiraAttachTools = (ctx2) => {
|
|
|
184200
184200
|
source_ref: external_exports.string().optional().describe('\uAF2C\uB9AC\uB9D0\xB7\uD45C\uC9C0 \uD478\uD130\uC5D0 \uD45C\uC2DC\uD560 \uCD9C\uCC98 (\uC608: "DYN-100 \xB7 2026-07-14")'),
|
|
184201
184201
|
include_cover: external_exports.boolean().optional().default(false).describe("\uD45C\uC9C0 \uD398\uC774\uC9C0 \uD3EC\uD568 \uC5EC\uBD80 (\uAE30\uBCF8 false)"),
|
|
184202
184202
|
author: external_exports.string().optional().describe('PDF /Author \uBA54\uD0C0 (\uAE30\uBCF8 "jira-mcp-server")'),
|
|
184203
|
-
font_path: external_exports.string().optional().describe("\uD3F0\uD2B8 \uD30C\uC77C \uC808\uB300 \uACBD\uB85C (.ttf/.otf/.ttc). \uBBF8\uC9C0\uC815 \uC2DC \
|
|
184203
|
+
font_path: external_exports.string().optional().describe("\uD3F0\uD2B8 \uD30C\uC77C \uC808\uB300 \uACBD\uB85C (.ttf/.otf/.ttc). \uBBF8\uC9C0\uC815 \uC2DC \uBC88\uB4E4 Pretendard \uC0AC\uC6A9 (\uBD80\uC7AC \uC2DC Helvetica \uD3F4\uBC31)"),
|
|
184204
184204
|
font_family_name: external_exports.string().optional().describe('pdfkit registerFont \uC774\uB984 (\uAE30\uBCF8 "BodyFont")'),
|
|
184205
184205
|
page_size: external_exports.enum(["A4", "LETTER", "LEGAL"]).optional().default("A4").describe("\uD398\uC774\uC9C0 \uD06C\uAE30"),
|
|
184206
184206
|
output_mode: external_exports.enum(["base64", "tmpfile"]).optional().default("base64").describe("base64(\uAE30\uBCF8, JSON \uC548\uC804) / tmpfile(\uC808\uB300\uACBD\uB85C \uBC18\uD658, consumer\uAC00 unlink \uCC45\uC784)")
|
|
@@ -184215,7 +184215,7 @@ var registerJiraAttachTools = (ctx2) => {
|
|
|
184215
184215
|
let md;
|
|
184216
184216
|
if (markdown_file) {
|
|
184217
184217
|
try {
|
|
184218
|
-
md =
|
|
184218
|
+
md = readFileSync4(markdown_file, "utf8");
|
|
184219
184219
|
} catch (err) {
|
|
184220
184220
|
throw new Error(`Failed to read markdown_file "${markdown_file}": ${err?.message ?? err}`);
|
|
184221
184221
|
}
|
|
@@ -184273,7 +184273,7 @@ var registerJiraAttachTools = (ctx2) => {
|
|
|
184273
184273
|
let buffer;
|
|
184274
184274
|
if (file_path) {
|
|
184275
184275
|
try {
|
|
184276
|
-
buffer =
|
|
184276
|
+
buffer = readFileSync4(file_path);
|
|
184277
184277
|
} catch (err) {
|
|
184278
184278
|
throw new Error(`Failed to read file_path "${file_path}": ${err?.message ?? err}`);
|
|
184279
184279
|
}
|
|
@@ -184349,7 +184349,7 @@ var registerJiraAttachTools = (ctx2) => {
|
|
|
184349
184349
|
let md;
|
|
184350
184350
|
if (markdown_file) {
|
|
184351
184351
|
try {
|
|
184352
|
-
md =
|
|
184352
|
+
md = readFileSync4(markdown_file, "utf8");
|
|
184353
184353
|
} catch (err) {
|
|
184354
184354
|
throw new Error(`Failed to read markdown_file "${markdown_file}": ${err?.message ?? err}`);
|
|
184355
184355
|
}
|
|
@@ -184641,10 +184641,10 @@ var registerExpertTools = (ctx2) => {
|
|
|
184641
184641
|
};
|
|
184642
184642
|
|
|
184643
184643
|
// src/tools/review-criteria.ts
|
|
184644
|
-
import { readFileSync as
|
|
184645
|
-
import { fileURLToPath as
|
|
184644
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
184645
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
184646
184646
|
import path2 from "path";
|
|
184647
|
-
var __dirname3 = path2.dirname(
|
|
184647
|
+
var __dirname3 = path2.dirname(fileURLToPath3(import.meta.url));
|
|
184648
184648
|
var CRITERIA_PATH = path2.resolve(__dirname3, "../data/review-criteria.md");
|
|
184649
184649
|
var registerReviewCriteriaTools = (ctx2) => {
|
|
184650
184650
|
ctx2.server.tool(
|
|
@@ -184654,7 +184654,7 @@ var registerReviewCriteriaTools = (ctx2) => {
|
|
|
184654
184654
|
async () => {
|
|
184655
184655
|
let body;
|
|
184656
184656
|
try {
|
|
184657
|
-
body =
|
|
184657
|
+
body = readFileSync5(CRITERIA_PATH, "utf8");
|
|
184658
184658
|
} catch (err) {
|
|
184659
184659
|
body = [
|
|
184660
184660
|
"# Review Criteria \u2014 \uB85C\uB4DC \uC2E4\uD328",
|
|
@@ -184691,7 +184691,7 @@ var xrayClientSecret = process.env.XRAY_CLIENT_SECRET || "";
|
|
|
184691
184691
|
var xray = xrayClientId && xrayClientSecret ? new XrayClient(xrayClientId, xrayClientSecret, jiraUrl, jiraEmail, jiraToken) : null;
|
|
184692
184692
|
var server = new McpServer({
|
|
184693
184693
|
name: "jira-confluence",
|
|
184694
|
-
version: "0.1.
|
|
184694
|
+
version: "0.1.18"
|
|
184695
184695
|
});
|
|
184696
184696
|
var ctx = { server, jira, confluence, risk, xray };
|
|
184697
184697
|
registerJiraCrudTools(ctx);
|