@r3nner/syntax-highlight-mcp 1.0.0
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/README.md +4 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +7 -0
- package/package.json +13 -0
- package/src/index.ts +72 -0
package/README.md
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// packages/mcp/src/index.ts
|
|
2
|
+
var MCP_HIGHLIGHT_RESOURCE_URI = "ui://syntax-highlight/code.html";
|
|
3
|
+
var MCP_HIGHLIGHT_MIME_TYPE = "text/html;profile=mcp-app";
|
|
4
|
+
function createRenderToolResult(payload, resourceUri = MCP_HIGHLIGHT_RESOURCE_URI) {
|
|
5
|
+
return {
|
|
6
|
+
structuredContent: payload,
|
|
7
|
+
content: [{ type: "text", text: `Rendered ${payload.document.languageId} source code.` }],
|
|
8
|
+
_meta: {
|
|
9
|
+
ui: { resourceUri },
|
|
10
|
+
"openai/outputTemplate": resourceUri
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function widgetHtml() {
|
|
15
|
+
return `<!doctype html>
|
|
16
|
+
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width">
|
|
17
|
+
<style>
|
|
18
|
+
:root{color-scheme:light dark}body{margin:0;padding:8px;background:transparent;color:CanvasText}
|
|
19
|
+
.frame{border:1px solid color-mix(in srgb,CanvasText 18%,transparent);border-radius:10px;overflow:hidden}
|
|
20
|
+
.title{padding:8px 12px;border-bottom:1px solid color-mix(in srgb,CanvasText 14%,transparent);font:600 12px system-ui}
|
|
21
|
+
pre{margin:0;padding:12px;overflow:auto;white-space:pre;tab-size:4;font:13px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace}
|
|
22
|
+
.sh-token--comment{color:#6a9955}.sh-token--reserved-word,.sh-token--contextual-word{color:#c586c0}
|
|
23
|
+
.sh-token--builtin-type,.sh-token--type-reference,.sh-token--unit{color:#4ec9b0}
|
|
24
|
+
.sh-token--declared-name{color:#4fc1ff}.sh-token--invocation-name{color:#dcdcaa}
|
|
25
|
+
.sh-token--text,.sh-token--character{color:#ce9178}
|
|
26
|
+
.sh-token--exact-number,.sh-token--rumber,.sh-token--point-literal{color:#b5cea8}
|
|
27
|
+
.sh-token--symbolic-operator{color:#d4d4d4}.sh-token--literal-constant{color:#569cd6}
|
|
28
|
+
</style></head><body><div class="frame"><div class="title" hidden></div><pre><code></code></pre></div>
|
|
29
|
+
<script>
|
|
30
|
+
const code=document.querySelector("code");const title=document.querySelector(".title");
|
|
31
|
+
function render(payload){const doc=payload&&payload.document;if(!doc||typeof doc.source!=="string"||!Array.isArray(doc.spans))return;
|
|
32
|
+
code.replaceChildren();let cursor=0;for(const span of doc.spans){if(!Number.isInteger(span.from)||!Number.isInteger(span.to)||span.from<cursor||span.to>doc.source.length)continue;
|
|
33
|
+
code.append(document.createTextNode(doc.source.slice(cursor,span.from)));const el=document.createElement("span");
|
|
34
|
+
el.className="sh-token sh-token--"+(/^[a-z][a-z0-9-]*$/.test(span.categoryId)?span.categoryId:"unknown");
|
|
35
|
+
el.textContent=doc.source.slice(span.from,span.to);code.append(el);cursor=span.to}
|
|
36
|
+
code.append(document.createTextNode(doc.source.slice(cursor)));title.textContent=payload.title||doc.languageId;title.hidden=false}
|
|
37
|
+
window.addEventListener("message",event=>{if(event.source!==window.parent)return;const message=event.data;
|
|
38
|
+
if(message&&message.jsonrpc==="2.0"&&message.method==="ui/notifications/tool-result")render(message.params&&message.params.structuredContent)});
|
|
39
|
+
window.parent.postMessage({jsonrpc:"2.0",id:1,method:"ui/initialize",params:{protocolVersion:"2026-01-26",capabilities:{}}},"*");
|
|
40
|
+
<\/script></body></html>`;
|
|
41
|
+
}
|
|
42
|
+
function createMcpHighlightResource(resourceUri = MCP_HIGHLIGHT_RESOURCE_URI) {
|
|
43
|
+
return {
|
|
44
|
+
uri: resourceUri,
|
|
45
|
+
mimeType: MCP_HIGHLIGHT_MIME_TYPE,
|
|
46
|
+
text: widgetHtml(),
|
|
47
|
+
_meta: { ui: { prefersBorder: false } }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
MCP_HIGHLIGHT_MIME_TYPE,
|
|
52
|
+
MCP_HIGHLIGHT_RESOURCE_URI,
|
|
53
|
+
createMcpHighlightResource,
|
|
54
|
+
createRenderToolResult
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import type { HighlightDocument } from \"@r3nner/syntax-highlight-core\";\n\nexport const MCP_HIGHLIGHT_RESOURCE_URI = \"ui://syntax-highlight/code.html\";\nexport const MCP_HIGHLIGHT_MIME_TYPE = \"text/html;profile=mcp-app\";\n\nexport interface McpHighlightPayload {\n document: HighlightDocument;\n title?: string;\n}\n\nexport function createRenderToolResult(\n payload: McpHighlightPayload,\n resourceUri = MCP_HIGHLIGHT_RESOURCE_URI,\n): {\n structuredContent: McpHighlightPayload;\n content: Array<{ type: \"text\"; text: string }>;\n _meta: { ui: { resourceUri: string }; \"openai/outputTemplate\": string };\n} {\n return {\n structuredContent: payload,\n content: [{ type: \"text\", text: `Rendered ${payload.document.languageId} source code.` }],\n _meta: {\n ui: { resourceUri },\n \"openai/outputTemplate\": resourceUri,\n },\n };\n}\n\nfunction widgetHtml(): string {\n return `<!doctype html>\n<html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">\n<style>\n:root{color-scheme:light dark}body{margin:0;padding:8px;background:transparent;color:CanvasText}\n.frame{border:1px solid color-mix(in srgb,CanvasText 18%,transparent);border-radius:10px;overflow:hidden}\n.title{padding:8px 12px;border-bottom:1px solid color-mix(in srgb,CanvasText 14%,transparent);font:600 12px system-ui}\npre{margin:0;padding:12px;overflow:auto;white-space:pre;tab-size:4;font:13px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace}\n.sh-token--comment{color:#6a9955}.sh-token--reserved-word,.sh-token--contextual-word{color:#c586c0}\n.sh-token--builtin-type,.sh-token--type-reference,.sh-token--unit{color:#4ec9b0}\n.sh-token--declared-name{color:#4fc1ff}.sh-token--invocation-name{color:#dcdcaa}\n.sh-token--text,.sh-token--character{color:#ce9178}\n.sh-token--exact-number,.sh-token--rumber,.sh-token--point-literal{color:#b5cea8}\n.sh-token--symbolic-operator{color:#d4d4d4}.sh-token--literal-constant{color:#569cd6}\n</style></head><body><div class=\"frame\"><div class=\"title\" hidden></div><pre><code></code></pre></div>\n<script>\nconst code=document.querySelector(\"code\");const title=document.querySelector(\".title\");\nfunction render(payload){const doc=payload&&payload.document;if(!doc||typeof doc.source!==\"string\"||!Array.isArray(doc.spans))return;\n code.replaceChildren();let cursor=0;for(const span of doc.spans){if(!Number.isInteger(span.from)||!Number.isInteger(span.to)||span.from<cursor||span.to>doc.source.length)continue;\n code.append(document.createTextNode(doc.source.slice(cursor,span.from)));const el=document.createElement(\"span\");\n el.className=\"sh-token sh-token--\"+(/^[a-z][a-z0-9-]*$/.test(span.categoryId)?span.categoryId:\"unknown\");\n el.textContent=doc.source.slice(span.from,span.to);code.append(el);cursor=span.to}\n code.append(document.createTextNode(doc.source.slice(cursor)));title.textContent=payload.title||doc.languageId;title.hidden=false}\nwindow.addEventListener(\"message\",event=>{if(event.source!==window.parent)return;const message=event.data;\n if(message&&message.jsonrpc===\"2.0\"&&message.method===\"ui/notifications/tool-result\")render(message.params&&message.params.structuredContent)});\nwindow.parent.postMessage({jsonrpc:\"2.0\",id:1,method:\"ui/initialize\",params:{protocolVersion:\"2026-01-26\",capabilities:{}}},\"*\");\n</script></body></html>`;\n}\n\nexport function createMcpHighlightResource(\n resourceUri = MCP_HIGHLIGHT_RESOURCE_URI,\n): {\n uri: string;\n mimeType: string;\n text: string;\n _meta: { ui: { prefersBorder: boolean } };\n} {\n return {\n uri: resourceUri,\n mimeType: MCP_HIGHLIGHT_MIME_TYPE,\n text: widgetHtml(),\n _meta: { ui: { prefersBorder: false } },\n };\n}\n"],
|
|
5
|
+
"mappings": ";AAEO,IAAM,6BAA6B;AACnC,IAAM,0BAA0B;AAOhC,SAAS,uBACd,SACA,cAAc,4BAKd;AACA,SAAO;AAAA,IACL,mBAAmB;AAAA,IACnB,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,YAAY,QAAQ,SAAS,UAAU,gBAAgB,CAAC;AAAA,IACxF,OAAO;AAAA,MACL,IAAI,EAAE,YAAY;AAAA,MAClB,yBAAyB;AAAA,IAC3B;AAAA,EACF;AACF;AAEA,SAAS,aAAqB;AAC5B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BT;AAEO,SAAS,2BACd,cAAc,4BAMd;AACA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,UAAU;AAAA,IACV,MAAM,WAAW;AAAA,IACjB,OAAO,EAAE,IAAI,EAAE,eAAe,MAAM,EAAE;AAAA,EACxC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@r3nner/syntax-highlight-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Portable MCP Apps syntax highlighting component.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": { "type": "git", "url": "git+https://github.com/R3Neer/syntax-highlight.git", "directory": "packages/mcp" },
|
|
8
|
+
"files": ["dist", "src", "README.md"],
|
|
9
|
+
"exports": { ".": { "types": "./src/index.ts", "import": "./dist/index.js" } },
|
|
10
|
+
"types": "./src/index.ts",
|
|
11
|
+
"dependencies": { "@r3nner/syntax-highlight-core": "1.0.0", "@r3nner/syntax-highlight-html": "1.0.0" },
|
|
12
|
+
"sideEffects": false
|
|
13
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { HighlightDocument } from "@r3nner/syntax-highlight-core";
|
|
2
|
+
|
|
3
|
+
export const MCP_HIGHLIGHT_RESOURCE_URI = "ui://syntax-highlight/code.html";
|
|
4
|
+
export const MCP_HIGHLIGHT_MIME_TYPE = "text/html;profile=mcp-app";
|
|
5
|
+
|
|
6
|
+
export interface McpHighlightPayload {
|
|
7
|
+
document: HighlightDocument;
|
|
8
|
+
title?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function createRenderToolResult(
|
|
12
|
+
payload: McpHighlightPayload,
|
|
13
|
+
resourceUri = MCP_HIGHLIGHT_RESOURCE_URI,
|
|
14
|
+
): {
|
|
15
|
+
structuredContent: McpHighlightPayload;
|
|
16
|
+
content: Array<{ type: "text"; text: string }>;
|
|
17
|
+
_meta: { ui: { resourceUri: string }; "openai/outputTemplate": string };
|
|
18
|
+
} {
|
|
19
|
+
return {
|
|
20
|
+
structuredContent: payload,
|
|
21
|
+
content: [{ type: "text", text: `Rendered ${payload.document.languageId} source code.` }],
|
|
22
|
+
_meta: {
|
|
23
|
+
ui: { resourceUri },
|
|
24
|
+
"openai/outputTemplate": resourceUri,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function widgetHtml(): string {
|
|
30
|
+
return `<!doctype html>
|
|
31
|
+
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width">
|
|
32
|
+
<style>
|
|
33
|
+
:root{color-scheme:light dark}body{margin:0;padding:8px;background:transparent;color:CanvasText}
|
|
34
|
+
.frame{border:1px solid color-mix(in srgb,CanvasText 18%,transparent);border-radius:10px;overflow:hidden}
|
|
35
|
+
.title{padding:8px 12px;border-bottom:1px solid color-mix(in srgb,CanvasText 14%,transparent);font:600 12px system-ui}
|
|
36
|
+
pre{margin:0;padding:12px;overflow:auto;white-space:pre;tab-size:4;font:13px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace}
|
|
37
|
+
.sh-token--comment{color:#6a9955}.sh-token--reserved-word,.sh-token--contextual-word{color:#c586c0}
|
|
38
|
+
.sh-token--builtin-type,.sh-token--type-reference,.sh-token--unit{color:#4ec9b0}
|
|
39
|
+
.sh-token--declared-name{color:#4fc1ff}.sh-token--invocation-name{color:#dcdcaa}
|
|
40
|
+
.sh-token--text,.sh-token--character{color:#ce9178}
|
|
41
|
+
.sh-token--exact-number,.sh-token--rumber,.sh-token--point-literal{color:#b5cea8}
|
|
42
|
+
.sh-token--symbolic-operator{color:#d4d4d4}.sh-token--literal-constant{color:#569cd6}
|
|
43
|
+
</style></head><body><div class="frame"><div class="title" hidden></div><pre><code></code></pre></div>
|
|
44
|
+
<script>
|
|
45
|
+
const code=document.querySelector("code");const title=document.querySelector(".title");
|
|
46
|
+
function render(payload){const doc=payload&&payload.document;if(!doc||typeof doc.source!=="string"||!Array.isArray(doc.spans))return;
|
|
47
|
+
code.replaceChildren();let cursor=0;for(const span of doc.spans){if(!Number.isInteger(span.from)||!Number.isInteger(span.to)||span.from<cursor||span.to>doc.source.length)continue;
|
|
48
|
+
code.append(document.createTextNode(doc.source.slice(cursor,span.from)));const el=document.createElement("span");
|
|
49
|
+
el.className="sh-token sh-token--"+(/^[a-z][a-z0-9-]*$/.test(span.categoryId)?span.categoryId:"unknown");
|
|
50
|
+
el.textContent=doc.source.slice(span.from,span.to);code.append(el);cursor=span.to}
|
|
51
|
+
code.append(document.createTextNode(doc.source.slice(cursor)));title.textContent=payload.title||doc.languageId;title.hidden=false}
|
|
52
|
+
window.addEventListener("message",event=>{if(event.source!==window.parent)return;const message=event.data;
|
|
53
|
+
if(message&&message.jsonrpc==="2.0"&&message.method==="ui/notifications/tool-result")render(message.params&&message.params.structuredContent)});
|
|
54
|
+
window.parent.postMessage({jsonrpc:"2.0",id:1,method:"ui/initialize",params:{protocolVersion:"2026-01-26",capabilities:{}}},"*");
|
|
55
|
+
</script></body></html>`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function createMcpHighlightResource(
|
|
59
|
+
resourceUri = MCP_HIGHLIGHT_RESOURCE_URI,
|
|
60
|
+
): {
|
|
61
|
+
uri: string;
|
|
62
|
+
mimeType: string;
|
|
63
|
+
text: string;
|
|
64
|
+
_meta: { ui: { prefersBorder: boolean } };
|
|
65
|
+
} {
|
|
66
|
+
return {
|
|
67
|
+
uri: resourceUri,
|
|
68
|
+
mimeType: MCP_HIGHLIGHT_MIME_TYPE,
|
|
69
|
+
text: widgetHtml(),
|
|
70
|
+
_meta: { ui: { prefersBorder: false } },
|
|
71
|
+
};
|
|
72
|
+
}
|