mrvn-cli 0.5.11 → 0.5.13
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/index.js +183 -18
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +182 -17
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +183 -18
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/marvin-serve.js
CHANGED
|
@@ -15676,9 +15676,14 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
15676
15676
|
};
|
|
15677
15677
|
});
|
|
15678
15678
|
const sprintTag = `sprint:${fm.id}`;
|
|
15679
|
-
const
|
|
15679
|
+
const sprintTaggedDocs = allDocs.filter(
|
|
15680
15680
|
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.type !== "meeting" && d.frontmatter.type !== "decision" && d.frontmatter.type !== "question" && d.frontmatter.tags?.includes(sprintTag)
|
|
15681
15681
|
);
|
|
15682
|
+
const sprintTaggedIds = new Set(sprintTaggedDocs.map((d) => d.frontmatter.id));
|
|
15683
|
+
const orphanContributions = allDocs.filter(
|
|
15684
|
+
(d) => d.frontmatter.type === "contribution" && !sprintTaggedIds.has(d.frontmatter.id) && d.frontmatter.aboutArtifact && sprintTaggedIds.has(d.frontmatter.aboutArtifact)
|
|
15685
|
+
);
|
|
15686
|
+
const workItemDocs = [...sprintTaggedDocs, ...orphanContributions];
|
|
15682
15687
|
const primaryDocs = workItemDocs.filter((d) => d.frontmatter.type !== "contribution");
|
|
15683
15688
|
const byStatus = {};
|
|
15684
15689
|
const byType = {};
|
|
@@ -15697,7 +15702,7 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
15697
15702
|
}
|
|
15698
15703
|
const allItemsById = /* @__PURE__ */ new Map();
|
|
15699
15704
|
const childrenByParent = /* @__PURE__ */ new Map();
|
|
15700
|
-
const
|
|
15705
|
+
const workItemIds = new Set(workItemDocs.map((d) => d.frontmatter.id));
|
|
15701
15706
|
for (const doc of workItemDocs) {
|
|
15702
15707
|
const about = doc.frontmatter.aboutArtifact;
|
|
15703
15708
|
const focusTag = (doc.frontmatter.tags ?? []).find((t) => t.startsWith("focus:"));
|
|
@@ -15711,10 +15716,12 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
15711
15716
|
workFocus: focusTag ? focusTag.slice(6) : void 0,
|
|
15712
15717
|
aboutArtifact: about,
|
|
15713
15718
|
jiraKey: doc.frontmatter.jiraKey,
|
|
15714
|
-
jiraUrl: doc.frontmatter.jiraUrl
|
|
15719
|
+
jiraUrl: doc.frontmatter.jiraUrl,
|
|
15720
|
+
confluenceUrl: doc.frontmatter.confluenceUrl,
|
|
15721
|
+
confluenceTitle: doc.frontmatter.confluenceTitle
|
|
15715
15722
|
};
|
|
15716
15723
|
allItemsById.set(item.id, item);
|
|
15717
|
-
if (about &&
|
|
15724
|
+
if (about && workItemIds.has(about)) {
|
|
15718
15725
|
if (!childrenByParent.has(about)) childrenByParent.set(about, []);
|
|
15719
15726
|
childrenByParent.get(about).push(item);
|
|
15720
15727
|
}
|
|
@@ -19026,11 +19033,14 @@ import { tool as tool20 } from "@anthropic-ai/claude-agent-sdk";
|
|
|
19026
19033
|
var JiraClient = class {
|
|
19027
19034
|
baseUrl;
|
|
19028
19035
|
baseUrlV3;
|
|
19036
|
+
confluenceBaseUrl;
|
|
19029
19037
|
authHeader;
|
|
19038
|
+
host;
|
|
19030
19039
|
constructor(config2) {
|
|
19031
|
-
|
|
19032
|
-
this.baseUrl = `https://${host}/rest/api/2`;
|
|
19033
|
-
this.baseUrlV3 = `https://${host}/rest/api/3`;
|
|
19040
|
+
this.host = config2.host.replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
19041
|
+
this.baseUrl = `https://${this.host}/rest/api/2`;
|
|
19042
|
+
this.baseUrlV3 = `https://${this.host}/rest/api/3`;
|
|
19043
|
+
this.confluenceBaseUrl = `https://${this.host}/wiki/api/v2`;
|
|
19034
19044
|
this.authHeader = "Basic " + Buffer.from(`${config2.email}:${config2.apiToken}`).toString("base64");
|
|
19035
19045
|
}
|
|
19036
19046
|
async request(path11, method = "GET", body) {
|
|
@@ -19118,6 +19128,30 @@ var JiraClient = class {
|
|
|
19118
19128
|
{ body }
|
|
19119
19129
|
);
|
|
19120
19130
|
}
|
|
19131
|
+
// --- Confluence methods ---
|
|
19132
|
+
async getConfluencePage(pageId) {
|
|
19133
|
+
return this.doRequest(
|
|
19134
|
+
`${this.confluenceBaseUrl}/pages/${encodeURIComponent(pageId)}?body-format=atlas_doc_format`,
|
|
19135
|
+
"GET"
|
|
19136
|
+
);
|
|
19137
|
+
}
|
|
19138
|
+
/**
|
|
19139
|
+
* Extract a Confluence page ID from various URL formats.
|
|
19140
|
+
* Returns null if the URL doesn't match any known pattern.
|
|
19141
|
+
*/
|
|
19142
|
+
static extractPageId(url2) {
|
|
19143
|
+
const pagesMatch = url2.match(/\/pages\/(\d+)/);
|
|
19144
|
+
if (pagesMatch) return pagesMatch[1];
|
|
19145
|
+
const paramMatch = url2.match(/[?&]pageId=(\d+)/);
|
|
19146
|
+
if (paramMatch) return paramMatch[1];
|
|
19147
|
+
return null;
|
|
19148
|
+
}
|
|
19149
|
+
/**
|
|
19150
|
+
* Build a web URL for a Confluence page.
|
|
19151
|
+
*/
|
|
19152
|
+
getConfluencePageUrl(pageId) {
|
|
19153
|
+
return `https://${this.host}/wiki/pages/viewpage.action?pageId=${pageId}`;
|
|
19154
|
+
}
|
|
19121
19155
|
};
|
|
19122
19156
|
function createJiraClient(jiraUserConfig) {
|
|
19123
19157
|
const host = jiraUserConfig?.host ?? process.env.JIRA_HOST;
|
|
@@ -20178,6 +20212,111 @@ function createJiraTools(store, projectConfig) {
|
|
|
20178
20212
|
};
|
|
20179
20213
|
}
|
|
20180
20214
|
),
|
|
20215
|
+
// --- Confluence tools ---
|
|
20216
|
+
tool20(
|
|
20217
|
+
"link_to_confluence",
|
|
20218
|
+
"Link a Confluence page to any Marvin artifact. Validates the page exists and fetches its title.",
|
|
20219
|
+
{
|
|
20220
|
+
artifactId: external_exports.string().describe("Marvin artifact ID (e.g. 'D-001', 'A-003', 'T-002')"),
|
|
20221
|
+
confluenceUrl: external_exports.string().describe("Confluence page URL")
|
|
20222
|
+
},
|
|
20223
|
+
async (args) => {
|
|
20224
|
+
const jira = createJiraClient(jiraUserConfig);
|
|
20225
|
+
if (!jira) return jiraNotConfiguredError();
|
|
20226
|
+
const artifact = store.get(args.artifactId);
|
|
20227
|
+
if (!artifact) {
|
|
20228
|
+
return {
|
|
20229
|
+
content: [
|
|
20230
|
+
{ type: "text", text: `Artifact ${args.artifactId} not found` }
|
|
20231
|
+
],
|
|
20232
|
+
isError: true
|
|
20233
|
+
};
|
|
20234
|
+
}
|
|
20235
|
+
const pageId = JiraClient.extractPageId(args.confluenceUrl);
|
|
20236
|
+
if (!pageId) {
|
|
20237
|
+
return {
|
|
20238
|
+
content: [
|
|
20239
|
+
{ type: "text", text: `Could not extract page ID from URL: ${args.confluenceUrl}` }
|
|
20240
|
+
],
|
|
20241
|
+
isError: true
|
|
20242
|
+
};
|
|
20243
|
+
}
|
|
20244
|
+
const page = await jira.client.getConfluencePage(pageId);
|
|
20245
|
+
const existingTags = artifact.frontmatter.tags ?? [];
|
|
20246
|
+
store.update(args.artifactId, {
|
|
20247
|
+
confluenceUrl: args.confluenceUrl,
|
|
20248
|
+
confluencePageId: pageId,
|
|
20249
|
+
confluenceTitle: page.title,
|
|
20250
|
+
tags: [...existingTags.filter((t) => !t.startsWith("confluence:")), `confluence:${page.title}`]
|
|
20251
|
+
});
|
|
20252
|
+
return {
|
|
20253
|
+
content: [
|
|
20254
|
+
{
|
|
20255
|
+
type: "text",
|
|
20256
|
+
text: `Linked ${args.artifactId} to Confluence page "${page.title}" (ID: ${pageId}).`
|
|
20257
|
+
}
|
|
20258
|
+
]
|
|
20259
|
+
};
|
|
20260
|
+
}
|
|
20261
|
+
),
|
|
20262
|
+
tool20(
|
|
20263
|
+
"read_confluence_page",
|
|
20264
|
+
"Read the content of a Confluence page by URL or page ID. Returns the page title, metadata, and body as plain text.",
|
|
20265
|
+
{
|
|
20266
|
+
pageUrl: external_exports.string().optional().describe("Confluence page URL"),
|
|
20267
|
+
pageId: external_exports.string().optional().describe("Confluence page ID (alternative to URL)")
|
|
20268
|
+
},
|
|
20269
|
+
async (args) => {
|
|
20270
|
+
const jira = createJiraClient(jiraUserConfig);
|
|
20271
|
+
if (!jira) return jiraNotConfiguredError();
|
|
20272
|
+
const resolvedId = args.pageId ?? (args.pageUrl ? JiraClient.extractPageId(args.pageUrl) : null);
|
|
20273
|
+
if (!resolvedId) {
|
|
20274
|
+
return {
|
|
20275
|
+
content: [
|
|
20276
|
+
{
|
|
20277
|
+
type: "text",
|
|
20278
|
+
text: "Provide either pageUrl or pageId. Could not extract page ID from the given URL."
|
|
20279
|
+
}
|
|
20280
|
+
],
|
|
20281
|
+
isError: true
|
|
20282
|
+
};
|
|
20283
|
+
}
|
|
20284
|
+
const page = await jira.client.getConfluencePage(resolvedId);
|
|
20285
|
+
let bodyText = "";
|
|
20286
|
+
if (page.body?.atlas_doc_format?.value) {
|
|
20287
|
+
try {
|
|
20288
|
+
const adf = JSON.parse(page.body.atlas_doc_format.value);
|
|
20289
|
+
bodyText = extractCommentText(adf);
|
|
20290
|
+
} catch {
|
|
20291
|
+
bodyText = page.body.atlas_doc_format.value;
|
|
20292
|
+
}
|
|
20293
|
+
}
|
|
20294
|
+
const parts = [
|
|
20295
|
+
`# ${page.title}`,
|
|
20296
|
+
"",
|
|
20297
|
+
`Page ID: ${page.id}`,
|
|
20298
|
+
`Status: ${page.status}`,
|
|
20299
|
+
`Version: ${page.version.number} (${page.version.createdAt.slice(0, 10)})`,
|
|
20300
|
+
"",
|
|
20301
|
+
"---",
|
|
20302
|
+
"",
|
|
20303
|
+
bodyText || "(empty page)"
|
|
20304
|
+
];
|
|
20305
|
+
const allDocs = store.registeredTypes.flatMap((t) => store.list({ type: t }));
|
|
20306
|
+
const linkedArtifacts = allDocs.filter(
|
|
20307
|
+
(d) => d.frontmatter.confluencePageId === resolvedId || d.frontmatter.confluenceUrl === args.pageUrl
|
|
20308
|
+
);
|
|
20309
|
+
if (linkedArtifacts.length > 0) {
|
|
20310
|
+
parts.push("");
|
|
20311
|
+
parts.push("---");
|
|
20312
|
+
parts.push(`Linked Marvin artifacts: ${linkedArtifacts.map((d) => d.frontmatter.id).join(", ")}`);
|
|
20313
|
+
}
|
|
20314
|
+
return {
|
|
20315
|
+
content: [{ type: "text", text: parts.join("\n") }]
|
|
20316
|
+
};
|
|
20317
|
+
},
|
|
20318
|
+
{ annotations: { readOnlyHint: true } }
|
|
20319
|
+
),
|
|
20181
20320
|
// --- Jira status fetch (read-only) ---
|
|
20182
20321
|
tool20(
|
|
20183
20322
|
"fetch_jira_status",
|
|
@@ -20488,6 +20627,8 @@ function formatIssueEntry(issue2) {
|
|
|
20488
20627
|
var COMMON_TOOLS = `**Available tools:**
|
|
20489
20628
|
- \`push_artifact_to_jira\` \u2014 create a Jira issue from any Marvin artifact and link it directly via \`jiraKey\` on the artifact.
|
|
20490
20629
|
- \`link_to_jira\` \u2014 link an existing Jira issue to any Marvin artifact (sets \`jiraKey\` directly on the artifact).
|
|
20630
|
+
- \`link_to_confluence\` \u2014 link a Confluence page to any Marvin artifact. Validates the page exists and fetches its title.
|
|
20631
|
+
- \`read_confluence_page\` \u2014 **read-only**: fetch and return the content of a Confluence page by URL or page ID. Use this to review Confluence content for updating tasks, generating contributions, or answering questions.
|
|
20491
20632
|
- \`fetch_jira_status\` \u2014 **read-only**: fetch current Jira status, subtask progress, and linked issues for Jira-linked actions/tasks. Returns proposed changes without applying them.
|
|
20492
20633
|
- \`fetch_jira_daily\` \u2014 **read-only**: fetch a daily/range summary of all Jira changes \u2014 status transitions, comments, linked Confluence pages, and cross-references with Marvin artifacts. Returns proposed actions (status updates, unlinked issues, question candidates, Confluence pages to review).
|
|
20493
20634
|
- \`fetch_jira_statuses\` \u2014 **read-only**: discover all Jira statuses in a project and show their Marvin mappings (mapped vs unmapped).
|
|
@@ -21188,11 +21329,30 @@ function formatDate(iso) {
|
|
|
21188
21329
|
function typeLabel(type) {
|
|
21189
21330
|
return type.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
21190
21331
|
}
|
|
21332
|
+
var JIRA_SVG = `<svg class="integration-icon" viewBox="0 0 256 256" width="14" height="14" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="jg1" x1="98.03%" y1="0.16%" x2="58.89%" y2="40.87%"><stop offset="18%" stop-color="#0052CC"/><stop offset="100%" stop-color="#2684FF"/></linearGradient><linearGradient id="jg2" x1="100.17%" y1="0.05%" x2="55.76%" y2="45.19%"><stop offset="18%" stop-color="#0052CC"/><stop offset="100%" stop-color="#2684FF"/></linearGradient></defs><path d="M244.658 0H121.707a55.502 55.502 0 0 0 55.502 55.502h22.649V77.37c.02 30.625 24.841 55.447 55.466 55.502V10.666C255.324 4.777 250.55 0 244.658 0z" fill="#2684FF"/><path d="M183.822 61.262H60.872c.019 30.625 24.84 55.447 55.466 55.502h22.649v21.868c.02 30.597 24.798 55.408 55.395 55.502V71.928c0-5.891-4.776-10.666-10.56-10.666z" fill="url(#jg1)"/><path d="M122.951 122.489H0c0 30.653 24.85 55.502 55.502 55.502h22.72v21.868c.02 30.597 24.798 55.408 55.396 55.502V133.155c0-5.891-4.776-10.666-10.667-10.666z" fill="url(#jg2)"/></svg>`;
|
|
21333
|
+
var CONFLUENCE_SVG = `<svg class="integration-icon" viewBox="0 0 256 246" width="14" height="14" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="cg1" x1="99.14%" y1="113.9%" x2="33.86%" y2="37.96%"><stop offset="18%" stop-color="#0052CC"/><stop offset="100%" stop-color="#2684FF"/></linearGradient><linearGradient id="cg2" x1="0.86%" y1="-13.9%" x2="66.14%" y2="62.04%"><stop offset="18%" stop-color="#0052CC"/><stop offset="100%" stop-color="#2684FF"/></linearGradient></defs><path d="M9.26 187.28c-3.14 5.06-6.71 10.98-9.26 15.53a7.84 7.84 0 0 0 2.83 10.72l67.58 40.48a7.85 7.85 0 0 0 10.72-2.63c2.14-3.54 5.01-8.25 8.15-13.41 22.18-36.47 44.67-32.02 85.83-13.41l68.59 31.05a7.85 7.85 0 0 0 10.42-3.94l29.24-66.24a7.85 7.85 0 0 0-3.84-10.32c-20.53-9.27-61.49-27.75-87.33-39.45-72.2-32.73-133.87-30.05-182.93 51.62z" fill="url(#cg1)"/><path d="M246.11 58.24c3.14-5.06 6.71-10.98 9.26-15.53a7.84 7.84 0 0 0-2.83-10.72L184.96 0a7.85 7.85 0 0 0-10.72 2.63c-2.14 3.54-5.01 8.25-8.15 13.41-22.18 36.47-44.67 32.02-85.83 13.41L12.37 -1.6a7.85 7.85 0 0 0-10.42 3.94L-27.29 68.58a7.85 7.85 0 0 0 3.84 10.32c20.53 9.27 61.49 27.75 87.33 39.45 72.2 32.73 133.87 30.05 182.23-60.11z" fill="url(#cg2)"/></svg>`;
|
|
21191
21334
|
function jiraIcon(jiraKey, jiraUrl) {
|
|
21192
21335
|
if (!jiraKey) return "";
|
|
21193
21336
|
const href = jiraUrl ?? "#";
|
|
21194
21337
|
const title = escapeHtml(jiraKey);
|
|
21195
|
-
return `<a href="${escapeHtml(href)}" target="_blank" rel="noopener" title="Jira: ${title}" class="
|
|
21338
|
+
return `<a href="${escapeHtml(href)}" target="_blank" rel="noopener" title="Jira: ${title}" class="integration-link jira-link">${JIRA_SVG}</a>`;
|
|
21339
|
+
}
|
|
21340
|
+
function confluenceIcon(confluenceUrl, confluenceTitle) {
|
|
21341
|
+
if (!confluenceUrl) return "";
|
|
21342
|
+
const title = confluenceTitle ? escapeHtml(confluenceTitle) : "Confluence";
|
|
21343
|
+
return `<a href="${escapeHtml(confluenceUrl)}" target="_blank" rel="noopener" title="${title}" class="integration-link confluence-link">${CONFLUENCE_SVG}</a>`;
|
|
21344
|
+
}
|
|
21345
|
+
function integrationIcons(frontmatter) {
|
|
21346
|
+
const jira = jiraIcon(
|
|
21347
|
+
frontmatter.jiraKey,
|
|
21348
|
+
frontmatter.jiraUrl
|
|
21349
|
+
);
|
|
21350
|
+
const confluence = confluenceIcon(
|
|
21351
|
+
frontmatter.confluenceUrl,
|
|
21352
|
+
frontmatter.confluenceTitle
|
|
21353
|
+
);
|
|
21354
|
+
if (!jira && !confluence) return "";
|
|
21355
|
+
return `<span class="integration-icons">${jira}${confluence}</span>`;
|
|
21196
21356
|
}
|
|
21197
21357
|
function renderMarkdown(md) {
|
|
21198
21358
|
const lines = md.split("\n");
|
|
@@ -23059,17 +23219,22 @@ tr:hover td {
|
|
|
23059
23219
|
.owner-badge-dm { background: rgba(52, 211, 153, 0.18); color: #34d399; }
|
|
23060
23220
|
.owner-badge-other { background: rgba(139, 143, 164, 0.12); color: var(--text-dim); }
|
|
23061
23221
|
|
|
23062
|
-
/* Jira
|
|
23063
|
-
.
|
|
23222
|
+
/* Integration icons (Jira, Confluence) */
|
|
23223
|
+
.integration-icons {
|
|
23064
23224
|
display: inline-flex;
|
|
23065
23225
|
align-items: center;
|
|
23226
|
+
gap: 0.25rem;
|
|
23066
23227
|
vertical-align: middle;
|
|
23067
|
-
margin-left: 0.
|
|
23228
|
+
margin-left: 0.5rem;
|
|
23229
|
+
}
|
|
23230
|
+
.integration-link {
|
|
23231
|
+
display: inline-flex;
|
|
23232
|
+
align-items: center;
|
|
23068
23233
|
opacity: 0.7;
|
|
23069
23234
|
transition: opacity 0.15s;
|
|
23070
23235
|
}
|
|
23071
|
-
.
|
|
23072
|
-
.
|
|
23236
|
+
.integration-link:hover { opacity: 1; }
|
|
23237
|
+
.integration-icon { vertical-align: middle; }
|
|
23073
23238
|
|
|
23074
23239
|
/* Group header rows (PO dashboard decisions/deps) */
|
|
23075
23240
|
.group-header-row td {
|
|
@@ -23095,7 +23260,7 @@ function documentsPage(data) {
|
|
|
23095
23260
|
(doc) => `
|
|
23096
23261
|
<tr>
|
|
23097
23262
|
<td><a href="/docs/${data.type}/${doc.frontmatter.id}">${escapeHtml(doc.frontmatter.id)}</a></td>
|
|
23098
|
-
<td><a href="/docs/${data.type}/${doc.frontmatter.id}">${escapeHtml(doc.frontmatter.title)}</a>${
|
|
23263
|
+
<td><a href="/docs/${data.type}/${doc.frontmatter.id}">${escapeHtml(doc.frontmatter.title)}</a>${integrationIcons(doc.frontmatter)}</td>
|
|
23099
23264
|
<td>${statusBadge(doc.frontmatter.status)}</td>
|
|
23100
23265
|
<td>${escapeHtml(doc.frontmatter.owner ?? "\u2014")}</td>
|
|
23101
23266
|
<td>${doc.frontmatter.priority ? `<span class="priority-${doc.frontmatter.priority.toLowerCase()}">${escapeHtml(doc.frontmatter.priority)}</span>` : "\u2014"}</td>
|
|
@@ -23184,7 +23349,7 @@ function documentDetailPage(doc) {
|
|
|
23184
23349
|
</div>
|
|
23185
23350
|
|
|
23186
23351
|
<div class="page-header">
|
|
23187
|
-
<h2>${escapeHtml(fm.title)}${
|
|
23352
|
+
<h2>${escapeHtml(fm.title)}${integrationIcons(fm)}</h2>
|
|
23188
23353
|
<div class="subtitle">${escapeHtml(fm.id)} · ${escapeHtml(label)}</div>
|
|
23189
23354
|
</div>
|
|
23190
23355
|
|
|
@@ -24615,7 +24780,7 @@ function renderItemRows(items, borderColor, showOwner, depth = 0) {
|
|
|
24615
24780
|
const row = `
|
|
24616
24781
|
<tr class="${classes.join(" ")}" style="--focus-color: ${borderColor}">
|
|
24617
24782
|
<td${indent}><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
|
|
24618
|
-
<td>${escapeHtml(w.title)}${jiraIcon(w.jiraKey, w.jiraUrl)}</td>
|
|
24783
|
+
<td>${escapeHtml(w.title)}${jiraIcon(w.jiraKey, w.jiraUrl)}${confluenceIcon(w.confluenceUrl, w.confluenceTitle)}</td>
|
|
24619
24784
|
${ownerCell}
|
|
24620
24785
|
<td>${statusBadge(w.status)}</td>
|
|
24621
24786
|
<td>${progressCell}</td>
|
|
@@ -26240,7 +26405,7 @@ function boardPage(data, basePath = "/board") {
|
|
|
26240
26405
|
<div class="board-card">
|
|
26241
26406
|
<a href="/docs/${doc.frontmatter.type}/${doc.frontmatter.id}">
|
|
26242
26407
|
<div class="bc-id">${escapeHtml(doc.frontmatter.id)}</div>
|
|
26243
|
-
<div class="bc-title">${escapeHtml(doc.frontmatter.title)}${
|
|
26408
|
+
<div class="bc-title">${escapeHtml(doc.frontmatter.title)}${integrationIcons(doc.frontmatter)}</div>
|
|
26244
26409
|
${doc.frontmatter.owner ? `<div class="bc-owner">${escapeHtml(doc.frontmatter.owner)}</div>` : ""}
|
|
26245
26410
|
</a>
|
|
26246
26411
|
</div>`
|