likec4 1.59.1 → 1.59.3
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/__app__/src/chunks/AIChat.mjs +21 -26
- package/__app__/src/chunks/LikeC4Styles.mjs +257 -263
- package/__app__/src/chunks/ProjectsOverview.mjs +58 -58
- package/__app__/src/chunks/hooks.mjs +106 -80
- package/__app__/src/chunks/libs/@floating-ui.mjs +646 -332
- package/__app__/src/chunks/libs/@mantine.mjs +1911 -1734
- package/__app__/src/chunks/libs/@tanstack-ai.mjs +26 -26
- package/__app__/src/chunks/libs/@tanstack.mjs +42 -41
- package/__app__/src/chunks/libs/@xstate/react.mjs +59 -40
- package/__app__/src/chunks/libs/@xyflow/react.mjs +532 -445
- package/__app__/src/chunks/libs/bezier-js.mjs +10 -9
- package/__app__/src/chunks/libs/d3.mjs +16 -36
- package/__app__/src/chunks/libs/fast-equals.mjs +12 -11
- package/__app__/src/chunks/libs/framer.mjs +294 -273
- package/__app__/src/chunks/libs/zod.mjs +17 -14
- package/__app__/src/chunks/rolldown-runtime.mjs +2 -2
- package/__app__/src/chunks/styled-system.mjs +9 -15
- package/__app__/src/main.mjs +15994 -15936
- package/__app__/src/style.css +1 -1
- package/config/schema.json +35 -0
- package/dist/app/render-view-client.css +1 -0
- package/dist/app/render-view-client.js +745 -0
- package/dist/chunks/enableServer.mjs +1 -1
- package/dist/chunks/filenames.mjs +7 -6
- package/dist/chunks/index.d.mts +11 -0
- package/dist/chunks/index2.d.mts +47 -7
- package/dist/chunks/libs/@chevrotain/gast.mjs +1 -1
- package/dist/chunks/libs/@chevrotain/regexp-to-ast.mjs +5 -5
- package/dist/chunks/libs/@logtape/logtape.mjs +1 -1
- package/dist/chunks/libs/@lume/kiwi.mjs +1 -1
- package/dist/chunks/libs/birpc.mjs +1 -1
- package/dist/chunks/libs/chevrotain-allstar.mjs +1 -1
- package/dist/chunks/libs/chevrotain.mjs +16 -16
- package/dist/chunks/libs/json5.mjs +3 -3
- package/dist/chunks/libs/langium.mjs +11 -11
- package/dist/chunks/libs/merge-error-cause.mjs +2 -2
- package/dist/chunks/libs/package-manager-detector.mjs +1 -1
- package/dist/chunks/libs/pako.mjs +1 -1
- package/dist/chunks/libs/picomatch.mjs +1 -1
- package/dist/chunks/libs/pretty-ms.mjs +1 -1
- package/dist/chunks/libs/remeda.mjs +1 -1
- package/dist/chunks/libs/zod.mjs +4 -4
- package/dist/chunks/node.mjs +69 -57
- package/dist/chunks/rolldown-runtime.mjs +1 -1
- package/dist/chunks/sequence-view.mjs +1 -1
- package/dist/chunks/vite-plugin.mjs +161 -50
- package/dist/cli/index.mjs +272 -162
- package/dist/config/index.d.mts +7 -1
- package/dist/config/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/vite-plugin/internal/index.d.mts +64 -27
- package/dist/vite-plugin/internal/index.mjs +76 -39
- package/package.json +41 -41
- package/react/index.d.mts +76 -1
- package/react/index.mjs +7310 -6785
- package/vite-plugin-modules.d.ts +18 -0
- package/dist/chunks/dist.mjs +0 -10
- package/dist/chunks/logger.mjs +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{i as e}from"./rolldown-runtime.mjs";import{
|
|
1
|
+
import{i as e}from"./rolldown-runtime.mjs";import{E as t,S as n,_ as r,g as i,r as a,x as o,y as s}from"./node.mjs";import{_ as c,b as l,g as u,h as d,y as f}from"./libs/langium.mjs";import{o as p}from"./libs/ufo.mjs";import{t as m}from"./libs/json5.mjs";import{C as h,T as g,a as _,b as v,l as y,n as b,z as ee}from"./libs/zod.mjs";import{l as x}from"./filenames.mjs";import{$ as S,B as te,F as C,H as ne,I as w,J as T,N as E,Q as D,U as O,Z as k,b as A,c as j,h as re,k as M,o as N,r as P,t as F,tt as I,v as ie,w as L,y as ae}from"./libs/remeda.mjs";import{n as oe,t as se}from"./libs/package-manager-detector.mjs";import{t as ce}from"./libs/birpc.mjs";import{t as le}from"./libs/pako.mjs";import{createRequire as ue}from"node:module";import{mkdir as de,readFile as fe,writeFile as pe}from"node:fs/promises";import{resolve as R}from"node:path";import{RichText as me,exact as he,flattenMarkdownOrString as z}from"@likec4/core/types";import{DefaultMap as B,LikeC4Styles as ge,exact as _e,invariant as ve,nonexhaustive as ye}from"@likec4/core";import{compareNatural as be,nonNullable as xe}from"@likec4/core/utils";import"@likec4/core/model";import Se from"nano-spawn";import{existsSync as Ce}from"node:fs";import{env as V}from"std-env";import H,{cwd as we}from"node:process";const pDebounce=(e,t,n={})=>{if(!Number.isFinite(t))throw TypeError("Expected `wait` to be a finite number");let r,i,a=[],onAbort=()=>{clearTimeout(i),i=void 0;try{n.signal?.throwIfAborted()}catch(e){for(let{reject:t}of a)t(e);a=[]}};return function(...o){return new Promise((s,c)=>{try{n.signal?.throwIfAborted()}catch(e){c(e);return}let l=n.before&&!i;clearTimeout(i),i=setTimeout(async()=>{i=void 0;let t=a;a=[];try{let i=n.before?r:await e.apply(this,o);for(let{resolve:e}of t)e(i)}catch(e){for(let{reject:n}of t)n(e)}r=void 0,n.signal?.removeEventListener(`abort`,onAbort)},t),l?(async()=>{try{r=await e.apply(this,o),s(r)}catch(e){c(e)}})():(a.push({resolve:s,reject:c}),n.signal&&a.length===1&&n.signal.addEventListener(`abort`,onAbort,{once:!0}))})}};pDebounce.promise=(e,t={})=>{let n,r;return async function(...i){if(n)return t.after?(r??={resolvers:[]},r.arguments=i,r.context=this,new Promise((e,t)=>{r.resolvers.push({resolve:e,reject:t})})):n;n=(async()=>{let t,n;try{t=await e.apply(this,i)}catch(e){n=e}for(;r;){let t=r;r=void 0;try{let n=await e.apply(t.context,t.arguments);for(let{resolve:e}of t.resolvers)e(n)}catch(e){for(let{reject:n}of t.resolvers)n(e)}}if(n)throw n;return t})();try{return await n}finally{n=void 0}}};function effectiveWebappExportFormats(e){let t=e.webapp?.exportFormats;if(!t)return[...x];let n=new Set(t);return x.filter(e=>n.has(e))}function isWebappExportFormatEnabled(e,t){return effectiveWebappExportFormats(e).includes(t)}function isJsonStringifyOutput(e){if(e.length===0)return!1;try{return JSON.parse(e),!0}catch{return!1}}function hardenJsonStringLiteralForEmbeddedScript(e){if(typeof e!=`string`)throw TypeError(`hardenJsonStringLiteralForEmbeddedScript: expected JSON.stringify(...) output as a string`);if(!isJsonStringifyOutput(e))throw TypeError(`hardenJsonStringLiteralForEmbeddedScript: expected JSON.stringify(...) output (string, object, array, number, boolean, or null)`);return e.replaceAll(`<`,`\\u003C`).replaceAll(`>`,`\\u003E`).replaceAll(`/`,`\\u002F`).replaceAll(`\u2028`,`\\u2028`).replaceAll(`\u2029`,`\\u2029`)}function generateMatches(e,t=`.js`){return{matches:n=>{let{module:r,projectId:i}=n.match(/likec4:plugin\/(?<projectId>.+)\/(?<module>.+)$/)?.groups??n.match(/likec4:(?<module>.+)\/(?<projectId>.+)$/)?.groups??{};return!r||!i?null:(r.endsWith(t)&&(r=r.slice(0,-t.length)),r===e?i:null)},virtualId:n=>p(`likec4:plugin`,n,e)+t}}function generateCombinedProjects(e,t,n){return{id:`likec4:${e}`,virtualId:`likec4:plugin/`+e+`.js`,async load({projects:r}){logGenerating(e);let i=(n?r.filter(({config:e})=>isWebappExportFormatEnabled(e,n)):r).map(({id:t})=>`${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(t))}: async () => await import(${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(p(`likec4:${e}`,t)))})`),a=n?hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(`Project does not enable ${n} export: `)):null;return{code:`
|
|
2
2
|
export let ${t}Fn = {
|
|
3
|
-
${
|
|
3
|
+
${i.join(`,
|
|
4
4
|
`)}
|
|
5
5
|
}
|
|
6
6
|
|
|
@@ -9,38 +9,35 @@ export async function ${t}(projectId) {
|
|
|
9
9
|
if (!fn) {
|
|
10
10
|
const projects = Object.keys(${t}Fn)
|
|
11
11
|
console.error('Unknown projectId: ' + projectId + ' (available: ' + projects + ')')
|
|
12
|
+
${n?`throw new Error(${a} + projectId)`:`
|
|
12
13
|
if (projects.length === 0) {
|
|
13
14
|
throw new Error('No projects found, invalid state')
|
|
14
15
|
}
|
|
15
16
|
projectId = projects[0]
|
|
16
17
|
console.warn('Falling back to project: ' + projectId)
|
|
17
18
|
fn = ${t}Fn[projectId]
|
|
19
|
+
`}
|
|
18
20
|
}
|
|
19
21
|
return await fn()
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
if (import.meta.hot) {
|
|
23
25
|
import.meta.hot.accept(md => {
|
|
24
|
-
if (!import.meta.hot.data.$update) {
|
|
25
|
-
import.meta.hot.data.$update = ${t}Fn
|
|
26
|
-
}
|
|
27
26
|
const update = md.${t}Fn
|
|
28
27
|
if (update) {
|
|
29
|
-
|
|
30
|
-
import.meta.hot.data.$update[id] ??= fn
|
|
31
|
-
}
|
|
28
|
+
${t}Fn = update
|
|
32
29
|
} else {
|
|
33
30
|
import.meta.hot.invalidate()
|
|
34
31
|
}
|
|
35
32
|
})
|
|
36
33
|
}
|
|
37
|
-
`,moduleType:`js`}}}}function isInstalled(e){try{return!!import.meta.resolve(e,
|
|
34
|
+
`,moduleType:`js`}}}}const U=n.getChild(`vite`);function logGenerating(e,t){t?U.info(s.dim(`generating `)+s.magenta(`likec4:${e}/`)+s.magentaBright(t)):U.info(s.dim(`generating `)+s.magenta(`likec4:${e}`))}function isInstalled(e){try{return!!import.meta.resolve(e,H.cwd())}catch(e){return U.trace(t(e)),!1}}async function ensurePackage(e){let n=U.getChild(`pkg`);if(isInstalled(e)){n.trace`${e} installed`;return}n.warn(s.dim(`not found `)+s.green(e));let r=xe(await se(),()=>{n.error`Package manager not detected, install ${e} manually`,H.exit(1)}),{command:i,args:a}=xe(oe(r.agent,`add`,[e]),()=>{n.error`Install package ${e} manually`,H.exit(1)});n.info(s.dim(`installing `)+s.green(e));try{await Se(i,a)}catch(r){n.debug(t(r)),n.error`Install package ${e} manually`,H.exit(1)}}const W=U.getChild(`ai`);function chooseModel(e,t){let n=V[e];return n||=(W.info(`I will use `+s.green(t)+` model `+s.dim(`you can override with `)+s.yellow(e)+s.dim(` env var`)),t),n}const G=16e3;async function loadOpenAI(){W.info(`Found `+s.yellow(`OPENAI_API_KEY`)+s.dim(`, loading @tanstack/ai-openai`)),await ensurePackage(`@tanstack/ai-openai`);let{openaiText:e}=await import(`@tanstack/ai-openai`);return{adapter:e(chooseModel(`OPENAI_CHAT_MODEL`,`gpt-5.2`)),modelOptions:{reasoning:{effort:`medium`}},maxTokens:G}}async function loadOpenRouter(){W.info(`Found `+s.yellow(`OPENROUTER_API_KEY`)+s.dim(`, loading @tanstack/ai-openrouter`)),await ensurePackage(`@tanstack/ai-openrouter`);let{openRouterText:e}=await import(`@tanstack/ai-openrouter`);return{adapter:e(chooseModel(`OPENROUTER_CHAT_MODEL`,`openai/gpt-5.4`)),maxTokens:G}}async function loadAnthropic(){W.info(`Found `+s.yellow(`ANTHROPIC_API_KEY`)+s.dim(`, loading @tanstack/ai-anthropic`)),await ensurePackage(`@tanstack/ai-anthropic`);let{anthropicText:e}=await import(`@tanstack/ai-anthropic`);return{adapter:e(chooseModel(`ANTHROPIC_CHAT_MODEL`,`claude-sonnet-4-6`)),maxTokens:G}}async function loadGemini(){W.info(`Found `+s.yellow(`GEMINI_API_KEY`)+s.dim(`, loading @tanstack/ai-gemini`)),await ensurePackage(`@tanstack/ai-gemini`);let{geminiText:e}=await import(`@tanstack/ai-gemini`);return{adapter:e(chooseModel(`GEMINI_CHAT_MODEL`,`gemini-2.5-pro`)),maxTokens:G}}async function loadOllama(){W.info(`Found `+s.yellow(`OLLAMA_HOST`)+s.dim(`, loading @tanstack/ai-ollama`)),await ensurePackage(`@tanstack/ai-ollama`);let{ollamaText:e}=await import(`@tanstack/ai-ollama`),t=chooseModel(`OLLAMA_CHAT_MODEL`,`qwen3`);return{adapter:e(t),modelOptions:{model:t,think:`low`},maxTokens:G}}const Te={global_en:`https://api.minimax.io/v1`,cn_zh:`https://api.minimaxi.com/v1`};function chooseMiniMaxBaseURL(){let e=V.MINIMAX_REGION?.trim().toLowerCase();return e===`cn_zh`||e===`cn`||e===`cn-zh`||e===`china`?Te.cn_zh:Te.global_en}async function loadMiniMax(){let e=chooseMiniMaxBaseURL();W.info(`Found `+s.yellow(`MINIMAX_API_KEY`)+s.dim(`, loading OpenAI-compatible adapter on `)+s.green(e)),await ensurePackage(`@tanstack/ai-openai`);let{createOpenaiChat:t}=await import(`@tanstack/ai-openai`),n=V.MINIMAX_API_KEY;return{adapter:t(chooseModel(`MINIMAX_CHAT_MODEL`,`MiniMax-M3`),n,{baseURL:e}),maxTokens:G}}function pickLoader(){if(L(V.OPENAI_API_KEY))return loadOpenAI;if(L(V.OPENROUTER_API_KEY))return loadOpenRouter;if(L(V.ANTHROPIC_API_KEY))return loadAnthropic;if(L(V.GEMINI_API_KEY))return loadGemini;if(L(V.OLLAMA_HOST))return loadOllama;if(L(V.MINIMAX_API_KEY))return loadMiniMax}const Ee=re(async()=>{let e=pickLoader();if(e){await ensurePackage(`@tanstack/ai`);let t=await e();return W.info([`AI configured with`,s.green(t.adapter.name),`adapter`,s.dim(`you can disable it in plugin options`)].join(` `)),t}}),K=U.getChild(`icons`);function iconBundlePlugin(e){let t=we(),n=[t];e.workspace&&n.unshift(e.workspace);let r=ue(t),i,resolveIcon=async(e,t)=>{try{let i=r.resolve(`@likec4/icons/${e}/${t}`,{paths:n});return K.trace(s.dim(`found in package `)+i),await fe(i,`utf-8`)}catch{return}},readFromCache=async(e,t)=>{if(i)try{let n=R(i,e,`${t}.js`);if(Ce(n))return K.trace(s.dim(`read cached `)+`${e}/${t}.js`),await fe(n,`utf-8`)}catch{}},writeToCache=async(e,t,n)=>{if(i)try{let r=R(i,e);Ce(r)||await de(r,{recursive:!0});let a=R(r,`${t}.js`);await pe(a,n),K.trace(s.dim(`written to cache `)+a)}catch(n){K.error(s.dim(`failed to write to cache `)+`${e}/${t}.js`,{error:n})}},fetchFromRemote=async(e,t)=>{let n=p(`https://icons.like-c4.dev`,e,`${t}.js`);K.trace(s.dim(`fetching `)+n);let r=await fetch(n);if(!r.ok)throw Error(`Failed to fetch icon: ${r.status} ${r.statusText}`);return await r.text()},a=new B(async e=>{try{let[t,n]=e.split(`:`);(n.endsWith(`.jsx`)||n.endsWith(`.js`))&&(n=n.slice(0,n.lastIndexOf(`.`))),K.debug(s.dim(`resolving `)+s.green(`${t}:${n}`));let r=await readFromCache(t,n);return r??=await resolveIcon(t,n),r||(r=await fetchFromRemote(t,n),await writeToCache(t,n,r),r)}catch(t){return K.error(s.dim(`failed to resolve icon `)+s.red(e),{error:t}),`
|
|
38
35
|
export default function NotFoundIcon() {
|
|
39
36
|
return null
|
|
40
37
|
}
|
|
41
|
-
`}});return{name:`likec4:icon-bundle`,sharedDuringBuild:!0,applyToEnvironment(t){return!e.environments||e.environments.includes(t.name)},configResolved({root:e,...t}){n.unshift(e),t.cacheDir&&(
|
|
42
|
-
`+
|
|
43
|
-
{response}`,{error:t,response:e});return}}function restoreIdsAndMapToHints(e,t){let{mapping:n}=t,nodeId=e=>{let t=n.nodes[e]?.id;return t||q.warn`Unknown node ID ${e} in LLM output, skipping`,t},mapToNodeId=e=>
|
|
38
|
+
`}});return{name:`likec4:icon-bundle`,sharedDuringBuild:!0,applyToEnvironment(t){return!e.environments||e.environments.includes(t.name)},configResolved({root:e,...t}){n.unshift(e),t.cacheDir&&(i=R(t.cacheDir,`likec4-icons`))},resolveId:{filter:{id:/likec4:icon-bundle/},handler(e){return{id:e,moduleSideEffects:!1}}},load:{filter:{id:/likec4:icon-bundle/},async handler(e){let t=e.split(`/`).slice(-2);if(!S(t,2))return null;let[n,r]=t;return{moduleType:`jsx`,code:await a.get(`${n}:${r}`)}}}}}const q=o(`ai-layout`);function truncate(e,t=100){return e=e.replaceAll(/\n/g,` `).trim(),e.length<=t?e:e.slice(0,t-1)+`…`}function mappedEntries(e){let t={};for(let[n,r]of e.entries())t[r]=n;return t}function edgeLabel(e){let t=e.label&&e.label!==`[...]`?e.label:void 0,n=z(e.description);return n&&(t=t?`${t}\n${n}`:n),t??=e.technology??void 0,t?truncate(t):void 0}function prepareLLMInput(e){let t=1,n=1,r=new B(e=>e.children.length===0?`n${n++}`:`c${t++}`),findNodeById=t=>e.nodes.find(e=>e.id===t),nodeId=e=>r.get(findNodeById(e)),i=new Set;e.nodes.forEach(e=>{r.get(e),e.children.length===0&&i.add(e.id)});let a=e.edges.find(e=>!i.has(e.source)||!i.has(e.target));if(a)throw q.error(`Non-leaf edge found in view`,{view:e.id,edge:{source:a.source,target:a.target}}),Error(`Non-leaf edge found in view, this is not supported by the current implementation`);let o=1,s=new B(e=>`e${o++}`),c=e.edges.map(e=>{let t=nodeId(e.source),n=nodeId(e.target),r=e.parent?nodeId(e.parent):null;e.dir===`back`&&([t,n]=[n,t]);let i=edgeLabel(e);return{id:s.get(e),...i&&{label:i},...r&&{parent:r},source:t,target:n}}),reduceNodes=(e,t)=>{let{level:n,kind:i,...a}=t,o=r.get(t),s=a.children.length>0,c=a.parent?nodeId(a.parent):void 0,l=truncate(a.title);if(s)return e.compounds.push(he({id:o,title:l,parent:c,children:a.children.map(nodeId),level:n})),e;let u=a.description?truncate(z(a.description),200):void 0;return e.nodes.push(he({id:o,kind:i,title:l,description:u,parent:c,level:n})),e};return{serialized:e.nodes.reduce(reduceNodes,{direction:e.autoLayout.direction,compounds:[],nodes:[],edges:c}),mapping:{nodes:mappedEntries(r),edges:mappedEntries(s)}}}const De=_([`TB`,`BT`,`LR`,`RL`]),J=g().nonempty().brand(),Oe=_([`same`,`source`,`sink`,`min`,`max`]),ke=v({rank:Oe,nodes:y(J)}),Y={id:g().nonempty().brand(),weight:b().int().min(0).max(20),minlen:b().int().min(0).max(4)},Ae=v({source:J,target:J,weight:Y.weight.optional(),minlen:Y.minlen.optional()}),je=v({direction:De.optional(),ranks:y(ke).default([]),edgeWeight:h(Y.id,Y.weight).default({}),edgeMinlen:h(Y.id,Y.minlen).default({}),reverseRank:y(Y.id).default([]),excludeFromRanking:y(Y.id).default([]),edgeOrder:y(Y.id).default([]),nodeOrder:y(J).default([]),invisibleEdges:y(Ae).default([]),reasoning:g().default(``)}),Me=/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/;function extractJson(e){let t=Me.exec(e);if(t&&t[1])return t[1];let n=e.indexOf(`{`),r=e.lastIndexOf(`}`);return n!==-1&&r!==-1&&r>n?e.slice(n,r+1):e.trim()}function parseOutput(e,t){try{let n=extractJson(e),r=m.parse(n),i=je.safeParse(r);if(!i.success){q.warn(`Failed to validate LLM response
|
|
39
|
+
`+ee(i.error));return}return restoreIdsAndMapToHints(i.data,t)}catch(t){q.warn(`Failed to parse LLM response
|
|
40
|
+
{response}`,{error:t,response:e});return}}function restoreIdsAndMapToHints(e,t){let{mapping:n}=t,nodeId=e=>{let t=n.nodes[e]?.id;return t||q.warn`Unknown node ID ${e} in LLM output, skipping`,t},mapToNodeId=e=>I(e,A(nodeId),k(C)),edgeId=e=>{let t=n.edges[e]?.id;return t||q.warn`Unknown edge ID ${e} in LLM output, skipping`,t},mapToNonEmpty=(e,t)=>{let n=e.map(t).filter(C);return S(n,1)?n:void 0},r=I(e.excludeFromRanking,A(edgeId),k(C),P(),e=>S(e,1)?e:void 0),i=I(e.reverseRank,A(edgeId),k(C),P(),e=>S(e,1)?e:void 0),a=(()=>{let e=new Set;return t=>t.filter(t=>!e.has(t)&&(e.add(t),!0))})(),o=I(e.ranks,A(e=>{let t=a(mapToNodeId(e.nodes));return S(t,1)?{rank:e.rank,nodes:t}:null}),k(L)),s=I(e.invisibleEdges,A(({source:e,target:t,minlen:n=1,weight:r=1})=>{let i=nodeId(e),a=nodeId(t);if(!(!i||!a))return _e({weight:r===1?void 0:r,minlen:n===1?void 0:n,source:i,target:a})}),k(C),ne(e=>`${e.source}->${e.target}`),ie(([e,...t])=>I(t,j((e,t)=>_e({...e,...t,weight:e.weight&&t.weight?Math.max(e.weight,t.weight):e.weight||t.weight,minlen:e.minlen&&t.minlen?Math.max(e.minlen,t.minlen):e.minlen||t.minlen}),e))),F(),e=>S(e,1)?e:void 0),c=e.reasoning;c&&(c=c.replaceAll(`][`,`] [`),D(t.mapping.nodes).forEach(([e,t])=>{c=c.replaceAll(RegExp(`\\[${e}\\]`,`g`),"`"+t.id+"`")}),D(t.mapping.edges).forEach(([e,t])=>{c=c.replaceAll(RegExp(`\\[${e}\\]`,`g`),"`"+t.source+` -> `+t.target+"`")}));let safeMapEdgeKeys=e=>{let t={};for(let[n,r]of D(e)){let e=edgeId(n);e&&(t[e]=r)}return t};return _e({direction:e.direction,ranks:o,edgeWeight:safeMapEdgeKeys(e.edgeWeight),edgeMinlen:safeMapEdgeKeys(e.edgeMinlen),excludeFromRanking:r,reverseRank:i,edgeOrder:mapToNonEmpty(e.edgeOrder,edgeId),nodeOrder:mapToNonEmpty(e.nodeOrder,nodeId),invisibleEdges:s,reasoning:c})}const Ne={systemPrompt:`You are an advisor specializing in software architecture diagrams and graphviz (DOT) layout optimizations.
|
|
44
41
|
You receive a JSON of Diagram data with:
|
|
45
42
|
- nodes (architectural elements, rendered as leaf boxes)
|
|
46
43
|
- compounds (group of nodes or other compounds, define hierarchy and rendered as boxes around children)
|
|
@@ -226,10 +223,10 @@ OUTPUT:
|
|
|
226
223
|
"reasoning": "I reversed [e4] as it moves [n4] to the top, pushes [n3] to the next row and balances layout, [e5] \`minlen=0\` to keep [n2][n3] on same rank"
|
|
227
224
|
}
|
|
228
225
|
\`\`\`
|
|
229
|
-
</example>`,userPrompt:`Analyze semantics and suggest layout hints for the following diagram. Return only JSON object without any additional text or markdown formatting.`};async function enhanceLayoutWithAI(e,t,n){try{q.debug`generating AI layout hints for ${e.id} using ${t.name}`;let{serialized:r,mapping:i}=prepareLLMInput(e);return parseOutput(await t.sendRequest({...
|
|
226
|
+
</example>`,userPrompt:`Analyze semantics and suggest layout hints for the following diagram. Return only JSON object without any additional text or markdown formatting.`};async function enhanceLayoutWithAI(e,t,n){try{q.debug`generating AI layout hints for ${e.id} using ${t.name}`;let{serialized:r,mapping:i}=prepareLLMInput(e);return parseOutput(await t.sendRequest({...Ne,view:e,mapping:i,diagram:JSON.stringify(r)},n),{mapping:i,view:e})}catch(e){q.warn(`AI layout enhancement failed`,{error:e});return}}async function applySemanticLayout({logger:e,ai:t,likec4:n,server:r},i){ve(t,`AI is not configured`),e.info([s.green(`semantic:layout`),s.dim(`project:`),i.projectId,s.dim(`view:`),i.viewId].join(` `));let a={started:()=>r.hot.send(`likec4:apply-semantic-layout`,{type:`started`}),completed:()=>r.hot.send(`likec4:apply-semantic-layout`,{type:`completed`}),log:e=>r.hot.send(`likec4:apply-semantic-layout`,{log:e})},{chat:o,EventType:c}=await import(`@tanstack/ai`),l=(await n.computedModel(i.projectId)).findView(i.viewId);ve(l,`View ${i.viewId} not found in project ${i.projectId}`),e.info([s.green(`semantic:layout`),s.dim(`call`),t.adapter.name].join(` `));let u=await enhanceLayoutWithAI(l.$view,{name:t.adapter.name,async sendRequest({systemPrompt:e,userPrompt:n,diagram:r}){a.started();let i=o({...t,systemPrompts:[e],stream:!0,messages:[{role:`user`,content:[{type:`text`,content:e},{type:`text`,content:n},{type:`text`,content:r}]}]}),s=``;for await(let e of i)switch(e.type){case c.TEXT_MESSAGE_CONTENT:a.log(e.delta),s+=e.delta;break;case c.REASONING_MESSAGE_CONTENT:a.log(e.delta)}return s}});if(a.completed(),!u){e.warn([s.yellow(`semantic:layout`),`No semantic layout generated`].join(` `));return}e.info([s.green(`semantic:layout`),s.dim(`apply ai hints to layout`)].join(` `));let d=await n.views.layoutView({viewId:i.viewId,projectId:i.projectId,layoutHints:u});if(!d){e.error([s.red(`semantic:layout`),`layout hints failed`].join(` `));return}e.info([s.green(`semantic:layout`),s.dim(`save view snapshot`)].join(` `));let f=await n.editor.applyChange({viewId:i.viewId,projectId:i.projectId,change:{op:`save-view-snapshot`,layout:d.diagram}});if(!f.success){e.error([s.red(`semantic:layout`),`apply change failed`,f.error].join(` `));let t=Error(f.error);throw t.stack=f.error,t}e.info([s.green(`semantic:layout`),s.dim(`project:`),i.projectId,s.dim(`view:`),i.viewId,`✅`].join(` `))}async function calcAdhocView({logger:e,likec4:t},n){e.info([s.green(`adhoc:view`),s.dim(`project:`),n.projectId].join(` `));let r=await t.views.adhocView(n.predicates,n.projectId);return e.info([s.green(`adhoc:view`),`✅`].join(` `)),r}async function updateView({logger:e,likec4:t},n){e.info([s.green(`view:onChange`),s.dim(`project`),n.projectId,s.dim(`view`),n.viewId,s.dim(`change`),n.change.op].join(` `));let r=await t.editor.applyChange(n);if(!r.success){e.error(`Failed to apply view change:\n${r.error}`);let t=Error(r.error);throw t.stack=r.error,t}e.info([s.green(`view:onChange`),`✅`].join(` `))}function splitErrorMessage(e){let t=e.split(`
|
|
230
227
|
`),n=/^\s+at\s+/,r=t.findIndex(e=>n.test(e));return r===-1&&(r=1),{message:t.slice(0,r).join(`
|
|
231
228
|
`),stack:t.slice(r).join(`
|
|
232
|
-
`)}}function sendError(e,{name:t,error:n}){e.hot.send({type:`error`,err:{...splitErrorMessage(n),name:t??`LikeC4PluginError`,plugin:`vite-plugin-likec4`}})}function enablePluginRPC(e){let t=null,n=e.server;
|
|
229
|
+
`)}}function sendError(e,{name:t,error:n}){e.hot.send({type:`error`,err:{...splitErrorMessage(n),name:t??`LikeC4PluginError`,plugin:`vite-plugin-likec4`}})}function enablePluginRPC(e){let t=null,n=e.server;ce({updateView:t=>updateView(e,t),calcAdhocView:t=>calcAdhocView(e,t),applySemanticLayout:t=>applySemanticLayout(e,t)},{on:e=>n.hot.on(`likec4:rpc`,e),post:e=>n.hot.send(`likec4:rpc`,e),onTimeoutError(e){return e===`applySemanticLayout`},onFunctionError:(r,i)=>{e.logger.error(`RPC error in ${i}`,{error:r});let a=r.stack??r.message;try{t!==a&&(t=a,sendError(n,{name:r.name,error:a}))}catch(t){e.logger.error(`Failed to send error to client`,{error:t})}}})}function createAppConfigModule(e){let{webcomponentPrefix:t=`likec4`,pageTitle:n=`LikeC4`,useHashHistory:r=!1,theme:i=`auto`}=e||{};return{id:`likec4:app-config`,virtualId:`likec4:plugin/app-config.js`,async load(){return logGenerating(`app-config`),`
|
|
233
230
|
export let ComponentName = {
|
|
234
231
|
View: ${JSON.stringify(t+`-view`)},
|
|
235
232
|
Browser: ${JSON.stringify(t+`-browser`)},
|
|
@@ -252,11 +249,11 @@ export let defaultTheme = ${JSON.stringify(i)}
|
|
|
252
249
|
export let krokiD2SvgUrl = import.meta.env.VITE_KROKI_D2_SVG_URL || 'https://kroki.io/d2/svg'
|
|
253
250
|
export let krokiPumlSvgUrl = import.meta.env.VITE_KROKI_D2_SVG_URL || 'https://kroki.io/plantuml/svg'
|
|
254
251
|
|
|
255
|
-
`}}}const
|
|
256
|
-
`);n=JSON.parse(t)}catch{}s+=1;continue}if(e.trim()===`// <likec4.strokeColor.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeColor.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),i=t.slice(n+1).trim();e&&i&&(r[e]=i)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.strokeWidth.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeWidth.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();e&&r!==``&&(i[e]=r)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.edge.waypoints>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.edge.waypoints>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)){let t=e.slice(3).trim(),n=t.indexOf(` `);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();if(e&&r)try{let t=JSON.parse(r);Array.isArray(t)&&(a[e]=t)}catch{}}}s+=1}s+=1;continue}s+=1}return o?{layoutByView:n,strokeColorByFqn:r,strokeWidthByFqn:i,edgeWaypoints:a}:null}function compressDrawioDiagramXml(e){let t=encodeURIComponent(e),n=new TextEncoder().encode(t);return uint8ArrayToBase64(
|
|
257
|
-
<mxUserObject>`+Object.entries(e).map(([e,t])=>{let n=typeof t==`string`?t:t==null?``:String(t);return`<data key="${escapeXml(e)}">${escapeXml(n)}</data>`}).join(``)+`</mxUserObject>`}function buildLikec4StyleForEdge(e){let t=[];return pushStylePart(t,`likec4Description`,e.edgeDesc),pushStylePart(t,`likec4Technology`,e.edgeTech),pushStylePart(t,`likec4Notes`,e.edgeNotes),pushStylePart(t,`likec4NavigateTo`,e.edgeNavTo),pushStylePart(t,`likec4RelationshipKind`,e.edgeKind??void 0),pushStylePart(t,`likec4Notation`,e.edgeNotation??void 0),e.edgeLinksJson!==``&&t.push(`likec4Links=${e.edgeLinksJson}`),e.edgeMetadataJson!==``&&t.push(`likec4Metadata=${e.edgeMetadataJson}`),t.length>0?t.join(`;`)+`;`:``}function buildEdgeLabelValue(e){return e.label?escapeXml(e.label):``}function buildEdgeGeometryXml(e,t){let n=t?.[`${e.source}|${e.target}|${e.id}`]??t?.[`${e.source}|${e.target}`],r=Array.isArray(n)?n.flatMap(normalizeEdgePoint):[];return r.length>0?`<mxGeometry relative="1" as="geometry">${`<Array as="points">`+r.map(([e,t])=>`<mxPoint x="${Math.round(e)}" y="${Math.round(t)}"/>`).join(``)+`</Array>`}</mxGeometry>`:`<mxGeometry relative="1" as="geometry" />`}function buildEdgeStyleString(e,t,n,r,i){let{bboxes:a,fontFamily:o}=t,s=a.get(e.source),c=a.get(e.target),l=s&&c?edgeAnchors(s,c):{exitX:1,exitY:.5,entryX:0,entryY:.5},u=`exitX=${l.exitX};exitY=${l.exitY};entryX=${l.entryX};entryY=${l.entryY};`,d=getEdgeStrokeColor(n,e.color),f=e.line===`dashed`?`dashed=1;`:e.line===`dotted`?`dashed=1;dashPattern=1 1;`:``,p=drawioArrow(e.head),m=e.tail==null||e.tail===`none`?`none`:drawioArrow(e.tail),h=buildLikec4StyleForEdge({edgeDesc:toExportString(e.description),edgeTech:toExportString(e.technology),edgeNotes:toExportString(e.notes),edgeNavTo:toNonEmptyString(e.navigateTo),edgeKind:
|
|
258
|
-
${u}${buildMxUserObjectXml(
|
|
259
|
-
</mxCell>`}function computeNodeGeometry(e,t,n){let{bboxes:r,defaultParentId:i,nodeIdsInView:a}=t,o=n(e.id),s=r.get(e.id),{width:c,height:l}=s,u=e.parent!=null&&a.has(e.parent)?n(e.parent):i,d=e.parent==null?void 0:r.get(e.parent);return{id:o,parentId:u,x:d==null?s.x+t.offsetX:s.x-d.x,y:d==null?s.y+t.offsetY:s.y-d.y,width:c,height:l}}function computeNodeStylePartsAndValue(e,t,n,r){let{containerNodeIds:i,effectiveStyles:a,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}=t,l=n?.strokeColorByNodeId,u=n?.strokeWidthByNodeId,d=i.has(e.id),f=e.kind??``,p=e.title,m=toExportString(e.description),h=toExportString(e.technology),g=toExportString(
|
|
252
|
+
`}}}const Pe=e(e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),`capitalizeFirstLetter`),Fe=e(e=>e.split(`.`).map(Pe).join(``),`fqnName`),Ie=e(e=>Fe(e.parent?e.id.slice(e.parent.length+1):e.id),`nodeName`),d2direction=({autoLayout:e})=>{switch(e.direction){case`TB`:return`down`;case`BT`:return`up`;case`LR`:return`right`;case`RL`:return`left`}},d2shape=({shape:e})=>{switch(e){case`queue`:case`cylinder`:case`rectangle`:case`document`:return e;case`person`:return`c4-person`;case`storage`:return`stored_data`;case`component`:case`bucket`:case`mobile`:case`browser`:return`rectangle`}};function generateD2(e){let t=e.$view,{nodes:n,edges:a}=t,o=new Map,printNode=(e,t)=>{let r=Ie(e),a=(t?t+`.`:``)+r;o.set(e.id,a);let s=JSON.stringify(e.title),c=d2shape(e);return new u().append(r,`: {`,i).indent({indentedChildren:t=>t.append(`label: `,s,i).appendIf(c!==`rectangle`,`shape: `,c,i).appendIf(e.children.length>0,i,d(n.filter(t=>t.parent===e.id),e=>printNode(e,a))),indentation:2}).append(`}`,i)},printEdge=e=>new u().append(o.get(e.source),` -> `,o.get(e.target)).append(t=>e.label&&t.append(`: `,JSON.stringify(e.label)));return r(new u().append(`direction: `,d2direction(t),i,i).append(d(n.filter(e=>M(e.parent)),e=>printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(a.length>0,i,d(a,e=>printEdge(e),{appendNewLineIfNotEmpty:!0})))}const Le=`data:page/id,likec4-`,Re=`diagrams.drawio`;function escapeXml(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}function parseDrawioRoundtripComments(e){let t=e.split(/\r?\n/),n={},r={},i={},a={},o=!1,s=0;for(;s<t.length;){let e=t[s];if(e==null){s+=1;continue}if(e.trim()===`// <likec4.layout.drawio>`){o=!0,s+=1;let e=[];for(;s<t.length&&t[s]?.trim()!==`// </likec4.layout.drawio>`;){let n=t[s]?.trim();n?.startsWith(`// `)&&e.push(n.slice(3)),s+=1}if(e.length>0)try{let t=e.join(`
|
|
253
|
+
`);n=JSON.parse(t)}catch{}s+=1;continue}if(e.trim()===`// <likec4.strokeColor.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeColor.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),i=t.slice(n+1).trim();e&&i&&(r[e]=i)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.strokeWidth.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeWidth.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();e&&r!==``&&(i[e]=r)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.edge.waypoints>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.edge.waypoints>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)){let t=e.slice(3).trim(),n=t.indexOf(` `);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();if(e&&r)try{let t=JSON.parse(r);Array.isArray(t)&&(a[e]=t)}catch{}}}s+=1}s+=1;continue}s+=1}return o?{layoutByView:n,strokeColorByFqn:r,strokeWidthByFqn:i,edgeWaypoints:a}:null}function compressDrawioDiagramXml(e){let t=encodeURIComponent(e),n=new TextEncoder().encode(t);return uint8ArrayToBase64(le.deflateRaw(n))}function uint8ArrayToBase64(e){if(typeof Buffer<`u`)return Buffer.from(e).toString(`base64`);let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}const X={getNotes(e){return e.notes},getSummary(e){return e.summary},getTags(e){return e.tags},getNavigateTo(e){return e.navigateTo},getIcon(e){return e.icon},getLinks(e){return e.links},getNotation(e){return e.notation},getCustomData(e){return e.customData},getChildren(e){return e.children}},Z={getKind(e){return e.kind},getNotation(e){return e.notation},getLinks(e){return e.links},getMetadata(e){return e.metadata},getCustomData(e){return e.customData}};function getEffectiveStyles(e){return e.$styles??ge.DEFAULT}function escapeHtml(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`)}function toNonEmptyString(e){if(e==null)return``;let t=typeof e;if(t===`string`){let t=e;return t.trim()===``?``:t}return t===`number`||t===`boolean`?String(e):``}function getContainerDashedStyle(e,t){return e&&t!==`none`||t===`dashed`?`dashed=1;`:``}function getDefaultStrokeWidth(e,t){return e===`none`?`0`:t||e?`1`:``}function applyStrokeColorOverride(e,t){return{fill:e?.fill??`#dae8fc`,stroke:t,font:e?.font??t}}function resolveThemeColor(e,t,n){return t&&t in e.theme.colors?t:n}function getThemeColorValues(e,t,n){let r=getEffectiveStyles(e),i=resolveThemeColor(r,t??n,n);try{return r.colors(i)}catch{return ge.DEFAULT.colors(n)}}function drawioShape(e){let t=`shape=rectangle;rounded=1;arcSize=12;`;switch(e){case`person`:return`shape=actor;`;case`rectangle`:case`browser`:case`mobile`:case`bucket`:return t;case`cylinder`:case`queue`:case`storage`:return`shape=cylinder3;whiteSpace=wrap;boundedLbl=1;backgroundOutline=1;size=15;`;case`document`:return`shape=document;whiteSpace=wrap;html=1;boundedLbl=1;`;case`component`:return`shape=component;`;default:return t}}function getElementColors(e,t){let n=getThemeColorValues(e,t,`primary`).elements;return{fill:String(n.fill??`#dae8fc`),stroke:String(n.stroke??`#2563eb`),font:String(n.hiContrast??n.stroke??`#1e40af`)}}function getEdgeStrokeColor(e,t){let n=getThemeColorValues(e,t??`gray`,`gray`);return String(n.relationships?.line??`#1e40af`)}function getEdgeLabelColors(e,t){let n=getThemeColorValues(e,t??`gray`,`gray`).relationships;return{font:String(n?.label??n?.line??`#1e40af`),background:String(n?.labelBg??`#ffffff`)}}function edgeAnchors(e,t){let n=e.x+e.width/2,r=e.y+e.height/2,i=t.x+t.width/2,a=t.y+t.height/2,o=i-n,s=a-r,c=Math.abs(o)>=Math.abs(s);return{exitX:c?+(o>=0):.5,exitY:c?.5:+(s>=0),entryX:c?o>=0?0:1:.5,entryY:c?.5:s>=0?0:1}}function normalizeEdgePoint(e){if(Array.isArray(e)&&e.length>=2&&typeof e[0]==`number`&&typeof e[1]==`number`)return[[e[0],e[1]]];let t=e;return typeof t.x==`number`&&typeof t.y==`number`?[[t.x,t.y]]:[]}function buildNodeValueHtml(e,t,n,r,i,a){return n?``:t===``?`<div style="box-sizing:border-box;width:100%;min-height:100%;display:flex;align-items:center;justify-content:center;text-align:center;color:${r};font-family:${i};"><b style="font-size:${a}px;">${escapeHtml(e)}</b></div>`:`<div style="box-sizing:border-box;width:100%;min-height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:${r};font-family:${i};"><b style="font-size:${a}px;">${escapeHtml(e)}</b><br/><span style="font-weight:normal;font-size:${a}px;">${escapeHtml(t)}</span></div>`}function pushStylePart(e,t,n){n!=null&&n!==``&&e.push(`${t}=${encodeURIComponent(n)}`)}function pushStylePartNum(e,t,n){n!=null&&e.push(`${t}=${n}`)}function buildNavLinkStyle(e){return e===``?``:`link=${encodeURIComponent(`${Le}${e}`)};`}function toExportString(e){let t=e==null?null:z(e);return t!=null&&!E(t)?t.trim():``}function linksToStyleJson(e){return!Array.isArray(e)||e.length===0?``:encodeURIComponent(JSON.stringify(e.map(e=>({url:e.url,title:e.title}))))}function metadataToStyleJson(e){return typeof e!=`object`||!e||Array.isArray(e)||Object.keys(e).length===0?``:encodeURIComponent(JSON.stringify(e))}const ze=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;function buildLikec4StyleForNode(e){let t=[];return pushStylePart(t,`likec4Description`,e.desc),pushStylePart(t,`likec4Technology`,e.tech),pushStylePart(t,`likec4Notes`,e.notes),pushStylePart(t,`likec4Tags`,e.tagList),pushStylePart(t,`likec4NavigateTo`,e.navTo),pushStylePart(t,`likec4Icon`,e.iconName),pushStylePart(t,`likec4Summary`,e.summaryStr),e.linksJson!==``&&t.push(`likec4Links=${e.linksJson}`),pushStylePart(t,`likec4Border`,e.borderVal),pushStylePartNum(t,`likec4Opacity`,e.containerOpacityNum),pushStylePart(t,`likec4StrokeWidth`,e.strokeWidth),e.colorNameForRoundtrip!==``&&t.push(`likec4ColorName=${e.colorNameForRoundtrip}`),pushStylePart(t,`likec4Size`,e.nodeStyle?.size),pushStylePart(t,`likec4Padding`,e.nodeStyle?.padding),pushStylePart(t,`likec4TextSize`,e.nodeStyle?.textSize),pushStylePart(t,`likec4IconPosition`,e.nodeStyle?.iconPosition),e.strokeHex&&ze.test(e.strokeHex)&&pushStylePart(t,`likec4StrokeColor`,e.strokeHex),pushStylePart(t,`likec4Notation`,e.nodeNotation??void 0),t.length>0?t.join(`;`)+`;`:``}function buildBridgeManagedStyleForNode(e,t,n,r){if(r?.profile!==`leanix`)return``;let i=[`bridgeManaged=true`,`likec4Id=${encodeURIComponent(e)}`,`likec4Kind=${encodeURIComponent(t)}`,`likec4ViewId=${encodeURIComponent(n)}`];r.projectId!=null&&r.projectId!==``&&i.push(`likec4ProjectId=${encodeURIComponent(r.projectId)}`);let a=r.leanixFactSheetTypeByKind?.[t];return a!=null&&a!==``&&i.push(`leanixFactSheetType=${encodeURIComponent(a)}`),i.join(`;`)+`;`}function buildBridgeManagedStyleForEdge(e,t){return t?.profile===`leanix`?`bridgeManaged=true;likec4RelationId=${encodeURIComponent(e)};`:``}function buildMxUserObjectXml(e){return!e||typeof e!=`object`||Array.isArray(e)||Object.keys(e).length===0?``:`
|
|
254
|
+
<mxUserObject>`+Object.entries(e).map(([e,t])=>{let n=typeof t==`string`?t:t==null?``:String(t);return`<data key="${escapeXml(e)}">${escapeXml(n)}</data>`}).join(``)+`</mxUserObject>`}function buildLikec4StyleForEdge(e){let t=[];return pushStylePart(t,`likec4Description`,e.edgeDesc),pushStylePart(t,`likec4Technology`,e.edgeTech),pushStylePart(t,`likec4Notes`,e.edgeNotes),pushStylePart(t,`likec4NavigateTo`,e.edgeNavTo),pushStylePart(t,`likec4RelationshipKind`,e.edgeKind??void 0),pushStylePart(t,`likec4Notation`,e.edgeNotation??void 0),e.edgeLinksJson!==``&&t.push(`likec4Links=${e.edgeLinksJson}`),e.edgeMetadataJson!==``&&t.push(`likec4Metadata=${e.edgeMetadataJson}`),t.length>0?t.join(`;`)+`;`:``}function buildEdgeLabelValue(e){return e.label?escapeXml(e.label):``}function buildEdgeGeometryXml(e,t){let n=t?.[`${e.source}|${e.target}|${e.id}`]??t?.[`${e.source}|${e.target}`],r=Array.isArray(n)?n.flatMap(normalizeEdgePoint):[];return r.length>0?`<mxGeometry relative="1" as="geometry">${`<Array as="points">`+r.map(([e,t])=>`<mxPoint x="${Math.round(e)}" y="${Math.round(t)}"/>`).join(``)+`</Array>`}</mxGeometry>`:`<mxGeometry relative="1" as="geometry" />`}function buildEdgeStyleString(e,t,n,r,i){let{bboxes:a,fontFamily:o}=t,s=a.get(e.source),c=a.get(e.target),l=s&&c?edgeAnchors(s,c):{exitX:1,exitY:.5,entryX:0,entryY:.5},u=`exitX=${l.exitX};exitY=${l.exitY};entryX=${l.entryX};entryY=${l.entryY};`,d=getEdgeStrokeColor(n,e.color),f=e.line===`dashed`?`dashed=1;`:e.line===`dotted`?`dashed=1;dashPattern=1 1;`:``,p=drawioArrow(e.head),m=e.tail==null||e.tail===`none`?`none`:drawioArrow(e.tail),h=buildLikec4StyleForEdge({edgeDesc:toExportString(e.description),edgeTech:toExportString(e.technology),edgeNotes:toExportString(e.notes),edgeNavTo:toNonEmptyString(e.navigateTo),edgeKind:Z.getKind(e),edgeNotation:Z.getNotation(e),edgeLinksJson:linksToStyleJson(Z.getLinks(e)),edgeMetadataJson:metadataToStyleJson(Z.getMetadata(e))}),g=buildBridgeManagedStyleForEdge(e.id,i),_=getEdgeLabelColors(n,e.color);return`endArrow=${p};startArrow=${m};html=1;rounded=0;${u}strokeColor=${d};strokeWidth=2;${f}${r===``?``:`fontColor=${_.font};fontSize=12;align=center;verticalAlign=middle;labelBackgroundColor=none;fontFamily=${encodeURIComponent(o)};`}${h}${g}`}function buildEdgeCellXml(e,t,n,r,i,a){let{defaultParentId:o}=t,s=i(e.source),c=i(e.target),l=buildEdgeLabelValue(e),u=buildEdgeGeometryXml(e,n?.edgeWaypoints);return`<mxCell id="${a}" value="${l}" style="${buildEdgeStyleString(e,t,r,l,n)}" edge="1" parent="${o}" source="${s}" target="${c}">
|
|
255
|
+
${u}${buildMxUserObjectXml(Z.getCustomData(e))}
|
|
256
|
+
</mxCell>`}function computeNodeGeometry(e,t,n){let{bboxes:r,defaultParentId:i,nodeIdsInView:a}=t,o=n(e.id),s=r.get(e.id),{width:c,height:l}=s,u=e.parent!=null&&a.has(e.parent)?n(e.parent):i,d=e.parent==null?void 0:r.get(e.parent);return{id:o,parentId:u,x:d==null?s.x+t.offsetX:s.x-d.x,y:d==null?s.y+t.offsetY:s.y-d.y,width:c,height:l}}function computeNodeStylePartsAndValue(e,t,n,r){let{containerNodeIds:i,effectiveStyles:a,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}=t,l=n?.strokeColorByNodeId,u=n?.strokeWidthByNodeId,d=i.has(e.id),f=e.kind??``,p=e.title,m=toExportString(e.description),h=toExportString(e.technology),g=toExportString(X.getNotes(e)),_=X.getTags(e),v=Array.isArray(_)&&_.length>0?_.join(`,`):``,y=toNonEmptyString(X.getNavigateTo(e)),b=toNonEmptyString(X.getIcon(e)),ee=f===`actor`||e.shape===`person`,x=d?`shape=rectangle;rounded=0;container=1;collapsible=0;startSize=0;`:ee?`shape=actor;`:drawioShape(e.shape),S=l?.[e.id],te=u?.[e.id],C=S?applyStrokeColorOverride(getElementColors(r,e.color),S):getElementColors(r,e.color),ne=C?.fill??`#dae8fc`,w=C?.stroke??`#2563eb`,T=C?.font??C?.stroke??`#1e40af`,E=`fillColor=${ne};strokeColor=${w};fontColor=${T};`,D=e.style,O=a.fontSize(D?.textSize),k=escapeXml(buildNodeValueHtml(p,m,d,T,o,O)),A=D?.border,j=te??getDefaultStrokeWidth(A,d),re=j===``?``:`strokeWidth=${j};`,M=getContainerDashedStyle(d,A),N=d===!0?D?.opacity??15:void 0,P=N!=null&&d===!0?`fillOpacity=${Math.min(100,Math.max(0,N))};`:``,F=buildLikec4StyleForNode({desc:m,tech:h,notes:g,tagList:v,navTo:y,iconName:b,summaryStr:toExportString(X.getSummary(e)),linksJson:linksToStyleJson(X.getLinks(e)),borderVal:A,containerOpacityNum:N,strokeWidth:j,colorNameForRoundtrip:e.color?encodeURIComponent(String(e.color)):``,nodeStyle:D,strokeHex:w,nodeNotation:X.getNotation(e)})+buildBridgeManagedStyleForNode(e.id,f,t.view.id,n),I=buildMxUserObjectXml(X.getCustomData(e)),ie=buildNavLinkStyle(y);return{value:k,styleStr:`${d?`align=left;verticalAlign=top;overflow=fill;whiteSpace=wrap;html=1;`:`align=center;verticalAlign=middle;verticalLabelPosition=middle;labelPosition=center;fontSize=${O};fontStyle=1;spacingTop=4;spacingLeft=2;spacingRight=2;spacingBottom=2;overflow=fill;whiteSpace=wrap;html=1;fontFamily=${encodeURIComponent(o)};`}${x}${E}${re}${M}${P}${ie}${F}`,userObjectXml:I,navTo:y,isContainer:d,title:p,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}}function computeNodeCellExportData(e,t,n,r,i,a){let o=computeNodeGeometry(e,t,i),s=computeNodeStylePartsAndValue(e,t,n,r);return{...o,value:s.value,styleStr:s.styleStr,userObjectXml:s.userObjectXml,navTo:s.navTo,isContainer:s.isContainer,fontFamily:s.fontFamily,...s.isContainer&&{title:s.title??``,titleCellId:String(a),containerTitleFontSizePx:s.containerTitleFontSizePx,containerTitleColor:s.containerTitleColor}}}function buildNodeCellXml(e){let t=`<mxGeometry height="${Math.round(e.height)}" width="${Math.round(e.width)}" x="${Math.round(e.x)}" y="${Math.round(e.y)}" as="geometry" />`,n=e.userObjectXml===``?`\n ${t}`:`${e.userObjectXml}\n ${t}`,r=e.isContainer&&e.title!=null?escapeXml(e.title):e.value,i=e.navTo===``?`<mxCell id="${e.id}" value="${e.value}" style="${e.styleStr}" vertex="1" parent="${e.parentId}">\n ${n}\n</mxCell>`:`<UserObject label="${r}" link="${Le}${escapeXml(e.navTo)}" id="${e.id}">\n <mxCell parent="${e.parentId}" style="${e.styleStr}" value="${e.value}" vertex="1">\n ${n}\n</mxCell>\n</UserObject>`;return e.isContainer?{vertexXml:i,titleCellXml:buildContainerTitleCellXml(e.title??``,e.titleCellId??e.id,e.navTo,e.id,e.fontFamily,e.containerTitleFontSizePx??12,e.containerTitleColor??`#74c0fc`),isContainer:!0}:{vertexXml:i,isContainer:!1}}function buildContainerTitleCellXml(e,t,n,r,i,a,o){let s=escapeXml(e),c=Math.max(60,Math.min(260,e.length*8)),l=buildNavLinkStyle(n),u=`shape=text;html=1;fillColor=none;strokeColor=none;align=left;verticalAlign=top;fontSize=${a};fontStyle=1;fontColor=${o};fontFamily=${encodeURIComponent(i)};${l}`;if(n===``)return`<mxCell id="${t}" value="${s}" style="${u}" vertex="1" parent="${r}">\n <mxGeometry x="8" y="8" width="${c}" height="18" as="geometry" />\n</mxCell>`;let d=`<mxCell parent="${r}" style="${u}" value="${s}" vertex="1">\n <mxGeometry x="8" y="8" width="${c}" height="18" as="geometry" />\n</mxCell>`;return`<UserObject label="${escapeXml(e)}" link="${Le}${escapeXml(n)}" id="${t}">\n ${d}\n</UserObject>`}function getViewTitle(e){return typeof e.title==`string`?e.title:null}function getViewDescriptionString(e){let t=e.description;return typeof t==`object`&&t&&`txt`in t?String(t.txt):typeof t==`object`&&t&&`md`in t?String(t.md):typeof t==`string`?t:``}function getLeanixRootStyleParts(e,t){let n=[`bridgeManaged=true;`,`likec4ViewId=${encodeURIComponent(e.id)};`];return t.projectId!=null&&t.projectId!==``&&n.push(`likec4ProjectId=${encodeURIComponent(t.projectId)};`),n}function buildRootCellStyle(e,t){let n=getViewTitle(e),r=getViewDescriptionString(e),i=r.trim()===``?``:encodeURIComponent(r.trim()),a=e.notation,o=typeof a==`string`&&a!==``?a:void 0,s=o==null?``:encodeURIComponent(o),c=[`rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=none;`,`likec4ViewTitle=${encodeURIComponent(n??e.id)};`,i===``?``:`likec4ViewDescription=${i};`,s===``?``:`likec4ViewNotation=${s};`];return t?.profile===`leanix`&&c.push(...getLeanixRootStyleParts(e,t)),c.join(``)}function drawioArrow(e){switch(e){case`none`:return`none`;case`open`:case`onormal`:case`vee`:return`open`;case`diamond`:case`odiamond`:return`diamond`;case`dot`:case`odot`:return`oval`;case`crow`:return`block`;default:return`block`}}const Q={x:0,y:0,width:120,height:60};function isDefaultBbox(e){return e.x===Q.x&&e.y===Q.y&&e.width===Q.width&&e.height===Q.height}function spreadUnlaidNodesOverVertical(e,t,n){let bboxKey=e=>`${e.x},${e.y},${e.width},${e.height}`,r=t.filter(e=>!n.has(e.id)),i=new Map;for(let t of r){let n=e.get(t.id);if(!n)continue;let r=bboxKey(n),a=i.get(r)??[];a.push(t),i.set(r,a)}for(let t of i.values()){if(t.length<=1)continue;let n=t[0],r=n?e.get(n.id):void 0;r&&isDefaultBbox(r)&&t.forEach((t,n)=>{e.set(t.id,{...r,x:r.x,y:r.y+n*(r.height+24)})})}}function computeContainerBboxesFromChildren(e,t,n,r,i,a){let o=[...n].filter(e=>t.has(e.id)).sort((e,t)=>(t.level??0)-(e.level??0));for(let t of o){let n=(X.getChildren(t)??[]).filter(e=>r.has(e));if(n.length===0||!isDefaultBbox(e.get(t.id)))continue;let o=1/0,s=1/0,c=-1/0,l=-1/0;for(let t of n){let n=e.get(t);n&&(o=Math.min(o,n.x),s=Math.min(s,n.y),c=Math.max(c,n.x+n.width),l=Math.max(l,n.y+n.height))}o!==1/0&&e.set(t.id,{x:o-i,y:s-a,width:c-o+2*i,height:l-s+2*a})}}function computeContentBoundsAndOffsets(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;for(let a of e.values())t=Math.min(t,a.x),n=Math.min(n,a.y),r=Math.max(r,a.x+a.width),i=Math.max(i,a.y+a.height);t===1/0&&(t=0),n===1/0&&(n=0),r===-1/0&&(r=t+800),i===-1/0&&(i=n+600);let a=t+(r-t)/2,o=n+(i-n)/2;return{offsetX:400-a,offsetY:300-o,canvasWidth:800,canvasHeight:600}}function computeDiagramLayout(e,t){let n=e.$view,{nodes:r}=n,i=t?.layoutOverride,a=[...r].sort((e,t)=>M(e.parent)&&M(t.parent)?0:M(e.parent)?-1:M(t.parent)?1:e.parent===t.parent?0:e.id.startsWith(t.id+`.`)?1:t.id.startsWith(e.id+`.`)?-1:0),getBBox=e=>{let t=i?.[e.id];if(t)return t;let n=e;return{x:typeof n.x==`number`?n.x:Array.isArray(n.position)?n.position[0]:0,y:typeof n.y==`number`?n.y:Array.isArray(n.position)?n.position[1]:0,width:typeof n.width==`number`?n.width:n.size?.width??120,height:typeof n.height==`number`?n.height:n.size?.height??60}},o=new Map;for(let e of a)o.set(e.id,getBBox(e));let s=new Set(r.map(e=>e.id)),c=new Set(r.filter(e=>{let t=X.getChildren(e);return Array.isArray(t)&&t.some(e=>s.has(e))}).map(e=>e.id));spreadUnlaidNodesOverVertical(o,a,c);let l=getEffectiveStyles(e),u=l.theme.spacing.xl;computeContainerBboxesFromChildren(o,c,a,s,u,l.theme.spacing.xl+l.theme.spacing.md);let{offsetX:d,offsetY:f,canvasWidth:p,canvasHeight:m}=computeContentBoundsAndOffsets(o);return{view:n,bboxes:o,containerNodeIds:c,sortedNodes:a,offsetX:d,offsetY:f,canvasWidth:p,canvasHeight:m,defaultParentId:`1`,rootId:`0`,effectiveStyles:l,fontFamily:`'IBM Plex Sans Variable',ui-sans-serif,system-ui,sans-serif`,containerTitleFontSizePx:Math.round(l.theme.textSizes.xs),containerTitleColor:`#74c0fc`,nodeIdsInView:s}}function generateDiagramContent(e,t){let n=e.$view,{edges:r}=n,i=t?.compressed!==!1,a=computeDiagramLayout(e,t),{sortedNodes:o,defaultParentId:s,rootId:c,canvasWidth:l,canvasHeight:u}=a,d=new Map,f=2,getCellId=e=>{let t=d.get(e);if(!t){if(f>=1e4)throw Error(`DrawIO cell ID range exhausted`);t=String(f++),d.set(e,t)}return t},p=[],m=[],h=[],g=1e4;for(let n of o){let r=buildNodeCellXml(computeNodeCellExportData(n,a,t,e,getCellId,g));r.isContainer?(p.push(r.vertexXml),r.titleCellXml&&p.push(r.titleCellXml),g++):m.push(r.vertexXml)}for(let n of r){if(f>=1e4)throw Error(`DrawIO cell ID range exhausted`);let r=String(f++);h.push(buildEdgeCellXml(n,a,t,e,getCellId,r))}let _=[`<mxCell id="${s}" value="" style="${buildRootCellStyle(n,t)}" vertex="1" parent="${c}">
|
|
260
257
|
<mxGeometry x="0" y="0" width="${l}" height="${u}" as="geometry" />
|
|
261
258
|
</mxCell>`,...p,...m,...h].join(`
|
|
262
259
|
`),v=(getViewTitle(n)??n.id).trim()||n.id,y=`<mxGraphModel dx="800" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
|
@@ -272,8 +269,8 @@ export let krokiPumlSvgUrl = import.meta.env.VITE_KROKI_D2_SVG_URL || 'https://k
|
|
|
272
269
|
${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}">${e.content}</diagram>`).join(`
|
|
273
270
|
`)}
|
|
274
271
|
</mxfile>
|
|
275
|
-
`}function generateDrawio(e,t){return wrapInMxFile([generateDiagramContent(e,t)],t?.modified)}function generateDrawioMulti(e,t,n){return wrapInMxFile(e.map(e=>generateDiagramContent(e,t?.[e.$view.id])),n)}function buildOptionsFromRoundtrip(e,t,n){let r={compressed:!1,...n};if(!t)return r;let i=t.layoutByView[e]?.nodes;return i!=null&&(r.layoutOverride=i),Object.keys(t.strokeColorByFqn).length>0&&(r.strokeColorByNodeId=t.strokeColorByFqn),Object.keys(t.strokeWidthByFqn).length>0&&(r.strokeWidthByNodeId=t.strokeWidthByFqn),Object.keys(t.edgeWaypoints).length>0&&(r.edgeWaypoints=t.edgeWaypoints),r}function buildDrawioExportOptionsForViews(e,t,n){let r=t?parseDrawioRoundtripComments(t):null;return Object.fromEntries(e.map(e=>[e,buildOptionsFromRoundtrip(e,r,n)]))}function generateDrawioEditUrl(e){let t=compressDrawioDiagramXml(e),n=JSON.stringify({type:`xml`,compressed:!0,data:t});return`https://app.diagrams.net/#create=`+encodeURIComponent(n)}const
|
|
276
|
-
`).map(e=>
|
|
272
|
+
`}function generateDrawio(e,t){return wrapInMxFile([generateDiagramContent(e,t)],t?.modified)}function generateDrawioMulti(e,t,n){return wrapInMxFile(e.map(e=>generateDiagramContent(e,t?.[e.$view.id])),n)}function buildOptionsFromRoundtrip(e,t,n){let r={compressed:!1,...n};if(!t)return r;let i=t.layoutByView[e]?.nodes;return i!=null&&(r.layoutOverride=i),Object.keys(t.strokeColorByFqn).length>0&&(r.strokeColorByNodeId=t.strokeColorByFqn),Object.keys(t.strokeWidthByFqn).length>0&&(r.strokeWidthByNodeId=t.strokeWidthByFqn),Object.keys(t.edgeWaypoints).length>0&&(r.edgeWaypoints=t.edgeWaypoints),r}function buildDrawioExportOptionsForViews(e,t,n){let r=t?parseDrawioRoundtripComments(t):null;return Object.fromEntries(e.map(e=>[e,buildOptionsFromRoundtrip(e,r,n)]))}function generateDrawioEditUrl(e){let t=compressDrawioDiagramXml(e),n=JSON.stringify({type:`xml`,compressed:!0,data:t});return`https://app.diagrams.net/#create=`+encodeURIComponent(n)}const Be=e(e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),`capitalizeFirstLetter`),Ve=e(e=>e.split(`.`).map(Be).join(``),`fqnName`),He=e(e=>Ve(e.parent?e.id.slice(e.parent.length+1):e.id),`nodeName`),toSingleQuotes=e=>e.replace(/\\?"/g,`'`),mmdshape=({shape:e,title:t})=>{let n=`label: ${JSON.stringify(t)}`;switch(e){case`queue`:return`@{ shape: horizontal-cylinder, ${n} }`;case`person`:return`@{ icon: "fa:user", shape: rounded, ${n} }`;case`storage`:return`@{ shape: disk, ${n} }`;case`cylinder`:return`@{ shape: cylinder, ${n} }`;case`mobile`:case`browser`:return`@{ shape: rounded, ${n} }`;case`bucket`:return`@{ shape: trap-t, ${n} }`;case`rectangle`:return`@{ shape: rectangle, ${n} }`;case`document`:return`@{ shape: doc, ${n} }`;case`component`:return`@{ shape: rectangle, ${n} }`;default:ye(e)}};function generateMermaid(e){let t=e.$view,{nodes:n,edges:a}=t,o=new Map,printNode=(e,t)=>{let r=He(e),a=(t?t+`.`:``)+r;o.set(e.id,a);let s=new u;if(e.children.length>0){let t=toSingleQuotes(e.title);s.append(`subgraph `,a,'["`',t,'`"]',i).indent({indentedChildren:[d(n.filter(t=>t.parent===e.id),e=>printNode(e,a),{appendNewLineIfNotEmpty:!0})],indentation:2}).append(`end`,i)}else s.append(a,mmdshape(e));return s},printEdge=e=>new u().append(o.get(e.source),` -.`,e.label?' "`'+toSingleQuotes(e.label)+'`" .-':`-`,`> `,o.get(e.target));return r(new u().append(`---`,i,`title: ${JSON.stringify(toSingleQuotes(e.titleOrId))}`,i,`---`,i).append(`graph `,t.autoLayout.direction,i).indent({indentedChildren:e=>{e.append(d(n.filter(e=>M(e.parent)),e=>printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(a.length>0,d(a,e=>printEdge(e),{appendNewLineIfNotEmpty:!0}))},indentation:2}))}const capitalizeFirstLetter=e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),fqnName=e=>e.split(/[.-]/).map(capitalizeFirstLetter).join(``),nodeName=e=>fqnName(e.parent?e.id.slice(e.parent.length+1):e.id),pumlColor=(e,t,n=`#3b82f6`)=>e?t(e)??n:n,pumlDirection=({autoLayout:e})=>{switch(e.direction){case`TB`:return`top to bottom`;case`BT`:return console.warn(`Bottom to top direction is not supported. Defaulting to top to bottom.`),`top to bottom`;case`LR`:return`left to right`;case`RL`:return console.warn(`Right to left direction is not supported. Defaulting to left to right.`),`left to right`}},pumlShape=({shape:e})=>{switch(e){case`queue`:case`rectangle`:case`person`:return e;case`storage`:case`cylinder`:return`database`;case`component`:return`component`;case`document`:case`mobile`:case`bucket`:case`browser`:return`rectangle`;default:ye(e)}},escapeLabel=e=>E(e)?null:JSON.stringify(e).slice(1,-1).replace(/\\"/g,`"`);function generatePuml(e){let t=e.$view,n=e.$model.$styles.theme.colors,{nodes:a,edges:o}=t,elementColorProvider=e=>t=>t in n?n[t].elements[e]:void 0,relationshipsColorProvider=e=>t=>t in n?n[t].relationships[e]:void 0,s=new Map,printHeader=()=>new u().append(`title "`,e.titleOrId,`"`,i).append(pumlDirection(t),` direction`,i),printTheme=()=>new u().append(`hide stereotype`,i).append(`skinparam ranksep `,`60`,i).append(`skinparam nodesep `,`30`,i).append(`skinparam {`,i).indent({indentedChildren:e=>e.append(`arrowFontSize `,`10`,i).append(`defaultTextAlignment `,`center`,i).append(`wrapWidth `,`200`,i).append(`maxMessageSize `,`100`,i).append(`shadowing `,`false`,i),indentation:2}).append(`}`,i),printStereotypes=e=>{let t=pumlShape(e),n=fqnName(e.id);return new u().append(`skinparam `,t,`<<`,n,`>>`,`{`,i).indent({indentedChildren:t=>t.append(`BackgroundColor `,pumlColor(e.color,elementColorProvider(`fill`)),i).append(`FontColor `,pumlColor(e.color,elementColorProvider(`hiContrast`),`#FFFFFF`),i).append(`BorderColor `,pumlColor(e.color,elementColorProvider(`stroke`)),i),indentation:2}).append(`}`,i)},printNode=e=>{let t=pumlShape(e),n=fqnName(e.id),r=escapeLabel(e.title)||nodeName(e),a=escapeLabel(e.technology);s.set(e.id,n);let o=me.from(e.description);return new u().append(t,` `).append(`"`).append(`==`,r).appendIf(!!a,`\\n<size:10>[`,a,`]</size>`).appendIf(o.nonEmpty,`\\n\\n`,escapeLabel(o.text)).append(`"`,` <<`,n,`>> `,`as `,n,i)},printBoundary=e=>{let t=escapeLabel(e.title)||nodeName(e),n=fqnName(e.id);return s.set(e.id,n),new u().append(`rectangle "`,t,`" <<`,n,`>> as `,n,` {`,i).indent({indentedChildren:t=>t.append(`skinparam `,`RectangleBorderColor<<`,n,`>> `,pumlColor(e.color,elementColorProvider(`fill`)),i).append(`skinparam `,`RectangleFontColor<<`,n,`>> `,pumlColor(e.color,elementColorProvider(`fill`)),i).append(`skinparam `,`RectangleBorderStyle<<`,n,`>> `,`dashed`,i,i).append(d(a.filter(t=>t.parent===e.id),e=>e.children.length>0?printBoundary(e):printNode(e))),indentation:2}).append(`}`,i)},printEdge=e=>{let t=e.technology||``,n=e.label||t,r=pumlColor(e.color,relationshipsColorProvider(`line`),`#777777`),withColor=e=>`<color:${r}>${e.replaceAll(`"`,`'`)}`,a=new u().append(s.get(e.source),` .[`,r,`,thickness=2].> `,s.get(e.target));return(n||t)&&(a.append(` : `,n.split(`
|
|
273
|
+
`).map(e=>E(e)?e:withColor(e)).join(`\\n`)),t&&t!==n&&a.append(`\\n<size:8>[`,withColor(t),`]</size>`)),a.append(i)};return r(new u().append(`@startuml`,i).append(printHeader(),i).append(printTheme(),i).append(d(a.filter(e=>e.children.length==0),e=>printStereotypes(e),{appendNewLineIfNotEmpty:!0})).append(d(a.filter(e=>M(e.parent)),e=>e.children.length>0?printBoundary(e):printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(o.length>0,i,d(o,e=>printEdge(e),{appendNewLineIfNotEmpty:!0})).append(`@enduml`,i))}function code$8(e){let t=new u;return t.appendTemplate`
|
|
277
274
|
/******************************************************************************
|
|
278
275
|
* This file was generated
|
|
279
276
|
* DO NOT EDIT MANUALLY!
|
|
@@ -282,7 +279,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
282
279
|
|
|
283
280
|
export let d2Source = (viewId) => {
|
|
284
281
|
switch (viewId) {
|
|
285
|
-
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(
|
|
282
|
+
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(d([...e.views()],e=>l`
|
|
286
283
|
case ${JSON.stringify(e.id)}: {
|
|
287
284
|
return ${JSON.stringify(generateD2(e))}
|
|
288
285
|
}
|
|
@@ -290,9 +287,9 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
290
287
|
default: {
|
|
291
288
|
throw new Error('Unknown viewId: ' + viewId)
|
|
292
289
|
}
|
|
293
|
-
`}}).append(
|
|
290
|
+
`}}).append(c,` }`,c).appendTemplate`
|
|
294
291
|
}
|
|
295
|
-
`.append(
|
|
292
|
+
`.append(c,c),f(t)}e(code$8,`code`);const Ue={exportFormat:`d2`,...generateMatches(`d2`),async load({likec4:e,project:t}){return logGenerating(`d2`,t.id),{code:code$8(await e.computedModel(t.id)),moduleType:`js`}}},We=generateCombinedProjects(`d2`,`loadD2Sources`,`d2`);function code$7(e){let t=new u;return t.appendTemplate`
|
|
296
293
|
/******************************************************************************
|
|
297
294
|
* This file was generated
|
|
298
295
|
* DO NOT EDIT MANUALLY!
|
|
@@ -301,7 +298,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
301
298
|
|
|
302
299
|
export let dotSource = (viewId) => {
|
|
303
300
|
switch (viewId) {
|
|
304
|
-
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(
|
|
301
|
+
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(d(Object.keys(e),t=>l`
|
|
305
302
|
case ${JSON.stringify(t)}: {
|
|
306
303
|
return ${JSON.stringify(e[t].dot)}
|
|
307
304
|
}
|
|
@@ -309,12 +306,12 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
309
306
|
default: {
|
|
310
307
|
throw new Error('Unknown viewId: ' + viewId)
|
|
311
308
|
}
|
|
312
|
-
`}}).append(
|
|
309
|
+
`}}).append(c,` }`,c).appendTemplate`
|
|
313
310
|
}
|
|
314
311
|
|
|
315
312
|
export let svgSource = (viewId) => {
|
|
316
313
|
switch (viewId) {
|
|
317
|
-
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(
|
|
314
|
+
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(d(Object.keys(e),t=>l`
|
|
318
315
|
case ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(t))}: {
|
|
319
316
|
return ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e[t].svg))}
|
|
320
317
|
}
|
|
@@ -322,7 +319,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
322
319
|
default: {
|
|
323
320
|
throw new Error('Unknown viewId: ' + viewId)
|
|
324
321
|
}
|
|
325
|
-
`}}).append(
|
|
322
|
+
`}}).append(c,` }`,c,`}`,c,c),f(t)}e(code$7,`code`);const Ge={exportFormat:`dot`,...generateMatches(`dot`),async load({likec4:e,project:t}){logGenerating(`dot`,t.id);let n=await e.views.viewsAsGraphvizOut(t.id);return{code:code$7(ae(n,({id:e,svg:t,dot:n})=>[e,{dot:n,svg:t}])),moduleType:`js`}}},Ke=generateCombinedProjects(`dot`,`loadDotSources`,`dot`);function code$6(e){let t=new u;return t.appendTemplate`
|
|
326
323
|
/******************************************************************************
|
|
327
324
|
* This file was generated
|
|
328
325
|
* DO NOT EDIT MANUALLY!
|
|
@@ -331,7 +328,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
331
328
|
|
|
332
329
|
export function drawioEditUrl(viewId) {
|
|
333
330
|
switch (viewId) {
|
|
334
|
-
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(
|
|
331
|
+
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(d([...e.views()],e=>l`
|
|
335
332
|
case ${JSON.stringify(e.id)}: {
|
|
336
333
|
return ${JSON.stringify(generateDrawioEditUrl(generateDrawio(e)))}
|
|
337
334
|
}
|
|
@@ -339,9 +336,9 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
|
|
|
339
336
|
default: {
|
|
340
337
|
throw new Error('Unknown viewId: ' + viewId)
|
|
341
338
|
}
|
|
342
|
-
`}}).append(
|
|
339
|
+
`}}).append(c,` }`,c).appendTemplate`
|
|
343
340
|
}
|
|
344
|
-
`.append(
|
|
341
|
+
`.append(c,c),f(t)}e(code$6,`code`);const qe={exportFormat:`drawio`,...generateMatches(`drawio`),async load({likec4:e,project:t}){return logGenerating(`drawio`,t.id),{code:code$6(await e.layoutedModel(t.id)),moduleType:`js`}}},Je=generateCombinedProjects(`drawio`,`loadDrawioSources`,`drawio`),Ye=/^(https?:)?\/\//i,Xe=new Set([`aws`,`azure`,`gcp`,`tech`,`bootstrap`]);function iconRef(e){if(!(!L(e)||Ye.test(e)||e===`none`||e.startsWith(`data:image`)))return e.startsWith(`file:`)||parseBundledIconRef(e)?e:void 0}function iconRefsFromModelData(e){let iconsFromViews=e=>F(e).flatMap(e=>e.nodes.map(e=>e.icon)),iconsFromStyled=e=>F(e).map(e=>e.style?.icon);return I([...iconsFromViews(e.views),...iconsFromViews(e.manualLayouts??{}),...iconsFromStyled(e.elements),...iconsFromStyled(e.deployments.elements)],A(iconRef),k(L),P(),N(be))}const isLocalSvg=e=>e.startsWith(`file:`)?e.toLowerCase().split(/[?#]/)[0]?.endsWith(`.svg`)??!1:!1,$=e(e=>hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e)),`jsStringLiteral`);function isBundledIconGroup(e){return Xe.has(e)}function parseBundledIconRef(e){let t=e.indexOf(`:`);if(t<=0||t===e.length-1)return null;let n=e.slice(0,t);return isBundledIconGroup(n)?{group:n,icon:e.slice(t+1)}:null}function generateIconRendererCode(e){let{imports:t,cases:n}=iconRefsFromModelData(e).reduce((e,t,n)=>{let r=t.startsWith(`file:`),i=`Icon`+n.toString().padStart(2,`0`),a=$(t);if(r){if(isLocalSvg(t)){let n=`${i}Raw`;e.imports.push(`import ${n} from ${$(`${t}?raw`)}`),e.imports.push(`import ${i} from ${$(`${t}?inline`)}`),e.cases.push(` ${a}: props => jsx(LocalSvgIcon, { ...props, src: ${i}, raw: ${n} })`)}else e.imports.push(`import ${i} from ${$(`${t}?inline`)}`),e.cases.push(` ${a}: props => jsx('img', { ...props, src: ${i} })`);return e}let o=parseBundledIconRef(t);if(!o)return e;let{group:s,icon:c}=o,l=`likec4:icon-bundle/${s}/${c}.jsx`;return e.imports.push(`import ${i} from ${$(l)}`),e.cases.push(` ${a}: ${i}`),e},{imports:[],cases:[]});return`
|
|
345
342
|
import { jsx } from 'react/jsx-runtime'
|
|
346
343
|
${t.join(`
|
|
347
344
|
`)}
|
|
@@ -350,6 +347,36 @@ const Icons = {
|
|
|
350
347
|
${n.join(`,
|
|
351
348
|
`)}
|
|
352
349
|
}
|
|
350
|
+
|
|
351
|
+
function MaskedSvgIcon({ src, style, ...props }) {
|
|
352
|
+
const maskUrl = 'url(' + JSON.stringify(src) + ')'
|
|
353
|
+
return jsx('span', {
|
|
354
|
+
...props,
|
|
355
|
+
style: {
|
|
356
|
+
...style,
|
|
357
|
+
display: 'inline-block',
|
|
358
|
+
width: '100%',
|
|
359
|
+
height: '100%',
|
|
360
|
+
backgroundColor: 'currentColor',
|
|
361
|
+
maskImage: maskUrl,
|
|
362
|
+
maskRepeat: 'no-repeat',
|
|
363
|
+
maskPosition: 'center',
|
|
364
|
+
maskSize: 'contain',
|
|
365
|
+
WebkitMaskImage: maskUrl,
|
|
366
|
+
WebkitMaskRepeat: 'no-repeat',
|
|
367
|
+
WebkitMaskPosition: 'center',
|
|
368
|
+
WebkitMaskSize: 'contain'
|
|
369
|
+
}
|
|
370
|
+
})
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function LocalSvgIcon({ src, raw, ...props }) {
|
|
374
|
+
if (typeof raw === 'string' && /currentcolor/i.test(raw)) {
|
|
375
|
+
return jsx(MaskedSvgIcon, { ...props, src })
|
|
376
|
+
}
|
|
377
|
+
return jsx('img', { ...props, src })
|
|
378
|
+
}
|
|
379
|
+
|
|
353
380
|
export function IconRenderer({ node, ...props }) {
|
|
354
381
|
const IconComponent = Icons[node.icon ?? '']
|
|
355
382
|
if (!IconComponent) {
|
|
@@ -357,13 +384,13 @@ export function IconRenderer({ node, ...props }) {
|
|
|
357
384
|
}
|
|
358
385
|
return jsx(IconComponent, props)
|
|
359
386
|
}
|
|
360
|
-
`}
|
|
387
|
+
`}const Ze={...generateMatches(`icons`,`.jsx`),async load({likec4:e,project:t}){return logGenerating(`icons`,t.id),{moduleType:`jsx`,code:generateIconRendererCode((await e.computedModel(t.id)).$data)}}},Qe=/^[a-zA-Z0-9_.-]+$/;function embedProjectIdAsJsString(e){if(!Qe.test(e))throw Error(`Unsafe value for code generation: ${e}`);return JSON.stringify(e)}function embedUrlAsJsString(e){return JSON.stringify(e)}const $e={id:`likec4:icons`,virtualId:`likec4:plugin/icons.jsx`,async load({projects:e,logger:t}){logGenerating(`icons`);let{imports:n,cases:r}=e.filter(e=>Qe.test(e.id)?!0:(t.warn(s.yellow(`Skipping project with unsafe id for icons registry: ${e.id}`)),!1)).reduce((e,t,n)=>{let r=`Project`+n.toString().padStart(2,`0`),i=hardenJsonStringLiteralForEmbeddedScript(embedProjectIdAsJsString(t.id)),a=hardenJsonStringLiteralForEmbeddedScript(embedUrlAsJsString(p(`likec4:icons`,t.id)));return e.imports.push(`import {IconRenderer as ${r}} from ${a}`),e.cases.push(` ${i}: ${r}`),e},{imports:[],cases:[]});return{code:`
|
|
361
388
|
import { jsx } from 'react/jsx-runtime'
|
|
362
389
|
${n.join(`
|
|
363
390
|
`)}
|
|
364
391
|
|
|
365
392
|
export let ProjectIconsRegistry = {
|
|
366
|
-
${
|
|
393
|
+
${r.join(`,
|
|
367
394
|
`)}
|
|
368
395
|
}
|
|
369
396
|
|
|
@@ -397,7 +424,7 @@ if (import.meta.hot) {
|
|
|
397
424
|
}
|
|
398
425
|
})
|
|
399
426
|
}
|
|
400
|
-
`,moduleType:`jsx`}}};function code$5(e){let t=new
|
|
427
|
+
`,moduleType:`jsx`}}};function code$5(e){let t=new u;return t.appendTemplate`
|
|
401
428
|
/******************************************************************************
|
|
402
429
|
* This file was generated
|
|
403
430
|
* DO NOT EDIT MANUALLY!
|
|
@@ -406,7 +433,7 @@ if (import.meta.hot) {
|
|
|
406
433
|
|
|
407
434
|
export let mmdSource = (viewId) => {
|
|
408
435
|
switch (viewId) {
|
|
409
|
-
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(
|
|
436
|
+
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(d([...e.views()],e=>l`
|
|
410
437
|
case ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e.id))}: {
|
|
411
438
|
return ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(generateMermaid(e)))}
|
|
412
439
|
}
|
|
@@ -414,13 +441,13 @@ if (import.meta.hot) {
|
|
|
414
441
|
default: {
|
|
415
442
|
throw new Error('Unknown viewId: ' + viewId)
|
|
416
443
|
}
|
|
417
|
-
`}}).append(
|
|
444
|
+
`}}).append(c,` }`,c).appendTemplate`
|
|
418
445
|
}
|
|
419
446
|
|
|
420
|
-
`.append(
|
|
447
|
+
`.append(c,c),f(t)}e(code$5,`code`);const et={exportFormat:`mmd`,...generateMatches(`mmd`),async load({likec4:e,project:t}){return logGenerating(`mmd`,t.id),{code:code$5(await e.computedModel(t.id)),moduleType:`js`}}},tt=generateCombinedProjects(`mmd`,`loadMmdSources`,`mmd`),projectModelCode=e=>`
|
|
421
448
|
import { createHooksForModel, atom } from 'likec4/vite-plugin/internal'
|
|
422
449
|
|
|
423
|
-
export let $likec4data = atom(${
|
|
450
|
+
export let $likec4data = atom(${m.stringify(e.$data)})
|
|
424
451
|
|
|
425
452
|
export let {
|
|
426
453
|
updateModel,
|
|
@@ -443,11 +470,11 @@ if (import.meta.hot) {
|
|
|
443
470
|
}
|
|
444
471
|
})
|
|
445
472
|
}
|
|
446
|
-
`,
|
|
473
|
+
`,nt={...generateMatches(`model`),async load({likec4:e,project:t}){logGenerating(`model`,t.id);let n=await e.layoutedModel(t.id);return{code:projectModelCode(n),moduleType:`js`}}},rt=generateCombinedProjects(`model`,`loadModel`),it=e(e=>`
|
|
447
474
|
import { atom, useStore } from 'likec4/vite-plugin/internal'
|
|
448
475
|
|
|
449
476
|
export const isSingleProject = ${e.length===1};
|
|
450
|
-
export const projects = ${
|
|
477
|
+
export const projects = ${m.stringify(e,null,2)};
|
|
451
478
|
|
|
452
479
|
export const $projects = atom([...projects])
|
|
453
480
|
|
|
@@ -473,10 +500,10 @@ if (import.meta.hot) {
|
|
|
473
500
|
}
|
|
474
501
|
})
|
|
475
502
|
}
|
|
476
|
-
`,`code`)
|
|
503
|
+
`,`code`),at={id:`likec4:projects`,virtualId:`likec4:plugin/projects.js`,async load({projects:e}){return logGenerating(`projects`),{code:it(A(e,e=>({id:e.id,title:e.title,landingPage:e.config.landingPage,exportFormats:effectiveWebappExportFormats(e.config)}))),moduleType:`js`}}},ot=e(e=>`
|
|
477
504
|
import { atom, useStore } from 'likec4/vite-plugin/internal'
|
|
478
505
|
|
|
479
|
-
export const $viewdata = atom(${
|
|
506
|
+
export const $viewdata = atom(${m.stringify(e)})
|
|
480
507
|
|
|
481
508
|
export function useLikeC4ProjectsOverview() {
|
|
482
509
|
return useStore($viewdata)
|
|
@@ -499,7 +526,7 @@ if (import.meta.hot) {
|
|
|
499
526
|
export function useLikeC4ProjectsOverview() {
|
|
500
527
|
throw new Error('No projects overview available for this workspace: single project mode is enabled')
|
|
501
528
|
}
|
|
502
|
-
`,
|
|
529
|
+
`,st={id:`likec4:projects-overview`,virtualId:`likec4:plugin/projects-overview.js`,async load({projects:e,likec4:t}){if(e.length<2)return noProjects();logGenerating(`projects-overview`);let n=await t.projectsOverview();return{code:ot(n),moduleType:`js`}}};function code$2(e){let t=new u;return t.appendTemplate`
|
|
503
530
|
/******************************************************************************
|
|
504
531
|
* This file was generated
|
|
505
532
|
* DO NOT EDIT MANUALLY!
|
|
@@ -508,7 +535,7 @@ export function useLikeC4ProjectsOverview() {
|
|
|
508
535
|
|
|
509
536
|
export let pumlSource = (viewId) => {
|
|
510
537
|
switch (viewId) {
|
|
511
|
-
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(
|
|
538
|
+
`.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(d([...e.views()],e=>l`
|
|
512
539
|
case ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e.id))}: {
|
|
513
540
|
return ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(generatePuml(e)))}
|
|
514
541
|
}
|
|
@@ -516,9 +543,9 @@ export function useLikeC4ProjectsOverview() {
|
|
|
516
543
|
default: {
|
|
517
544
|
throw new Error('Unknown viewId: ' + viewId)
|
|
518
545
|
}
|
|
519
|
-
`}}).append(
|
|
546
|
+
`}}).append(c,` }`,c).appendTemplate`
|
|
520
547
|
}
|
|
521
|
-
`.append(
|
|
548
|
+
`.append(c,c),f(t)}e(code$2,`code`);const ct={exportFormat:`puml`,...generateMatches(`puml`),async load({likec4:e,project:t}){return logGenerating(`puml`,t.id),{code:code$2(await e.computedModel(t.id)),moduleType:`js`}}},lt=generateCombinedProjects(`puml`,`loadPumlSources`,`puml`),projectCode=e=>`
|
|
522
549
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
523
550
|
import { LikeC4ModelProvider as Provider, LikeC4View as GenericView, ReactLikeC4 as GenericReactLikeC4 } from 'likec4/react';
|
|
524
551
|
import { IconRenderer } from 'likec4:icons/${e}'
|
|
@@ -541,14 +568,14 @@ export {
|
|
|
541
568
|
useLikeC4View,
|
|
542
569
|
useLikeC4Views
|
|
543
570
|
}
|
|
544
|
-
`,
|
|
571
|
+
`,ut={...generateMatches(`react`),async load({project:e}){return logGenerating(`react`,e.id),{code:projectCode(e.id),moduleType:`js`}}},dt={id:`likec4:react`,virtualId:`likec4:plugin/react.js`,async load({projects:e}){let t=T(e);return logGenerating(`react-default-project`),{code:`export {
|
|
545
572
|
useLikeC4Model,
|
|
546
573
|
useLikeC4View,
|
|
547
574
|
useLikeC4Views,
|
|
548
575
|
LikeC4ModelProvider,
|
|
549
576
|
LikeC4View,
|
|
550
577
|
ReactLikeC4
|
|
551
|
-
} from 'likec4:react/${t.id}'`,moduleType:`js`}}},
|
|
578
|
+
} from 'likec4:react/${t.id}'`,moduleType:`js`}}},ft=e(({isAIAvailable:e,ai:t,rpcEnabled:n})=>`
|
|
552
579
|
import { createRpc } from 'likec4/vite-plugin/internal'
|
|
553
580
|
|
|
554
581
|
export const isRpcAvailable = !!import.meta.hot && ${n}
|
|
@@ -580,7 +607,7 @@ export const likec4rpc = rpc ?? {
|
|
|
580
607
|
throw new Error('likec4rpc.calcAdhocView is not available in production')
|
|
581
608
|
},
|
|
582
609
|
}
|
|
583
|
-
`,`code`),
|
|
610
|
+
`,`code`),pt={id:`likec4:rpc`,virtualId:`likec4:plugin/rpc.js`,async load(e){return logGenerating(`rpc`),{code:ft(e),moduleType:`js`,moduleSideEffects:!1}}},code=e=>`
|
|
584
611
|
export { IconRenderer } from 'likec4:icons/${e}'
|
|
585
612
|
export {
|
|
586
613
|
$likec4data,
|
|
@@ -590,4 +617,88 @@ export {
|
|
|
590
617
|
useLikeC4View
|
|
591
618
|
} from 'likec4:model/${e}'
|
|
592
619
|
export const projectId = ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e))}
|
|
593
|
-
`,
|
|
620
|
+
`,mt={id:`likec4:single-project`,virtualId:`likec4:plugin/single-project.js`,async load({projects:e}){let t=T(e);return logGenerating(`single-project`,t.id),code(t.id)}},jsStringLiteral=e=>hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e)),generateWebcomponentsCode=e=>{let t=jsStringLiteral(e);return`
|
|
621
|
+
import { createElement } from 'react'
|
|
622
|
+
import { createRoot } from 'react-dom/client'
|
|
623
|
+
import { LikeC4View } from ${jsStringLiteral(`likec4:react/${e}`)}
|
|
624
|
+
|
|
625
|
+
const projectId = ${t}
|
|
626
|
+
const projectIdSymbol = Symbol.for('likec4.webcomponent.projectId')
|
|
627
|
+
|
|
628
|
+
function booleanAttribute(element, name, fallback) {
|
|
629
|
+
const value = element.getAttribute(name)
|
|
630
|
+
return value === null ? fallback : value.toLowerCase() !== 'false'
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
function enumAttribute(element, name, values) {
|
|
634
|
+
const value = element.getAttribute(name)
|
|
635
|
+
return value !== null && values.includes(value) ? value : undefined
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
function propsFrom(element) {
|
|
639
|
+
const props = {
|
|
640
|
+
viewId: element.getAttribute('view-id') ?? 'index',
|
|
641
|
+
browser: booleanAttribute(element, 'browser', true),
|
|
642
|
+
}
|
|
643
|
+
const dynamicViewVariant = enumAttribute(element, 'dynamic-variant', ['diagram', 'sequence'])
|
|
644
|
+
const colorScheme = enumAttribute(element, 'color-scheme', ['light', 'dark'])
|
|
645
|
+
if (dynamicViewVariant) {
|
|
646
|
+
props.dynamicViewVariant = dynamicViewVariant
|
|
647
|
+
}
|
|
648
|
+
if (colorScheme) {
|
|
649
|
+
props.colorScheme = colorScheme
|
|
650
|
+
}
|
|
651
|
+
return props
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
function createLikeC4ViewElement() {
|
|
655
|
+
return class LikeC4ViewElement extends HTMLElement {
|
|
656
|
+
static observedAttributes = ['view-id', 'browser', 'dynamic-variant', 'color-scheme']
|
|
657
|
+
|
|
658
|
+
constructor() {
|
|
659
|
+
super()
|
|
660
|
+
this.shadow = this.attachShadow({ mode: 'open', delegatesFocus: true })
|
|
661
|
+
const style = document.createElement('style')
|
|
662
|
+
style.textContent = ':host { display: contents; background-color: transparent; margin: 0; padding: 0; }'
|
|
663
|
+
this.mount = document.createElement('div')
|
|
664
|
+
this.mount.style.display = 'contents'
|
|
665
|
+
this.shadow.append(style, this.mount)
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
connectedCallback() {
|
|
669
|
+
this.root ??= createRoot(this.mount)
|
|
670
|
+
this.render()
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
disconnectedCallback() {
|
|
674
|
+
this.root?.unmount()
|
|
675
|
+
this.root = undefined
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
attributeChangedCallback() {
|
|
679
|
+
if (this.root) {
|
|
680
|
+
this.render()
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
render() {
|
|
685
|
+
this.root.render(createElement(LikeC4View, propsFrom(this)))
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export function defineWebcomponent(name) {
|
|
691
|
+
const existing = customElements.get(name)
|
|
692
|
+
if (existing) {
|
|
693
|
+
if (existing[projectIdSymbol] === projectId) {
|
|
694
|
+
return existing
|
|
695
|
+
}
|
|
696
|
+
throw new Error('Custom element "' + name + '" is already defined')
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const LikeC4ViewElement = createLikeC4ViewElement()
|
|
700
|
+
Object.defineProperty(LikeC4ViewElement, projectIdSymbol, { value: projectId })
|
|
701
|
+
customElements.define(name, LikeC4ViewElement)
|
|
702
|
+
return LikeC4ViewElement
|
|
703
|
+
}
|
|
704
|
+
`},ht={...generateMatches(`webcomponents`),async load({project:e}){return logGenerating(`webcomponents`,e.id),{code:generateWebcomponentsCode(e.id),moduleType:`js`}}},gt=[nt,Ze,Ue,Ge,et,ct,qe],_t=[We,Ke,tt,lt,Je],vt=[...gt,ut,ht],yt=[at,rt,st,mt,dt,..._t,$e,pt];function LikeC4VitePlugin({environments:e,appConfig:n,ai:r=`auto`,...i}){let o,c,l=!1,u,d=i.watch??!1,f=[...yt,createAppConfigModule(n)],initAI=async()=>{if(w(r))throw Error(`Invalid AI configuration: true is not allowed, use an object with adapter configuration or false to disable AI`);if(r!==`disabled`)return r===`auto`?await Ee():r};function moduleopts(e){return{rpcEnabled:l,isAIAvailable:!!u,ai:u,assetsDir:c,likec4:o,logger:U,...e}}let projectsChangeDetector=()=>{let e=A(e=>({id:e.id,title:e.title,folder:e.folder.toString(),landingPage:e.config.landingPage,exportFormats:effectiveWebappExportFormats(e.config)})),t;return n=>{let r=e(n);return t??=r,!te(t,r)&&(t=r,!0)}};return[iconBundlePlugin({environments:e?[e].flat():void 0,workspace:i.workspace??i.languageServices?.workspacePath}),{name:`vite-plugin-likec4`,sharedDuringBuild:!0,applyToEnvironment(t){return!e||e.includes(t.name)},async configResolved(e){let t=l=e.command===`serve`;if(i.languageServices)o=i.languageServices;else{let n=d=t&&(i.watch??!0);o=(await a(i.workspace??e.root,{manualLayouts:!0,graphviz:i.graphviz??`wasm`,configureLogger:`console`,logLevel:i.logLevel??`warning`,printErrors:i.printErrors??!0,throwIfInvalid:i.throwIfInvalid??!1,watch:n})).languageServices}c=o.workspaceUri.fsPath,l&&(u=await initAI())},resolveId:{filter:{id:/^likec4:/},handler(e){for(let t of vt){let n=t.matches(e);if(n)return t.virtualId(n)}for(let t of f)if(t.id===e)return t.virtualId;return null}},load:{filter:{id:/likec4:plugin/},async handler(e){for(let t of vt){let n=t.matches(e);if(n){let e=o.project(n);return await t.load.call(this,moduleopts({project:e}))}}for(let t of f)if(t.virtualId===e){let e=o.projects();return S(e,1)?await t.load.call(this,moduleopts({projects:e})):null}return null}},async configureServer(e){if(l){if(enablePluginRPC.call(this,moduleopts({server:e})),u){U.info(s.dim(`enabling`)+` `+s.magenta(`AI Chat`));let{enableAIServer:t}=await import(`./enableServer.mjs`);t.call(this,moduleopts({server:e}))}return()=>{let n=e.hot,r=projectsChangeDetector(),reloadModule=async n=>{let r=e.moduleGraph.getModuleById(n);if(!r||r.importers.size===0)return!1;try{return await e.reloadModule(r),!0}catch(e){return U.error(t(e)),!1}},hasErrors=()=>{let[e]=o.getErrors();if(!e)return!1;try{n.send({type:`error`,err:{name:`LikeC4ValidationError`,...splitErrorMessage(e.message),plugin:`vite-plugin-likec4`,loc:{file:e.sourceFsPath,line:e.line,column:e.range.start.character+1}}}),U.trace(s.dim(`sent LikeC4ValidationError`))}catch(e){U.error(t(e))}return!0},reloadProjects=async()=>{let e=o.projects();if(r(e)){U.trace(s.dim(`onProjectsUpdate - change detected`)),await reloadModule(at.virtualId),await reloadModule($e.virtualId),await reloadModule(rt.virtualId);for(let e of _t)await reloadModule(e.virtualId);e.length>1&&await reloadModule(st.virtualId)}else U.trace(s.dim(`onProjectsUpdate - no change`))};o.projectsManager.onProjectsUpdate(pDebounce(reloadProjects,100)),o.builder.onModelParsed(onModelParsedBatched(async e=>{if(!hasErrors())for(let t of e){U.trace(s.dim(`onModelParsed project`)+` `+s.cyan(t));for(let e of gt)await reloadModule(e.virtualId(t))}}))}}},async buildEnd(){d&&await o.dispose()}}]}function onModelParsedBatched(e){return O(n=>{e(n).catch(e=>{U.error(t(e))})},{reducer:(e,t)=>(e??=new Set,e.add(t),e),triggerAt:`end`,minQuietPeriodMs:130,maxBurstDurationMs:500}).call}export{generateDrawio as a,generateD2 as c,buildDrawioExportOptionsForViews as i,enhanceLayoutWithAI as l,generatePuml as n,generateDrawioMulti as o,generateMermaid as r,Re as s,LikeC4VitePlugin as t,U as u};
|