2746 lines
87 KiB
JavaScript
2746 lines
87 KiB
JavaScript
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// main.ts
|
|
var main_exports = {};
|
|
__export(main_exports, {
|
|
TRIDENT_ICON_NAME: () => TRIDENT_ICON_NAME,
|
|
default: () => MermaidPlugin
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
var import_obsidian7 = require("obsidian");
|
|
|
|
// src/elements/sampleDiagrams.ts
|
|
var sampleDiagrams = {
|
|
EntityRelationshipDiagram: `erDiagram
|
|
CUSTOMER ||--o{ ORDER : places
|
|
ORDER ||--|{ LINE-ITEM : contains
|
|
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses`,
|
|
ClassDiagram: `class BankAccount
|
|
BankAccount : +String owner
|
|
BankAccount : +Bigdecimal balance
|
|
BankAccount : +deposit(amount)
|
|
BankAccount : +withdrawal(amount)`,
|
|
Flowchart: "flowchart LR\nStart --> Stop",
|
|
GanttChart: `gantt
|
|
title A Gantt Diagram
|
|
dateFormat YYYY-MM-DD
|
|
section Section
|
|
A task :a1, 2014-01-01, 30d
|
|
Another task :after a1 , 20d
|
|
section Another
|
|
Task in sec :2014-01-12 , 12d
|
|
another task : 24d`,
|
|
GitGraph: `gitGraph
|
|
commit
|
|
commit
|
|
branch develop
|
|
checkout develop
|
|
commit
|
|
commit
|
|
checkout main
|
|
merge develop
|
|
commit
|
|
commit`,
|
|
PieChart: `pie title /r/obsidianmd posts by type
|
|
"Look at my awesome graph" : 85
|
|
"Look at my cool dashboard" : 14
|
|
"Moved from Notion, liking it" : 1`,
|
|
RequirementDiagram: ` requirementDiagram
|
|
|
|
requirement test_req {
|
|
id: 1
|
|
text: the test text.
|
|
risk: high
|
|
verifymethod: test
|
|
}
|
|
|
|
element test_entity {
|
|
type: simulation
|
|
}
|
|
|
|
test_entity - satisfies -> test_req`,
|
|
SequenceDiagram: `sequenceDiagram
|
|
Alice->>John: Hello John, how are you?
|
|
John-->>Alice: Great!
|
|
Alice-)John: See you later!`,
|
|
StateDiagram: `stateDiagram-v2
|
|
[*] --> Still
|
|
Still --> [*]
|
|
|
|
Still --> Moving
|
|
Moving --> Still
|
|
Moving --> Crash
|
|
Crash --> [*]`,
|
|
UserJourneyDiagram: `journey
|
|
title My working day
|
|
section Go to work
|
|
Make tea: 5: Me
|
|
Go upstairs: 3: Me
|
|
Do work: 1: Me, Cat
|
|
section Go home
|
|
Go downstairs: 5: Me
|
|
Sit down: 5: Me`,
|
|
Mindmap: `mindmap
|
|
Root
|
|
A
|
|
B
|
|
C`,
|
|
Timeline: `timeline
|
|
title History of Social Media Platform
|
|
2002 : LinkedIn
|
|
2004 : Facebook
|
|
: Google
|
|
2005 : Youtube
|
|
2006 : Twitter`,
|
|
QuadrantChart: `quadrantChart
|
|
title Reach and engagement of campaigns
|
|
x-axis Low Reach --> High Reach
|
|
y-axis Low Engagement --> High Engagement
|
|
quadrant-1 We should expand
|
|
quadrant-2 Need to promote
|
|
quadrant-3 Re-evaluate
|
|
quadrant-4 May be improved
|
|
Campaign A: [0.3, 0.6]
|
|
Campaign B: [0.45, 0.23]
|
|
Campaign C: [0.57, 0.69]
|
|
Campaign D: [0.78, 0.34]
|
|
Campaign E: [0.40, 0.34]
|
|
Campaign F: [0.35, 0.78]`,
|
|
C4Diagram: `C4Context
|
|
title System Context diagram for Internet Banking System
|
|
Enterprise_Boundary(b0, "BankBoundary0") {
|
|
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
|
|
Person(customerB, "Banking Customer B")
|
|
Person_Ext(customerC, "Banking Customer C", "desc")
|
|
|
|
Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")
|
|
|
|
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
|
|
|
|
Enterprise_Boundary(b1, "BankBoundary") {
|
|
|
|
SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
|
|
|
System_Boundary(b2, "BankBoundary2") {
|
|
System(SystemA, "Banking System A")
|
|
System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts. next line.")
|
|
}
|
|
|
|
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
|
|
SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")
|
|
|
|
Boundary(b3, "BankBoundary3", "boundary") {
|
|
SystemQueue(SystemF, "Banking System F Queue", "A system of the bank.")
|
|
SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
|
|
}
|
|
}
|
|
}
|
|
|
|
BiRel(customerA, SystemAA, "Uses")
|
|
BiRel(SystemAA, SystemE, "Uses")
|
|
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
|
|
Rel(SystemC, customerA, "Sends e-mails to")
|
|
|
|
UpdateElementStyle(customerA, $fontColor="red", $bgColor="grey", $borderColor="red")
|
|
UpdateRelStyle(customerA, SystemAA, $textColor="blue", $lineColor="blue", $offsetX="5")
|
|
UpdateRelStyle(SystemAA, SystemE, $textColor="blue", $lineColor="blue", $offsetY="-10")
|
|
UpdateRelStyle(SystemAA, SystemC, $textColor="blue", $lineColor="blue", $offsetY="-40", $offsetX="-50")
|
|
UpdateRelStyle(SystemC, customerA, $textColor="red", $lineColor="red", $offsetX="-50", $offsetY="20")
|
|
|
|
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")`,
|
|
SankeyDiagram: `sankey-beta
|
|
|
|
%% source,target,value
|
|
Electricity grid,Over generation / exports,104.453
|
|
Electricity grid,Heating and cooling - homes,113.726
|
|
Electricity grid,H2 conversion,27.14`,
|
|
XyChart: `xychart-beta
|
|
title "Sales Revenue"
|
|
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
|
y-axis "Revenue (in $)" 4000 --> 11000
|
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]`,
|
|
Packet: `packet-beta
|
|
title UDP Packet
|
|
0-15: "Source Port"
|
|
16-31: "Destination Port"
|
|
32-47: "Length"
|
|
48-63: "Checksum"
|
|
64-95: "Data (variable length)"
|
|
`,
|
|
Kanban: `kanban
|
|
Todo
|
|
[Create Documentation]
|
|
docs[Create Blog about the new diagram]
|
|
[In progress]
|
|
id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.]
|
|
id9[Ready for deploy]
|
|
id8[Design grammar]@{ assigned: 'knsv' }
|
|
id10[Ready for test]
|
|
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
|
|
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
|
|
id11[Done]
|
|
id5[define getData]
|
|
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
|
|
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
|
|
|
|
id12[Can't reproduce]
|
|
id3[Weird flickering in Firefox]`,
|
|
Block: `block-beta
|
|
columns 1
|
|
db(("DB"))
|
|
blockArrowId6<[" "]>(down)
|
|
block:ID
|
|
A
|
|
B["A wide one in the middle"]
|
|
C
|
|
end
|
|
space
|
|
D
|
|
ID --> D
|
|
C --> D
|
|
style B fill:#969,stroke:#333,stroke-width:4px
|
|
`,
|
|
Architecture: `architecture-beta
|
|
group api(cloud)[API]
|
|
|
|
service db(database)[Database] in api
|
|
service disk1(disk)[Storage] in api
|
|
service disk2(disk)[Storage] in api
|
|
service server(server)[Server] in api
|
|
|
|
db:L -- R:server
|
|
disk1:T -- B:server
|
|
disk2:T -- B:db
|
|
`
|
|
};
|
|
|
|
// src/elements/architecture.ts
|
|
var architectureElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "architecture",
|
|
description: "a sample architecture diagram",
|
|
content: `architecture-beta
|
|
group api(cloud)[API]
|
|
|
|
service db(database)[Database] in api
|
|
service disk1(disk)[Storage] in api
|
|
service disk2(disk)[Storage] in api
|
|
service server(server)[Server] in api
|
|
|
|
db:L -- R:server
|
|
disk1:T -- B:server
|
|
disk2:T -- B:db
|
|
`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/blockDiagram.ts
|
|
var blockDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "block",
|
|
description: "a sample block diagram",
|
|
content: `block-beta
|
|
columns 1
|
|
db(("DB"))
|
|
blockArrowId6<[" "]>(down)
|
|
block:ID
|
|
A
|
|
B["A wide one in the middle"]
|
|
C
|
|
end
|
|
space
|
|
D
|
|
ID --> D
|
|
C --> D
|
|
style B fill:#969,stroke:#333,stroke-width:4px
|
|
`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/c4Diagram.ts
|
|
var c4DiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "c4Diagram",
|
|
description: "sample C4 diagram (compatible with PlantUML)",
|
|
content: `C4Context
|
|
title System Context diagram for Internet Banking System
|
|
Enterprise_Boundary(b0, "BankBoundary0") {
|
|
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
|
|
Person(customerB, "Banking Customer B")
|
|
Person_Ext(customerC, "Banking Customer C", "desc")
|
|
|
|
Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")
|
|
|
|
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
|
|
|
|
Enterprise_Boundary(b1, "BankBoundary") {
|
|
|
|
SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
|
|
|
System_Boundary(b2, "BankBoundary2") {
|
|
System(SystemA, "Banking System A")
|
|
System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts. next line.")
|
|
}
|
|
|
|
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
|
|
SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")
|
|
|
|
Boundary(b3, "BankBoundary3", "boundary") {
|
|
SystemQueue(SystemF, "Banking System F Queue", "A system of the bank.")
|
|
SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
|
|
}
|
|
}
|
|
}
|
|
|
|
BiRel(customerA, SystemAA, "Uses")
|
|
BiRel(SystemAA, SystemE, "Uses")
|
|
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
|
|
Rel(SystemC, customerA, "Sends e-mails to")
|
|
|
|
UpdateElementStyle(customerA, $fontColor="red", $bgColor="grey", $borderColor="red")
|
|
UpdateRelStyle(customerA, SystemAA, $textColor="blue", $lineColor="blue", $offsetX="5")
|
|
UpdateRelStyle(SystemAA, SystemE, $textColor="blue", $lineColor="blue", $offsetY="-10")
|
|
UpdateRelStyle(SystemAA, SystemC, $textColor="blue", $lineColor="blue", $offsetY="-40", $offsetX="-50")
|
|
UpdateRelStyle(SystemC, customerA, $textColor="red", $lineColor="red", $offsetX="-50", $offsetY="20")
|
|
|
|
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/classDiagram.ts
|
|
var classDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "sample class",
|
|
content: `class Duck{
|
|
+String beakColor
|
|
+swim()
|
|
+quack()
|
|
}`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "sample class",
|
|
content: `class BankAccount
|
|
BankAccount : +String owner
|
|
BankAccount : +Bigdecimal balance
|
|
BankAccount : +deposit(amount)
|
|
BankAccount : +withdrawal(amount)`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "generic class",
|
|
content: `class Square~Shape~{
|
|
int id
|
|
List~int~ position
|
|
setPoints(List~int~ points)
|
|
getPoints() List~int~
|
|
}
|
|
|
|
Square : -List~string~ messages
|
|
Square : +setMessages(List~string~ messages)
|
|
Square : +getMessages() List~string~`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "inheritance",
|
|
content: "classA <|-- classB",
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "composition",
|
|
content: "classC *-- classD",
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "aggregation",
|
|
content: "classE o-- classF",
|
|
sortingOrder: 5,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "association",
|
|
content: "classG <-- classH",
|
|
sortingOrder: 6,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "solid link",
|
|
content: "classI -- classJ",
|
|
sortingOrder: 7,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "dependency",
|
|
content: "classK <.. classL",
|
|
sortingOrder: 8,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "realization",
|
|
content: "classM <|.. classN",
|
|
sortingOrder: 9,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "dashed link",
|
|
content: "classO .. classP",
|
|
sortingOrder: 10,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "two-way relation",
|
|
content: "Animal <|--|> Zebra",
|
|
sortingOrder: 11,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "classDiagram",
|
|
description: "sample class diagram",
|
|
content: `classDiagram
|
|
Animal <|-- Duck
|
|
Animal <|-- Fish
|
|
Animal <|-- Zebra
|
|
Animal : +int age
|
|
Animal : +String gender
|
|
Animal: +isMammal()
|
|
Animal: +mate()
|
|
class Duck{
|
|
+String beakColor
|
|
+swim()
|
|
+quack()
|
|
}
|
|
class Fish{
|
|
-int sizeInFeet
|
|
-canEat()
|
|
}
|
|
class Zebra{
|
|
+bool is_wild
|
|
+run()
|
|
}`,
|
|
sortingOrder: 12,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/entityRelationshipDiagram.ts
|
|
var entityRelationshipDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "a sample entity relationship diagram",
|
|
content: `erDiagram
|
|
CUSTOMER ||--o{ ORDER : places
|
|
ORDER ||--|{ LINE-ITEM : contains
|
|
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "an entity",
|
|
content: ` CUSTOMER {
|
|
string name
|
|
string custNumber
|
|
string sector
|
|
}`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "one-to-many relationship",
|
|
content: `A ||--|{ B : label`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "many-to-many relationship",
|
|
content: `A }|--|{ B : label`,
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "one-to-one relationship",
|
|
content: `A ||--|| B : label`,
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "many-to-one relationship",
|
|
content: `A }|--|| B : label`,
|
|
sortingOrder: 5,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "zero/one-to-one relationship",
|
|
content: `A |o--|| B : label`,
|
|
sortingOrder: 6,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "one-to-one/zero relationship",
|
|
content: `A ||--o| B : label`,
|
|
sortingOrder: 7,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "zero-or-more-to-one relationship",
|
|
content: `A }o--|| B : label`,
|
|
sortingOrder: 8,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "one-to-zero-or-more relationship",
|
|
content: `A ||--o{ B : label`,
|
|
sortingOrder: 9,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "zero-or-more-to-many relationship",
|
|
content: `A }o--|{ B : label`,
|
|
sortingOrder: 10,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "entityRelationshipDiagram",
|
|
description: "many-to-zero-or-more relationship",
|
|
content: `A }|--o{ B : label`,
|
|
sortingOrder: 11,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/flowchart.ts
|
|
var flowchartElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "a simple flowchart with top to down direction",
|
|
content: `flowchart TD
|
|
Start --> Stop`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "a simple flowchart with left to right direction",
|
|
content: "flowchart LR\nStart --> Stop",
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "A node with round edges",
|
|
content: "id1(Some text)",
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "A stadium-shaped node",
|
|
content: "id1([Some text])",
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "A node in a cylindrical shape",
|
|
content: "id1[(Database)]",
|
|
sortingOrder: 5,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Circle",
|
|
content: "id1((Some text))",
|
|
sortingOrder: 6,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Rhombus",
|
|
content: "id1{Some text}",
|
|
sortingOrder: 7,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Hexagon",
|
|
content: "id1{{Some text}}",
|
|
sortingOrder: 8,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Parallelogram skewed right",
|
|
content: "id1[/Some text/]",
|
|
sortingOrder: 9,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Parallelogram skewed left",
|
|
content: "id1[\\Some text\\]",
|
|
sortingOrder: 10,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Trapezoid",
|
|
content: "A[/Some text\\]",
|
|
sortingOrder: 11,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Trapezoid upside down",
|
|
content: "A[\\Some text/]",
|
|
sortingOrder: 12,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Double circle node",
|
|
content: "id1(((Some text)))",
|
|
sortingOrder: 13,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "A link with arrow head",
|
|
content: "A-->B",
|
|
sortingOrder: 14,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "An open link",
|
|
content: "A --- B",
|
|
sortingOrder: 15,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Text on links",
|
|
content: "A-- This is the text! ---B",
|
|
sortingOrder: 16,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "A link with arrow head and text",
|
|
content: "A-->|text|B",
|
|
sortingOrder: 17,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Dotted link",
|
|
content: "A-.->B",
|
|
sortingOrder: 18,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Thick link",
|
|
content: "A ==> B",
|
|
sortingOrder: 19,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Invisible link",
|
|
content: "A ~~~ B",
|
|
sortingOrder: 20,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Link with circle edge",
|
|
content: "A --o B",
|
|
sortingOrder: 21,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Link with cross edge",
|
|
content: "A --x B",
|
|
sortingOrder: 22,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "flowchart",
|
|
description: "Subgraph",
|
|
content: "subgraph one\na1-->a2\nend",
|
|
sortingOrder: 14,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/ganntChart.ts
|
|
var ganttChartElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "ganttChart",
|
|
description: "simple gantt chart",
|
|
content: `gantt
|
|
title A Gantt Diagram
|
|
dateFormat YYYY-MM-DD
|
|
section Section
|
|
A task :a1, 2014-01-01, 30d
|
|
Another task :after a1 , 20d
|
|
section Another
|
|
Task in sec :2014-01-12 , 12d
|
|
another task : 24d`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "ganttChart",
|
|
description: "rich gantt chart",
|
|
content: `gantt
|
|
dateFormat YYYY-MM-DD
|
|
title Adding GANTT diagram functionality to mermaid
|
|
excludes weekends
|
|
|
|
section A section
|
|
Completed task :done, des1, 2014-01-06,2014-01-08
|
|
Active task :active, des2, 2014-01-09, 3d
|
|
Future task : des3, after des2, 5d
|
|
Future task2 : des4, after des3, 5d
|
|
|
|
section Critical tasks
|
|
Completed task in the critical line :crit, done, 2014-01-06,24h
|
|
Implement parser and jison :crit, done, after des1, 2d
|
|
Create tests for parser :crit, active, 3d
|
|
Future task in critical line :crit, 5d
|
|
Create tests for renderer :2d
|
|
Add to mermaid :1d
|
|
Functionality added :milestone, 2014-01-25, 0d
|
|
|
|
section Documentation
|
|
Describe gantt syntax :active, a1, after des1, 3d
|
|
Add gantt diagram to demo page :after a1 , 20h
|
|
Add another diagram to demo page :doc1, after a1 , 48h
|
|
|
|
section Last section
|
|
Describe gantt syntax :after doc1, 3d
|
|
Add gantt diagram to demo page :20h
|
|
Add another diagram to demo page :48h`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "ganttChart",
|
|
description: "milestones example",
|
|
content: `gantt
|
|
dateFormat HH:mm
|
|
axisFormat %H:%M
|
|
Initial milestone : milestone, m1, 17:49,2min
|
|
taska2 : 10min
|
|
taska3 : 5min
|
|
Final milestone : milestone, m2, 18:14, 2min`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/gitGraph.ts
|
|
var gitGraphElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "gitGraph",
|
|
description: "simple git graph",
|
|
content: `gitGraph
|
|
commit
|
|
commit
|
|
branch develop
|
|
checkout develop
|
|
commit
|
|
commit
|
|
checkout main
|
|
merge develop
|
|
commit
|
|
commit`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "gitGraph",
|
|
description: "tagged commit",
|
|
content: `commit id: "Normal" tag: "v1.0.0"`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "gitGraph",
|
|
description: "reverse commit",
|
|
content: `commit id: "Reverse" type: REVERSE`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "gitGraph",
|
|
description: "highlighted commit",
|
|
content: `commit id: "Highlight" type: HIGHLIGHT`,
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "gitGraph",
|
|
description: "reverse commit",
|
|
content: `commit id: "Reverse" type: REVERSE`,
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "gitGraph",
|
|
description: "git graph with cherry-pick",
|
|
content: `gitGraph
|
|
commit id: "ZERO"
|
|
branch develop
|
|
commit id:"A"
|
|
checkout main
|
|
commit id:"ONE"
|
|
checkout develop
|
|
commit id:"B"
|
|
checkout main
|
|
commit id:"TWO"
|
|
cherry-pick id:"A"
|
|
commit id:"THREE"
|
|
checkout develop
|
|
commit id:"C"`,
|
|
sortingOrder: 5,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/kanban.ts
|
|
var kanbanElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "kanban",
|
|
description: "a sample kanban diagram",
|
|
content: `kanban
|
|
Todo
|
|
[Create Documentation]
|
|
docs[Create Blog about the new diagram]
|
|
[In progress]
|
|
id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.]
|
|
id9[Ready for deploy]
|
|
id8[Design grammar]@{ assigned: 'knsv' }
|
|
id10[Ready for test]
|
|
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
|
|
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
|
|
id11[Done]
|
|
id5[define getData]
|
|
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
|
|
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
|
|
|
|
id12[Can't reproduce]
|
|
id3[Weird flickering in Firefox]`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/mindMap.ts
|
|
var mindMapElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "a simple mindmap",
|
|
content: `mindmap
|
|
Root
|
|
A
|
|
B
|
|
C`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "square",
|
|
content: `id[I am a square]`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "rounded square",
|
|
content: `id(I am a rounded square)`,
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "circle",
|
|
content: `id((I am a circle))`,
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "bang",
|
|
content: `id))I am a bang((`,
|
|
sortingOrder: 5,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "cloud",
|
|
content: `id)I am a cloud(`,
|
|
sortingOrder: 6,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "hexagon",
|
|
content: `id{{I am a hexagon}}`,
|
|
sortingOrder: 7,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "default",
|
|
content: `I am the default shape`,
|
|
sortingOrder: 8,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "mindmap",
|
|
description: "sample mindmap",
|
|
content: `mindmap
|
|
root((mindmap))
|
|
Origins
|
|
Long history
|
|
Popularisation
|
|
British popular psychology author Tony Buzan
|
|
Research
|
|
On effectiveness<br/>and features
|
|
On Automatic creation
|
|
Uses
|
|
Creative techniques
|
|
Strategic planning
|
|
Argument mapping
|
|
Tools
|
|
Pen and paper
|
|
Mermaid`,
|
|
sortingOrder: 9,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/packet.ts
|
|
var packetElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "packet",
|
|
description: "a sample packet diagram",
|
|
content: `packet-beta
|
|
title UDP Packet
|
|
0-15: "Source Port"
|
|
16-31: "Destination Port"
|
|
32-47: "Length"
|
|
48-63: "Checksum"
|
|
64-95: "Data (variable length)"
|
|
`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/pieChart.ts
|
|
var pieChartElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "pieChart",
|
|
description: "sample pie chart",
|
|
content: `pie title /r/obsidianmd posts by type
|
|
"Graphs" : 85
|
|
"Dashboards" : 14
|
|
"Tips" : 1`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "pieChart",
|
|
description: "sample pie chart with values shown in legend",
|
|
content: `pie showData title /r/obsidianmd posts by type
|
|
"Graphs" : 85
|
|
"Dashboards" : 14
|
|
"Tips" : 1`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/quadrant.ts
|
|
var quadrantElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "quadrantChart",
|
|
description: "sample quadrant chart",
|
|
content: `quadrantChart
|
|
title Reach and engagement of campaigns
|
|
x-axis Low Reach --> High Reach
|
|
y-axis Low Engagement --> High Engagement
|
|
quadrant-1 We should expand
|
|
quadrant-2 Need to promote
|
|
quadrant-3 Re-evaluate
|
|
quadrant-4 May be improved
|
|
Campaign A: [0.3, 0.6]
|
|
Campaign B: [0.45, 0.23]
|
|
Campaign C: [0.57, 0.69]
|
|
Campaign D: [0.78, 0.34]
|
|
Campaign E: [0.40, 0.34]
|
|
Campaign F: [0.35, 0.78]`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "quadrantChart",
|
|
description: "themed quadrant chart",
|
|
content: `%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%%
|
|
quadrantChart
|
|
x-axis Urgent --> Not Urgent
|
|
y-axis Not Important --> "Important \u2764"
|
|
quadrant-1 Plan
|
|
quadrant-2 Do
|
|
quadrant-3 Delegate
|
|
quadrant-4 Delete`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/requirementDiagram.ts
|
|
var requirementDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "requirementDiagram",
|
|
description: "sample requirements diagram",
|
|
content: ` requirementDiagram
|
|
|
|
requirement test_req {
|
|
id: 1
|
|
text: the test text.
|
|
risk: high
|
|
verifymethod: test
|
|
}
|
|
|
|
element test_entity {
|
|
type: simulation
|
|
}
|
|
|
|
test_entity - satisfies -> test_req`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "requirementDiagram",
|
|
description: "sample requirements diagram",
|
|
content: `element customElement {
|
|
type: customType
|
|
docref: customDocRef
|
|
}`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "requirementDiagram",
|
|
description: "a requirement with high risk",
|
|
content: `functionalRequirement myReq {
|
|
id: reqId
|
|
text: someText
|
|
risk: High
|
|
verifymethod: analysis
|
|
}`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "requirementDiagram",
|
|
description: "sample requirements diagram",
|
|
content: `interfaceRequirement myReq2 {
|
|
id: reqId
|
|
text: someText
|
|
risk: Medium
|
|
verifymethod: demonstration
|
|
}`,
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "requirementDiagram",
|
|
description: "sample requirements diagram",
|
|
content: `designConstraint myReq3 {
|
|
id: reqId
|
|
text: someText
|
|
risk: Low
|
|
verifymethod: test
|
|
}`,
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/sankeyDiagram.ts
|
|
var sankeyDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "sankeyDiagram",
|
|
description: "",
|
|
content: `sankey-beta
|
|
%% source,target,value
|
|
Electricity grid,Over generation / exports,104.453
|
|
Electricity grid,Heating and cooling - homes,113.726
|
|
Electricity grid,H2 conversion,27.14`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/sequenceDiagram.ts
|
|
var sequenceDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "sequenceDiagram",
|
|
description: "a simple sequence diagram",
|
|
content: `sequenceDiagram
|
|
Alice->>John: Hello John, how are you?
|
|
John-->>Alice: Great!
|
|
Alice-)John: See you later!`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "sequenceDiagram",
|
|
description: "a simple sequence diagram with actors",
|
|
content: `sequenceDiagram
|
|
actor Alice
|
|
actor John
|
|
Alice->>John: Hello John, how are you?
|
|
John-->>Alice: Great!
|
|
Alice-)John: See you later!`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/stateDiagram.ts
|
|
var stateDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "a sample state diagram",
|
|
content: `stateDiagram-v2
|
|
[*] --> Still
|
|
Still --> [*]
|
|
|
|
Still --> Moving
|
|
Moving --> Still
|
|
Moving --> Crash
|
|
Crash --> [*]`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "a sample state diagram with left-to-right direction",
|
|
content: `stateDiagram-v2
|
|
direction LR
|
|
[*] --> Still
|
|
Still --> [*]
|
|
|
|
Still --> Moving
|
|
Moving --> Still
|
|
Moving --> Crash
|
|
Crash --> [*]`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "node with description",
|
|
content: `s2 : This is a state description`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "a transition",
|
|
content: `s1 --> s2`,
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "a transition with label",
|
|
content: `s1 --> s2: A transition`,
|
|
sortingOrder: 4,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "composite state",
|
|
content: `
|
|
[*] --> First
|
|
state First {
|
|
[*] --> second
|
|
second --> [*]
|
|
}`,
|
|
sortingOrder: 5,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "diagram with choice",
|
|
content: `stateDiagram-v2
|
|
state if_state <<choice>>
|
|
[*] --> IsPositive
|
|
IsPositive --> if_state
|
|
if_state --> False: if n < 0
|
|
if_state --> True : if n >= 0`,
|
|
sortingOrder: 6,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "diagram with fork",
|
|
content: `stateDiagram-v2
|
|
state fork_state <<fork>>
|
|
[*] --> fork_state
|
|
fork_state --> State2
|
|
fork_state --> State3
|
|
|
|
state join_state <<join>>
|
|
State2 --> join_state
|
|
State3 --> join_state
|
|
join_state --> State4
|
|
State4 --> [*]`,
|
|
sortingOrder: 7,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "stateDiagram",
|
|
description: "a diagram with concurrency",
|
|
content: `stateDiagram-v2
|
|
[*] --> Active
|
|
|
|
state Active {
|
|
[*] --> NumLockOff
|
|
NumLockOff --> NumLockOn : EvNumLockPressed
|
|
NumLockOn --> NumLockOff : EvNumLockPressed
|
|
--
|
|
[*] --> CapsLockOff
|
|
CapsLockOff --> CapsLockOn : EvCapsLockPressed
|
|
CapsLockOn --> CapsLockOff : EvCapsLockPressed
|
|
--
|
|
[*] --> ScrollLockOff
|
|
ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
|
|
ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
|
|
}`,
|
|
sortingOrder: 8,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/timeline.ts
|
|
var timelineElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "timeline",
|
|
description: "sample timeline",
|
|
content: `timeline
|
|
title History of Social Media Platform
|
|
2002 : LinkedIn
|
|
2004 : Facebook
|
|
: Google
|
|
2005 : Youtube
|
|
2006 : Twitter`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "timeline",
|
|
description: "timeline with grouping",
|
|
content: `timeline
|
|
title Timeline of Industrial Revolution
|
|
section 17th-20th century
|
|
Industry 1.0 : Machinery, Water power, Steam <br>power
|
|
Industry 2.0 : Electricity, Internal combustion engine, Mass production
|
|
Industry 3.0 : Electronics, Computers, Automation
|
|
section 21st century
|
|
Industry 4.0 : Internet, Robotics, Internet of Things
|
|
Industry 5.0 : Artificial intelligence, Big data,3D printing`,
|
|
sortingOrder: 2,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "timeline",
|
|
description: "timeline with Forest theme. see the docs for additional themes",
|
|
content: `%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
|
|
timeline
|
|
title History of Social Media Platform
|
|
2002 : LinkedIn
|
|
2004 : Facebook : Google
|
|
2005 : Youtube
|
|
2006 : Twitter
|
|
2007 : Tumblr
|
|
2008 : Instagram
|
|
2010 : Pinterest`,
|
|
sortingOrder: 3,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/userJourneyDiagram.ts
|
|
var userJourneyDiagramElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "userJourneyDiagram",
|
|
description: "a sample user journey diagram",
|
|
content: `journey
|
|
title My working day
|
|
section Go to work
|
|
Make tea: 5: Me
|
|
Go upstairs: 3: Me
|
|
Do work: 1: Me, Cat
|
|
section Go home
|
|
Go downstairs: 5: Me
|
|
Sit down: 5: Me`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
},
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "userJourneyDiagram",
|
|
description: "a step in user journey",
|
|
content: ` Step Title: 5: ActorName`,
|
|
sortingOrder: 1,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/xyChart.ts
|
|
var xyChartElements = [
|
|
{
|
|
id: crypto.randomUUID(),
|
|
categoryId: "xyChart",
|
|
description: "a sample XYChart diagram",
|
|
content: `xychart-beta
|
|
title "Sales Revenue"
|
|
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
|
y-axis "Revenue (in $)" 4000 --> 11000
|
|
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
|
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]`,
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
}
|
|
];
|
|
|
|
// src/elements/defaultElements.ts
|
|
var defaultElements = [
|
|
...flowchartElements,
|
|
...sequenceDiagramElements,
|
|
...classDiagramElements,
|
|
...stateDiagramElements,
|
|
...entityRelationshipDiagramElements,
|
|
...userJourneyDiagramElements,
|
|
...ganttChartElements,
|
|
...pieChartElements,
|
|
...requirementDiagramElements,
|
|
...gitGraphElements,
|
|
...mindMapElements,
|
|
...timelineElements,
|
|
...quadrantElements,
|
|
...c4DiagramElements,
|
|
...sankeyDiagramElements,
|
|
...xyChartElements,
|
|
...packetElements,
|
|
...kanbanElements,
|
|
...blockDiagramElements,
|
|
...architectureElements
|
|
];
|
|
|
|
// src/core/defaultCategories.ts
|
|
var DEFAULT_CATEGORIES = [
|
|
{
|
|
id: "flowchart",
|
|
name: "Flowchart",
|
|
defaultWrapping: "flowchart LR",
|
|
wrappings: ["flowchart LR", "flowchart TD"],
|
|
isCustom: false,
|
|
sortOrder: 0
|
|
},
|
|
{
|
|
id: "sequenceDiagram",
|
|
name: "SequenceDiagram",
|
|
defaultWrapping: "sequenceDiagram",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 1
|
|
},
|
|
{
|
|
id: "classDiagram",
|
|
name: "ClassDiagram",
|
|
defaultWrapping: "classDiagram",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 2
|
|
},
|
|
{
|
|
id: "stateDiagram",
|
|
name: "StateDiagram",
|
|
defaultWrapping: "stateDiagram-v2",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 3
|
|
},
|
|
{
|
|
id: "entityRelationshipDiagram",
|
|
name: "EntityRelationshipDiagram",
|
|
defaultWrapping: "erDiagram",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 4
|
|
},
|
|
{
|
|
id: "userJourneyDiagram",
|
|
name: "UserJourneyDiagram",
|
|
defaultWrapping: "journey",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 5
|
|
},
|
|
{
|
|
id: "ganttChart",
|
|
name: "GanttChart",
|
|
defaultWrapping: "gantt",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 6
|
|
},
|
|
{
|
|
id: "pieChart",
|
|
name: "PieChart",
|
|
defaultWrapping: "pie",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 7
|
|
},
|
|
{
|
|
id: "requirementDiagram",
|
|
name: "RequirementDiagram",
|
|
defaultWrapping: "requirementDiagram",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 8
|
|
},
|
|
{
|
|
id: "gitGraph",
|
|
name: "GitGraph",
|
|
defaultWrapping: "gitGraph",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 9
|
|
},
|
|
{
|
|
id: "mindmap",
|
|
name: "Mindmap",
|
|
defaultWrapping: "mindmap",
|
|
wrappings: ["mindmap"],
|
|
isCustom: false,
|
|
sortOrder: 10
|
|
},
|
|
{
|
|
id: "timeline",
|
|
name: "Timeline",
|
|
defaultWrapping: "timeline",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 11
|
|
},
|
|
{
|
|
id: "c4Diagram",
|
|
name: "C4Diagram",
|
|
defaultWrapping: "C4Context",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 12
|
|
},
|
|
{
|
|
id: "quadrantChart",
|
|
name: "QuadrantChart",
|
|
defaultWrapping: "quadrantChart",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 13
|
|
},
|
|
{
|
|
id: "sankeyDiagram",
|
|
name: "SankeyDiagram",
|
|
defaultWrapping: "sankey-beta",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 14
|
|
},
|
|
{
|
|
id: "xyChart",
|
|
name: "XyChart",
|
|
defaultWrapping: "xychart-beta",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 15
|
|
},
|
|
{
|
|
id: "kanban",
|
|
name: "Kanban",
|
|
defaultWrapping: "kanban",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 16
|
|
},
|
|
{
|
|
id: "architecture",
|
|
name: "Architecture",
|
|
defaultWrapping: "architecture-beta",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 17
|
|
},
|
|
{
|
|
id: "block",
|
|
name: "Block",
|
|
defaultWrapping: "block-beta",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 18
|
|
},
|
|
{
|
|
id: "packet",
|
|
name: "Packet",
|
|
defaultWrapping: "packet-beta",
|
|
wrappings: null,
|
|
isCustom: false,
|
|
sortOrder: 19
|
|
}
|
|
];
|
|
|
|
// src/core/categoryService.ts
|
|
var CategoryService = class {
|
|
constructor() {
|
|
this.categories = [];
|
|
this.categories = [...DEFAULT_CATEGORIES];
|
|
}
|
|
static getInstance() {
|
|
if (!CategoryService.instance) {
|
|
CategoryService.instance = new CategoryService();
|
|
}
|
|
return CategoryService.instance;
|
|
}
|
|
getCategories() {
|
|
return [...this.categories].sort((a, b) => a.sortOrder - b.sortOrder);
|
|
}
|
|
getCategoryById(id) {
|
|
return this.categories.find((cat) => cat.id === id);
|
|
}
|
|
getCategoryByName(name) {
|
|
return this.categories.find((cat) => cat.name === name);
|
|
}
|
|
addCategory(category) {
|
|
if (this.categories.some((cat) => cat.id === category.id)) {
|
|
throw new Error(`Category with ID '${category.id}' already exists`);
|
|
}
|
|
this.categories.push(category);
|
|
}
|
|
updateCategory(category) {
|
|
const index = this.categories.findIndex((cat) => cat.id === category.id);
|
|
if (index === -1) {
|
|
throw new Error(`Category with ID '${category.id}' not found`);
|
|
}
|
|
this.categories[index] = category;
|
|
}
|
|
deleteCategory(id) {
|
|
var _a;
|
|
if (!((_a = this.getCategoryById(id)) == null ? void 0 : _a.isCustom)) {
|
|
throw new Error("Cannot delete default categories");
|
|
}
|
|
this.categories = this.categories.filter((cat) => cat.id !== id);
|
|
}
|
|
loadCategories(customCategories = [], defaultCategorySortOrders = {}, categoryModifications = {}) {
|
|
const defaultCategories = DEFAULT_CATEGORIES.map((cat) => ({
|
|
...cat,
|
|
...categoryModifications[cat.id],
|
|
id: cat.id,
|
|
isCustom: false,
|
|
sortOrder: defaultCategorySortOrders[cat.id] !== void 0 ? defaultCategorySortOrders[cat.id] : cat.sortOrder
|
|
}));
|
|
const customCats = customCategories.filter((cat) => cat.isCustom);
|
|
this.categories = [...defaultCategories, ...customCats];
|
|
}
|
|
getCustomCategories() {
|
|
return this.categories.filter((cat) => cat.isCustom);
|
|
}
|
|
getWrappingData(categoryId) {
|
|
var _a;
|
|
const category = this.getCategoryById(categoryId);
|
|
if (!category)
|
|
return null;
|
|
return {
|
|
defaultWrapping: category.defaultWrapping,
|
|
wrappings: (_a = category.wrappings) != null ? _a : null
|
|
};
|
|
}
|
|
getNextSortOrder() {
|
|
return Math.max(...this.categories.map((cat) => cat.sortOrder), -1) + 1;
|
|
}
|
|
};
|
|
|
|
// src/core/elementService.ts
|
|
var MermaidElementService = class {
|
|
constructor() {
|
|
this.categoryService = CategoryService.getInstance();
|
|
}
|
|
static DefaultElements() {
|
|
return defaultElements;
|
|
}
|
|
async saveElement(element, plugin) {
|
|
const existingElement = plugin.settings.elements.find((el) => el.id === element.id);
|
|
const elementExists = existingElement !== void 0;
|
|
if (elementExists) {
|
|
if (existingElement.categoryId !== element.categoryId) {
|
|
this.fixSortOrder(element, plugin);
|
|
}
|
|
const index = plugin.settings.elements.findIndex((el) => el.id === element.id);
|
|
if (index !== -1) {
|
|
plugin.settings.elements[index] = element;
|
|
}
|
|
} else {
|
|
this.fixSortOrder(element, plugin);
|
|
plugin.settings.elements.push(element);
|
|
}
|
|
await plugin.saveSettings();
|
|
}
|
|
fixSortOrder(element, plugin) {
|
|
const elementsFromSameCategory = plugin.settings.elements.filter((el) => el.categoryId === element.categoryId);
|
|
if (elementsFromSameCategory.some((el) => el.sortingOrder === element.sortingOrder)) {
|
|
element.sortingOrder = elementsFromSameCategory.length;
|
|
}
|
|
}
|
|
getSampleDiagram(categoryId) {
|
|
const category = this.categoryService.getCategoryById(categoryId);
|
|
if (!category) {
|
|
return this.wrapForPastingIntoEditor(this.wrapWithMermaidBlock("flowchart TD\nStart --> End"));
|
|
}
|
|
const sampleKey = category.name;
|
|
const sample = sampleDiagrams[sampleKey];
|
|
if (sample) {
|
|
return this.wrapForPastingIntoEditor(this.wrapWithMermaidBlock(sample));
|
|
}
|
|
return this.wrapForPastingIntoEditor(this.wrapWithMermaidBlock("flowchart TD\nStart --> End"));
|
|
}
|
|
wrapForPastingIntoEditor(text) {
|
|
return `${text}
|
|
`;
|
|
}
|
|
wrapWithMermaidBlock(text) {
|
|
return `\`\`\`mermaid
|
|
${text}
|
|
\`\`\``;
|
|
}
|
|
wrapAsCompleteDiagram(element) {
|
|
const wrapping = this.categoryService.getWrappingData(element.categoryId);
|
|
if (!wrapping) {
|
|
return element.content;
|
|
}
|
|
const contentAlreadyWrapped = wrapping.wrappings ? wrapping.wrappings.some((w) => element.content.includes(w)) : element.content.includes(wrapping.defaultWrapping);
|
|
if (contentAlreadyWrapped) {
|
|
return element.content;
|
|
}
|
|
const wrappedContent = wrapping.defaultWrapping + "\n" + element.content;
|
|
return wrappedContent;
|
|
}
|
|
};
|
|
|
|
// src/core/textEditorService.ts
|
|
var NoActiveCursorError = class extends Error {
|
|
constructor() {
|
|
super();
|
|
this.message = "Mermaid Tools: Error getting cursor position. Make sure you are in editing mode and have an active cursor in file content.";
|
|
}
|
|
};
|
|
var TextEditorService = class {
|
|
constructor() {
|
|
this._elementService = new MermaidElementService();
|
|
}
|
|
insertTextAtCursor(editor, content) {
|
|
if (!editor)
|
|
throw new NoActiveCursorError();
|
|
content = this._elementService.wrapForPastingIntoEditor(content);
|
|
const cursor = editor.getCursor();
|
|
editor.replaceRange(content, cursor);
|
|
const lines = content.split("\n");
|
|
const newCursor = {
|
|
line: cursor.line + lines.length - 1,
|
|
ch: lines.length === 1 ? cursor.ch + lines[0].length : lines[lines.length - 1].length
|
|
};
|
|
editor.setCursor(newCursor);
|
|
editor.focus();
|
|
}
|
|
};
|
|
|
|
// src/settings/settings.ts
|
|
var MermaidPluginSettings = class {
|
|
static DefaultSettings() {
|
|
const settings = new MermaidPluginSettings();
|
|
settings.elements = defaultElements;
|
|
settings.customCategories = [];
|
|
settings.selectedCategoryId = "flowchart";
|
|
settings.defaultCategorySortOrders = {};
|
|
settings.categoryModifications = {};
|
|
settings.defaultElementCategoryIds = Array.from(new Set(defaultElements.map((element) => element.categoryId)));
|
|
return settings;
|
|
}
|
|
};
|
|
|
|
// src/trident-icon.ts
|
|
var import_obsidian = require("obsidian");
|
|
function addTridentIcon() {
|
|
(0, import_obsidian.addIcon)(TRIDENT_ICON_NAME, TRIDENT_ICON);
|
|
}
|
|
var TRIDENT_ICON = `<svg width="100" height="100" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M63.3876 30.1639C62.8776 29.6541 62.1414 29.4434 61.439 29.6051L46.6574 32.5601C45.9179
|
|
32.7318 45.3279 33.2907 45.1192 34.0208C44.9089 34.7506 45.113 35.5373 45.6499 36.0742L47.1282
|
|
37.552L36.7814 47.895C35.965 48.7111 34.6415 48.7111 33.8252 47.895L29.3908 43.4622L50.0846 22.7759L51.5629
|
|
24.2537C52.0998 24.7904 52.8871 24.9944 53.6169 24.7842C54.3473 24.5753 54.9064 23.9858 55.0782
|
|
23.2466L58.0341 8.4704C58.1958 7.76815 57.9851 7.03228 57.4751 6.52252C56.965 6.01265 56.229 5.80202
|
|
55.5265 5.96365L40.7453 8.91853C40.0057 9.09028 39.4158 9.64916 39.2071 10.3793C38.9967 11.109 39.2008
|
|
11.8958 39.7378 12.4327L41.2161 13.9104L20.5223 34.5966L16.0879 30.1638C15.2716 29.3477 15.2716 28.0247
|
|
16.0879 27.2087L26.4347 16.8657L27.913 18.3434C28.45 18.8802 29.2373 19.0842 29.967 18.8739C30.6974 18.6653
|
|
31.2565 18.0755 31.4283 17.3363L34.3843 2.56014C34.546 1.85789 34.3353 1.12202 33.8252 0.612265C33.3151 0.102514
|
|
32.579 -0.108237 31.8765 0.0533888L17.0953 3.00839C16.3557 3.18014 15.7658 3.73902 15.5571 4.46915C15.3467 5.1989
|
|
15.5508 5.98565 16.0878 6.5224L17.5661 8.00015L7.21925 18.3432C1.50488 24.0554 1.50488 33.3169 7.21925 39.0295L11.6536
|
|
43.4622L0.610679 54.524C-0.204122 55.3402 -0.203497 56.6621 0.612179 57.4776L6.52461 63.388C7.34154 64.2046 8.66628
|
|
64.2039 9.48233 63.3865L20.522 52.3277L24.9564 56.7605C30.6708 62.4727 39.9358 62.4727 45.6501 56.7605L55.9969 46.4175L57.4752
|
|
47.8952C58.0121 48.432 58.7994 48.636 59.5292 48.4257C60.2596 48.2171 60.8187 47.6273 60.9905 46.8881L63.9464 32.1119C64.1084
|
|
31.4097 63.8977 30.6738 63.3876 30.1639ZM57.6701 42.1787L55.9975 40.5068L42.6944 53.8051C38.6127 57.8855 31.9948 57.8852 27.9131
|
|
53.8051L20.5223 46.4173L17.5661 49.3725L8.00441 58.9569L5.04819 56.0017L14.6098 46.4173L17.5661 43.4622L10.1755 36.0743C6.09383
|
|
31.9942 6.09383 25.3787 10.1755 21.2986L23.4786 8.00028L21.8053 6.3274L29.6834 4.75302L28.1077 12.6273L26.4352 10.9554L13.1321
|
|
24.2537C10.6829 26.7019 10.6829 30.6711 13.1321 33.1192L20.5227 40.5071L47.1287 13.9108L45.4554 12.2378L53.3335 10.6635L51.7578
|
|
18.5378L50.0853 16.8659L23.4786 43.462L30.8692 50.8499C33.3184 53.2979 37.289 53.2979 39.738 50.8499L53.0412 37.5516L51.3678
|
|
35.8786L59.246 34.3042L57.6701 42.1787Z" fill="currentColor"/>
|
|
</svg>`;
|
|
|
|
// src/ui/settingsTab.ts
|
|
var import_obsidian4 = require("obsidian");
|
|
|
|
// src/ui/editMermaidElementModal.ts
|
|
var import_obsidian2 = require("obsidian");
|
|
|
|
// src/ui/renderMermaidSvg.ts
|
|
var DISALLOWED_SVG_TAGS = /* @__PURE__ */ new Set([
|
|
"base",
|
|
"embed",
|
|
"iframe",
|
|
"link",
|
|
"meta",
|
|
"object",
|
|
"script"
|
|
]);
|
|
var URL_ATTRIBUTE_NAMES = /* @__PURE__ */ new Set([
|
|
"href",
|
|
"src",
|
|
"xlink:href"
|
|
]);
|
|
function setMermaidSvgContent(containerEl, svg) {
|
|
containerEl.empty();
|
|
containerEl.appendChild(parseSanitizedSvg(svg));
|
|
}
|
|
function parseSanitizedSvg(svg) {
|
|
const parsedSvg = new DOMParser().parseFromString(svg, "image/svg+xml");
|
|
const parserError = parsedSvg.querySelector("parsererror");
|
|
const svgEl = parsedSvg.documentElement;
|
|
if (parserError || svgEl.nodeName.toLowerCase() !== "svg") {
|
|
throw new Error("Unable to parse Mermaid SVG output.");
|
|
}
|
|
sanitizeSvgTree(svgEl);
|
|
return document.importNode(svgEl, true);
|
|
}
|
|
function sanitizeSvgTree(rootEl) {
|
|
var _a;
|
|
const elements = [rootEl, ...Array.from(rootEl.querySelectorAll("*"))];
|
|
for (const el of elements) {
|
|
if (DISALLOWED_SVG_TAGS.has(el.tagName.toLowerCase())) {
|
|
el.remove();
|
|
continue;
|
|
}
|
|
sanitizeSvgAttributes(el);
|
|
if (el.tagName.toLowerCase() === "style") {
|
|
el.textContent = sanitizeCss((_a = el.textContent) != null ? _a : "");
|
|
}
|
|
}
|
|
}
|
|
function sanitizeSvgAttributes(el) {
|
|
for (const attr of Array.from(el.attributes)) {
|
|
const attrName = attr.name.toLowerCase();
|
|
if (attrName.startsWith("on")) {
|
|
el.removeAttribute(attr.name);
|
|
continue;
|
|
}
|
|
if (attrName === "style") {
|
|
el.setAttribute(attr.name, sanitizeCss(attr.value));
|
|
continue;
|
|
}
|
|
if (URL_ATTRIBUTE_NAMES.has(attrName) && !isSafeSvgUrl(attr.value)) {
|
|
el.removeAttribute(attr.name);
|
|
}
|
|
}
|
|
}
|
|
function isSafeSvgUrl(value) {
|
|
const trimmedValue = value.trim();
|
|
return trimmedValue === "" || trimmedValue.startsWith("#");
|
|
}
|
|
function sanitizeCss(css) {
|
|
return css.replace(/@import[^;]*;?/gi, "").replace(/url\s*\(\s*(['"]?)(.*?)\1\s*\)/gi, (_match, _quote, url) => {
|
|
const trimmedUrl = url.trim();
|
|
return trimmedUrl.startsWith("#") ? `url(${trimmedUrl})` : "none";
|
|
}).replace(/expression\s*\([^)]*\)/gi, "");
|
|
}
|
|
|
|
// src/ui/editMermaidElementModal.ts
|
|
var EditMermaidElementModal = class extends import_obsidian2.Modal {
|
|
constructor(app, _plugin, _mermaid, element, _categoryService) {
|
|
super(app);
|
|
this._plugin = _plugin;
|
|
this._mermaid = _mermaid;
|
|
this._categoryService = _categoryService;
|
|
this._element = { ...element };
|
|
}
|
|
async onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.addClass("mermaid-tools-edit-element-modal");
|
|
contentEl.createEl("h2", { text: "Edit element" });
|
|
const renderContainerEl = contentEl.createDiv();
|
|
const renderEl = renderContainerEl.createDiv({ text: "rendered diagram" });
|
|
renderEl.addClass("mermaid-tools-element-preview");
|
|
if (!this._mermaid) {
|
|
this._mermaid = await (0, import_obsidian2.loadMermaid)();
|
|
}
|
|
const mermaid = this._mermaid;
|
|
if (!mermaid) {
|
|
throw new Error("Unable to load Mermaid renderer.");
|
|
}
|
|
const elementCategoryContainerEl = contentEl.createDiv();
|
|
elementCategoryContainerEl.createEl("label", { text: "Category" });
|
|
const elementCategoryEl = elementCategoryContainerEl.createEl("select");
|
|
const categories = this._categoryService.getCategories();
|
|
for (const category of categories) {
|
|
const option = elementCategoryEl.createEl("option", { text: category.name });
|
|
option.value = category.id;
|
|
}
|
|
elementCategoryEl.value = this._element.categoryId;
|
|
elementCategoryEl.onchange = async () => {
|
|
this._element.categoryId = elementCategoryEl.value;
|
|
await this.renderPreview(mermaid, renderEl);
|
|
};
|
|
const elementDescriptionContainerEl = contentEl.createDiv();
|
|
elementDescriptionContainerEl.createEl("label", { text: "Description" });
|
|
const elementDescriptionEl = elementDescriptionContainerEl.createEl("input", { value: this._element.description, type: "text" });
|
|
elementDescriptionEl.addClass("mermaid-tools-element-description-input");
|
|
elementDescriptionEl.onchange = () => {
|
|
this._element.description = elementDescriptionEl.value;
|
|
};
|
|
const elementContentContainerEl = contentEl.createDiv();
|
|
elementContentContainerEl.createEl("label", { text: "Content" });
|
|
const elementContentEl = elementContentContainerEl.createEl("textarea", { text: this._element.content });
|
|
elementContentEl.addClass("mermaid-tools-element-content-input");
|
|
elementContentEl.onchange = async () => {
|
|
this._element.content = elementContentEl.value;
|
|
await this.renderPreview(mermaid, renderEl);
|
|
};
|
|
const saveButtonEl = contentEl.createEl("button", { text: "Save" });
|
|
saveButtonEl.onclick = () => {
|
|
void this.save();
|
|
};
|
|
await this.renderPreview(mermaid, renderEl);
|
|
}
|
|
async save() {
|
|
await this._plugin._mermaidElementService.saveElement(this._element, this._plugin);
|
|
this.close();
|
|
}
|
|
async renderPreview(mermaid, renderEl) {
|
|
try {
|
|
const { svg } = await mermaid.render(createMermaidPreviewId(), this._plugin._mermaidElementService.wrapAsCompleteDiagram(this._element));
|
|
renderEl.removeClass("mermaid-tools-render-error");
|
|
setMermaidSvgContent(renderEl, svg);
|
|
} catch (error) {
|
|
renderEl.empty();
|
|
renderEl.addClass("mermaid-tools-render-error");
|
|
renderEl.createDiv({ text: "Unable to render preview" });
|
|
const errorEl = renderEl.createDiv({ text: getErrorMessage(error) });
|
|
errorEl.addClass("mermaid-tools-render-error-message");
|
|
}
|
|
}
|
|
};
|
|
function getErrorMessage(error) {
|
|
return error instanceof Error ? error.message : String(error);
|
|
}
|
|
function createMermaidPreviewId() {
|
|
return `mermaid-tools-edit-preview-${crypto.randomUUID()}`;
|
|
}
|
|
|
|
// src/ui/editCategoryModal.ts
|
|
var import_obsidian3 = require("obsidian");
|
|
var EditCategoryModal = class extends import_obsidian3.Modal {
|
|
constructor(app, existingCategory, onSave) {
|
|
super(app);
|
|
this.categoryService = CategoryService.getInstance();
|
|
this.onSave = onSave;
|
|
this.isNewCategory = !existingCategory;
|
|
if (existingCategory) {
|
|
this.category = { ...existingCategory };
|
|
} else {
|
|
this.category = {
|
|
id: "",
|
|
name: "",
|
|
defaultWrapping: "",
|
|
wrappings: null,
|
|
isCustom: true,
|
|
sortOrder: this.categoryService.getNextSortOrder()
|
|
};
|
|
}
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.addClass("mermaid-tools-edit-category-modal");
|
|
contentEl.createEl("h2", {
|
|
text: this.isNewCategory ? "Create Custom Category" : "Edit Category"
|
|
});
|
|
new import_obsidian3.Setting(contentEl).setName("Category ID").setDesc(this.isNewCategory ? "Unique identifier for this category (lowercase, no spaces)" : "Category IDs cannot be changed after creation").addText((text) => {
|
|
text.setPlaceholder("my-custom-category").setValue(this.category.id).setDisabled(!this.isNewCategory).onChange((value) => {
|
|
this.category.id = value.toLowerCase().replace(/\s+/g, "-");
|
|
});
|
|
});
|
|
new import_obsidian3.Setting(contentEl).setName("Category Name").setDesc("Display name for this category").addText((text) => text.setPlaceholder("My Custom Category").setValue(this.category.name).onChange((value) => {
|
|
this.category.name = value;
|
|
}));
|
|
new import_obsidian3.Setting(contentEl).setName("Default Wrapping").setDesc('Default mermaid syntax to wrap elements (e.g., "flowchart TD", "sequenceDiagram")').addText((text) => text.setPlaceholder("flowchart TD").setValue(this.category.defaultWrapping).onChange((value) => {
|
|
this.category.defaultWrapping = value;
|
|
}));
|
|
new import_obsidian3.Setting(contentEl).setName("Additional Wrappings (Optional)").setDesc('Comma-separated list of alternative wrappings (e.g., "flowchart LR, flowchart TB")').addText((text) => text.setPlaceholder("flowchart LR, flowchart TB").setValue(this.category.wrappings ? this.category.wrappings.join(", ") : "").onChange((value) => {
|
|
if (value.trim()) {
|
|
this.category.wrappings = value.split(",").map((w) => w.trim()).filter((w) => w);
|
|
} else {
|
|
this.category.wrappings = null;
|
|
}
|
|
}));
|
|
new import_obsidian3.Setting(contentEl).setName("Sort Order").setDesc("Determines the order in which categories appear").addText((text) => text.setPlaceholder("0").setValue(this.category.sortOrder.toString()).onChange((value) => {
|
|
const num = parseInt(value, 10);
|
|
if (!isNaN(num)) {
|
|
this.category.sortOrder = num;
|
|
}
|
|
}));
|
|
const buttonContainer = contentEl.createDiv("mermaid-tools-modal-button-container");
|
|
const cancelButton = buttonContainer.createEl("button", { text: "Cancel" });
|
|
cancelButton.onclick = () => this.close();
|
|
const saveButton = buttonContainer.createEl("button", {
|
|
text: this.isNewCategory ? "Create" : "Save",
|
|
cls: "mod-cta"
|
|
});
|
|
saveButton.onclick = () => {
|
|
void this.save();
|
|
};
|
|
}
|
|
async save() {
|
|
if (!this.category.id.trim()) {
|
|
new import_obsidian3.Notice("Category ID is required");
|
|
return;
|
|
}
|
|
if (!this.category.name.trim()) {
|
|
new import_obsidian3.Notice("Category name is required");
|
|
return;
|
|
}
|
|
if (!this.category.defaultWrapping.trim()) {
|
|
new import_obsidian3.Notice("Default wrapping is required");
|
|
return;
|
|
}
|
|
const commonDiagramTypes = [
|
|
"flowchart",
|
|
"graph",
|
|
"sequenceDiagram",
|
|
"classDiagram",
|
|
"stateDiagram-v2",
|
|
"erDiagram",
|
|
"journey",
|
|
"gantt",
|
|
"pie",
|
|
"requirementDiagram",
|
|
"gitGraph",
|
|
"mindmap",
|
|
"timeline",
|
|
"quadrantChart",
|
|
"C4Context",
|
|
"sankey-beta",
|
|
"xychart-beta",
|
|
"packet-beta",
|
|
"kanban",
|
|
"block-beta",
|
|
"architecture-beta"
|
|
];
|
|
const wrapping = this.category.defaultWrapping.trim().split(/\s+/)[0];
|
|
if (!commonDiagramTypes.includes(wrapping)) {
|
|
new import_obsidian3.Notice(`"${wrapping}" is not a recognized Mermaid diagram type. The category will still be saved.`);
|
|
}
|
|
if (this.isNewCategory && this.categoryService.getCategoryById(this.category.id)) {
|
|
new import_obsidian3.Notice(`A category with ID '${this.category.id}' already exists`);
|
|
return;
|
|
}
|
|
try {
|
|
await this.onSave(this.category);
|
|
this.close();
|
|
} catch (error) {
|
|
new import_obsidian3.Notice(`Error saving category: ${getErrorMessage2(error)}`);
|
|
}
|
|
}
|
|
};
|
|
function getErrorMessage2(error) {
|
|
return error instanceof Error ? error.message : String(error);
|
|
}
|
|
|
|
// src/ui/settingsTab.ts
|
|
var expandedCategoryIds = /* @__PURE__ */ new Set();
|
|
var MermaidToolsSettingsTab = class extends import_obsidian4.PluginSettingTab {
|
|
constructor(_app, _plugin) {
|
|
super(_app, _plugin);
|
|
this._app = _app;
|
|
this._plugin = _plugin;
|
|
}
|
|
async display() {
|
|
await renderSettings(this.containerEl, this._plugin);
|
|
}
|
|
};
|
|
async function renderSettings(containerEl, plugin) {
|
|
const mermaid = await (0, import_obsidian4.loadMermaid)();
|
|
const categoryService = CategoryService.getInstance();
|
|
categoryService.loadCategories(plugin.settings.customCategories, plugin.settings.defaultCategorySortOrders, plugin.settings.categoryModifications);
|
|
containerEl.empty();
|
|
containerEl.createEl("h1", { text: "Mermaid Tools Settings" });
|
|
containerEl.createEl("h2", { text: "Manage Elements & Categories" });
|
|
const buttonsContainer = containerEl.createDiv();
|
|
buttonsContainer.addClass("mermaid-tools-actions-row");
|
|
const addElementButton = buttonsContainer.createEl("button", { text: "Add Element" });
|
|
addElementButton.addClass("mod-cta");
|
|
addElementButton.onclick = () => {
|
|
const newElement = {
|
|
id: crypto.randomUUID(),
|
|
description: "New element",
|
|
content: `flowchart TD
|
|
Start --> Stop`,
|
|
categoryId: "flowchart",
|
|
sortingOrder: 0,
|
|
isPinned: false
|
|
};
|
|
const modal = new EditMermaidElementModal(plugin.app, plugin, mermaid, newElement, categoryService);
|
|
modal.open();
|
|
modal.onClose = () => {
|
|
void renderSettings(containerEl, plugin);
|
|
};
|
|
};
|
|
const addCategoryButton = buttonsContainer.createEl("button", { text: "Add Category" });
|
|
addCategoryButton.addClass("mod-cta");
|
|
addCategoryButton.onclick = () => {
|
|
const modal = new EditCategoryModal(plugin.app, null, async (category) => {
|
|
try {
|
|
if (category.sortOrder === void 0 || category.sortOrder === null) {
|
|
category.sortOrder = categoryService.getNextSortOrder();
|
|
}
|
|
categoryService.addCategory(category);
|
|
await saveAllCategoryChanges(plugin, categoryService);
|
|
await renderSettings(containerEl, plugin);
|
|
} catch (error) {
|
|
new import_obsidian4.Notice(`Error adding category: ${getErrorMessage3(error)}`);
|
|
}
|
|
});
|
|
modal.open();
|
|
};
|
|
createIntegratedCategorySection(containerEl, plugin, categoryService, mermaid);
|
|
}
|
|
async function saveAllCategoryChanges(plugin, categoryService) {
|
|
plugin.settings.customCategories = categoryService.getCustomCategories();
|
|
plugin.settings.defaultCategorySortOrders = {};
|
|
plugin.settings.categoryModifications = {};
|
|
const defaultCategories = categoryService.getCategories().filter((cat) => !cat.isCustom);
|
|
defaultCategories.forEach((cat) => {
|
|
var _a, _b, _c;
|
|
const originalCategory = DEFAULT_CATEGORIES.find((defaultCategory) => defaultCategory.id === cat.id);
|
|
if (!originalCategory) {
|
|
return;
|
|
}
|
|
if (cat.sortOrder !== originalCategory.sortOrder) {
|
|
plugin.settings.defaultCategorySortOrders[cat.id] = cat.sortOrder;
|
|
}
|
|
const categoryModification = {};
|
|
if (cat.name !== originalCategory.name) {
|
|
categoryModification.name = cat.name;
|
|
}
|
|
if (cat.defaultWrapping !== originalCategory.defaultWrapping) {
|
|
categoryModification.defaultWrapping = cat.defaultWrapping;
|
|
}
|
|
if (!areNullableStringArraysEqual((_a = cat.wrappings) != null ? _a : null, (_b = originalCategory.wrappings) != null ? _b : null)) {
|
|
categoryModification.wrappings = (_c = cat.wrappings) != null ? _c : null;
|
|
}
|
|
if (Object.keys(categoryModification).length > 0) {
|
|
plugin.settings.categoryModifications[cat.id] = categoryModification;
|
|
}
|
|
});
|
|
await plugin.saveSettings();
|
|
}
|
|
function createIntegratedCategorySection(containerEl, plugin, categoryService, mermaid) {
|
|
const allCategories = categoryService.getCategories().sort((a, b) => a.sortOrder - b.sortOrder);
|
|
allCategories.forEach((category) => {
|
|
const categoryContainer = containerEl.createDiv();
|
|
categoryContainer.addClass("mermaid-tools-category-section");
|
|
const categoryHeader = categoryContainer.createDiv();
|
|
categoryHeader.addClass("mermaid-tools-category-header");
|
|
const categoryTitle = categoryHeader.createDiv();
|
|
categoryTitle.addClass("mermaid-tools-category-title");
|
|
const expandIcon = categoryTitle.createSpan();
|
|
expandIcon.addClass("mermaid-tools-expand-icon");
|
|
expandIcon.setText("\u25BC");
|
|
const categoryName = categoryTitle.createEl("h3", { text: category.name });
|
|
categoryName.addClass("mermaid-tools-category-name");
|
|
const categoryInfo = categoryTitle.createSpan();
|
|
const elementCount = plugin.settings.elements.filter((el) => el.categoryId === category.id).length;
|
|
categoryInfo.setText(`(${elementCount} elements)`);
|
|
categoryInfo.addClass("mermaid-tools-category-info");
|
|
const categoryControls = categoryHeader.createDiv();
|
|
categoryControls.addClass("mermaid-tools-category-controls");
|
|
const addElementButton = createCategoryControlButton(categoryControls, "Add element to this category", "plus");
|
|
addElementButton.onclick = (e) => {
|
|
e.stopPropagation();
|
|
const newElement = {
|
|
id: crypto.randomUUID(),
|
|
description: "New element",
|
|
content: `flowchart TD
|
|
Start --> Stop`,
|
|
categoryId: category.id,
|
|
sortingOrder: plugin.settings.elements.filter((el) => el.categoryId === category.id).length,
|
|
isPinned: false
|
|
};
|
|
const modal = new EditMermaidElementModal(plugin.app, plugin, mermaid, newElement, categoryService);
|
|
modal.open();
|
|
modal.onClose = () => {
|
|
void renderSettings(containerEl, plugin);
|
|
};
|
|
};
|
|
const moveUpButton = createCategoryControlButton(categoryControls, "Move category up", "arrow-up");
|
|
moveUpButton.onclick = (e) => {
|
|
e.stopPropagation();
|
|
void moveCategory(category, -1, containerEl, plugin, categoryService);
|
|
};
|
|
const moveDownButton = createCategoryControlButton(categoryControls, "Move category down", "arrow-down");
|
|
moveDownButton.onclick = (e) => {
|
|
e.stopPropagation();
|
|
void moveCategory(category, 1, containerEl, plugin, categoryService);
|
|
};
|
|
const editButton = createCategoryControlButton(categoryControls, "Edit category", "edit");
|
|
editButton.onclick = (e) => {
|
|
e.stopPropagation();
|
|
const modal = new EditCategoryModal(plugin.app, category, async (updatedCategory) => {
|
|
try {
|
|
categoryService.updateCategory(updatedCategory);
|
|
await saveAllCategoryChanges(plugin, categoryService);
|
|
await renderSettings(containerEl, plugin);
|
|
} catch (error) {
|
|
new import_obsidian4.Notice(`Error updating category: ${getErrorMessage3(error)}`);
|
|
}
|
|
});
|
|
modal.open();
|
|
};
|
|
const deleteButton = createCategoryControlButton(categoryControls, "Delete category", "trash-2");
|
|
deleteButton.disabled = !category.isCustom;
|
|
if (!category.isCustom) {
|
|
deleteButton.title = "Default categories cannot be deleted";
|
|
deleteButton.setAttr("aria-label", "Default categories cannot be deleted");
|
|
}
|
|
deleteButton.onclick = (e) => {
|
|
e.stopPropagation();
|
|
if (!category.isCustom) {
|
|
return;
|
|
}
|
|
openDeleteCategoryConfirmation(category, containerEl, plugin, categoryService);
|
|
};
|
|
const elementsContainer = categoryContainer.createDiv();
|
|
elementsContainer.addClass("mermaid-tools-elements-container");
|
|
let isCollapsed = !expandedCategoryIds.has(category.id);
|
|
elementsContainer.toggleClass("is-collapsed", isCollapsed);
|
|
expandIcon.toggleClass("is-collapsed", isCollapsed);
|
|
categoryHeader.onclick = () => {
|
|
isCollapsed = !isCollapsed;
|
|
if (isCollapsed) {
|
|
expandedCategoryIds.delete(category.id);
|
|
} else {
|
|
expandedCategoryIds.add(category.id);
|
|
}
|
|
elementsContainer.toggleClass("is-collapsed", isCollapsed);
|
|
expandIcon.toggleClass("is-collapsed", isCollapsed);
|
|
};
|
|
renderCategoryElements(category, plugin, elementsContainer, mermaid, categoryService);
|
|
});
|
|
}
|
|
function renderCategoryElements(category, plugin, parentEl, mermaid, categoryService) {
|
|
const elements = plugin.settings.elements.filter((e) => e.categoryId === category.id).sort((a, b) => a.sortingOrder - b.sortingOrder);
|
|
if (elements.length === 0) {
|
|
const emptyMessage = parentEl.createDiv();
|
|
emptyMessage.setText("No elements in this category");
|
|
emptyMessage.addClass("mermaid-tools-empty-message");
|
|
return;
|
|
}
|
|
elements.forEach((element, index) => {
|
|
const settingContainer = parentEl.createDiv("mermaid-tools-element-container");
|
|
const setting = new import_obsidian4.Setting(settingContainer);
|
|
setting.setName(element.description);
|
|
setting.addExtraButton((cb) => {
|
|
cb.setIcon("edit").setTooltip("edit element").onClick(() => {
|
|
const modal = new EditMermaidElementModal(plugin.app, plugin, mermaid, element, categoryService);
|
|
modal.open();
|
|
modal.onClose = () => {
|
|
void renderSettingsFromParent(parentEl, plugin);
|
|
};
|
|
});
|
|
});
|
|
setting.addExtraButton((cb) => {
|
|
cb.setIcon("copy").setTooltip("create a duplicate of this element").onClick(() => {
|
|
void duplicateElement(element, plugin, parentEl);
|
|
});
|
|
});
|
|
setting.addExtraButton((cb) => {
|
|
cb.setIcon("arrow-up").setTooltip("move element up in the sidebar").onClick(() => {
|
|
void moveElement(category, elements, index, -1, plugin, parentEl);
|
|
});
|
|
});
|
|
setting.addExtraButton((cb) => {
|
|
cb.setIcon("arrow-down").setTooltip("move element down in the sidebar").onClick(() => {
|
|
void moveElement(category, elements, index, 1, plugin, parentEl);
|
|
});
|
|
});
|
|
setting.addExtraButton((cb) => {
|
|
cb.setIcon("trash-2").setTooltip("delete element").onClick(() => {
|
|
void deleteElement(element, plugin, parentEl);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
function createCategoryControlButton(parentEl, title, iconName) {
|
|
const button = parentEl.createEl("button");
|
|
button.addClass("mermaid-tools-icon-button");
|
|
button.title = title;
|
|
button.setAttr("aria-label", title);
|
|
(0, import_obsidian4.setIcon)(button, iconName);
|
|
return button;
|
|
}
|
|
async function moveCategory(category, direction, containerEl, plugin, categoryService) {
|
|
const categories = categoryService.getCategories().sort((a, b) => a.sortOrder - b.sortOrder);
|
|
const currentIndex = categories.findIndex((cat) => cat.id === category.id);
|
|
const nextIndex = currentIndex + direction;
|
|
if (currentIndex === -1 || nextIndex < 0 || nextIndex >= categories.length) {
|
|
return;
|
|
}
|
|
const adjacentCategory = categories[nextIndex];
|
|
const temp = adjacentCategory.sortOrder;
|
|
adjacentCategory.sortOrder = category.sortOrder;
|
|
category.sortOrder = temp;
|
|
categoryService.updateCategory(adjacentCategory);
|
|
categoryService.updateCategory(category);
|
|
await saveAllCategoryChanges(plugin, categoryService);
|
|
await renderSettings(containerEl, plugin);
|
|
}
|
|
function openDeleteCategoryConfirmation(category, containerEl, plugin, categoryService) {
|
|
const elementsInCategory = plugin.settings.elements.filter((el) => el.categoryId === category.id);
|
|
if (elementsInCategory.length > 0) {
|
|
new import_obsidian4.Notice(`Cannot delete category '${category.name}' because it contains ${elementsInCategory.length} element(s).`);
|
|
return;
|
|
}
|
|
new ConfirmActionModal(plugin.app, "Delete Category", category.isCustom ? `Delete the category '${category.name}'?` : `Delete the default category '${category.name}'? This action cannot be undone.`, async () => {
|
|
try {
|
|
categoryService.deleteCategory(category.id);
|
|
expandedCategoryIds.delete(category.id);
|
|
if (category.isCustom) {
|
|
plugin.settings.customCategories = categoryService.getCustomCategories();
|
|
}
|
|
await plugin.saveSettings();
|
|
await renderSettings(containerEl, plugin);
|
|
} catch (error) {
|
|
new import_obsidian4.Notice(`Error deleting category: ${getErrorMessage3(error)}`);
|
|
}
|
|
}).open();
|
|
}
|
|
async function duplicateElement(element, plugin, parentEl) {
|
|
const duplicate = {
|
|
id: crypto.randomUUID(),
|
|
categoryId: element.categoryId,
|
|
description: element.description + " (copy)",
|
|
content: element.content,
|
|
sortingOrder: plugin.settings.elements.filter((el) => el.categoryId === element.categoryId).length,
|
|
isPinned: element.isPinned
|
|
};
|
|
await plugin._mermaidElementService.saveElement(duplicate, plugin);
|
|
await renderSettingsFromParent(parentEl, plugin);
|
|
}
|
|
async function moveElement(category, elements, index, direction, plugin, parentEl) {
|
|
const nextIndex = index + direction;
|
|
if (nextIndex < 0 || nextIndex >= elements.length) {
|
|
return;
|
|
}
|
|
const temp = elements[nextIndex].sortingOrder;
|
|
elements[nextIndex].sortingOrder = elements[index].sortingOrder;
|
|
elements[index].sortingOrder = temp;
|
|
plugin.settings.elements = plugin.settings.elements.filter((el) => el.categoryId !== category.id).concat(elements);
|
|
expandedCategoryIds.add(category.id);
|
|
await plugin.saveSettings();
|
|
await renderSettingsFromParent(parentEl, plugin);
|
|
}
|
|
async function deleteElement(element, plugin, parentEl) {
|
|
plugin.settings.elements = plugin.settings.elements.filter((e) => e.id !== element.id);
|
|
await plugin.saveSettings();
|
|
await renderSettingsFromParent(parentEl, plugin);
|
|
}
|
|
async function renderSettingsFromParent(parentEl, plugin) {
|
|
const settingsContainer = parentEl.closest(".vertical-tab-content");
|
|
if (settingsContainer instanceof HTMLElement) {
|
|
await renderSettings(settingsContainer, plugin);
|
|
}
|
|
}
|
|
function getErrorMessage3(error) {
|
|
return error instanceof Error ? error.message : String(error);
|
|
}
|
|
function areNullableStringArraysEqual(first, second) {
|
|
if (first === null || second === null) {
|
|
return first === second;
|
|
}
|
|
return first.length === second.length && first.every((value, index) => value === second[index]);
|
|
}
|
|
var ConfirmActionModal = class extends import_obsidian4.Modal {
|
|
constructor(app, title, message, onConfirm) {
|
|
super(app);
|
|
this.title = title;
|
|
this.message = message;
|
|
this.onConfirm = onConfirm;
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
contentEl.addClass("mermaid-tools-confirm-modal");
|
|
contentEl.createEl("h2", { text: this.title });
|
|
contentEl.createEl("p", { text: this.message });
|
|
const buttonContainer = contentEl.createDiv("mermaid-tools-modal-button-container");
|
|
const cancelButton = buttonContainer.createEl("button", { text: "Cancel" });
|
|
cancelButton.onclick = () => this.close();
|
|
const confirmButton = buttonContainer.createEl("button", {
|
|
text: "Delete",
|
|
cls: "mod-warning"
|
|
});
|
|
confirmButton.onclick = () => {
|
|
void this.runConfirmedAction();
|
|
};
|
|
}
|
|
async runConfirmedAction() {
|
|
await this.onConfirm();
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
// src/ui/toolbarView/mermaidToolbarView.ts
|
|
var import_obsidian6 = require("obsidian");
|
|
|
|
// src/ui/toolbarView/viewHelpers.ts
|
|
var import_obsidian5 = require("obsidian");
|
|
var TOOLBAR_ELEMENT_CLASS_NAME = "mermaid-toolbar-element";
|
|
var TOOLBAR_ELEMENTS_CONTAINER_CLASS_NAME = "mermaid-toolbar-elements-container";
|
|
var TOOLBAR_ELEMENTS_CONTAINER_ID = "mermaid-toolbar-elements-container-id";
|
|
async function createMermaidToolbar(topRowButtons, items, selectedCategoryId, onCategoryChanged, onElementClick, categoryService) {
|
|
const container = document.createElement("div");
|
|
const topRow = container.createDiv();
|
|
topRow.addClass("mermaid-toolbar-top-row");
|
|
const elementsContainer = container.createDiv();
|
|
elementsContainer.addClass(TOOLBAR_ELEMENTS_CONTAINER_CLASS_NAME);
|
|
elementsContainer.setAttr("id", TOOLBAR_ELEMENTS_CONTAINER_ID);
|
|
createDropdown(topRow, elementsContainer, items, selectedCategoryId, onCategoryChanged, onElementClick, categoryService);
|
|
createTopRowBtns(topRow, topRowButtons);
|
|
await recreateElementsSection(elementsContainer, selectedCategoryId, items, onElementClick);
|
|
return container;
|
|
}
|
|
function createTopRowBtns(parentEl, buttons) {
|
|
buttons.forEach((btn) => {
|
|
const b = new import_obsidian5.ButtonComponent(parentEl).setClass("clickable-icon").setIcon(btn.iconName).setTooltip(btn.tooltip).onClick(btn.callback);
|
|
});
|
|
}
|
|
function createDropdown(parentEl, elementsContainer, items, selectedCategoryId, onSelectionChanged, onElClick, categoryService) {
|
|
const categories = categoryService.getCategories();
|
|
const dropdown = new import_obsidian5.DropdownComponent(parentEl);
|
|
categories.forEach((category) => {
|
|
dropdown.addOption(category.id, category.name);
|
|
});
|
|
dropdown.setValue(selectedCategoryId);
|
|
dropdown.onChange((val) => {
|
|
void handleCategoryChanged(elementsContainer, val, items, onSelectionChanged, onElClick);
|
|
});
|
|
}
|
|
async function handleCategoryChanged(elementsContainer, categoryId, items, onSelectionChanged, onElClick) {
|
|
await onSelectionChanged(categoryId);
|
|
await recreateElementsSection(elementsContainer, categoryId, items, onElClick);
|
|
}
|
|
async function recreateElementsSection(sectionContainer, categoryId, items, onElClick) {
|
|
sectionContainer.empty();
|
|
const elemService = new MermaidElementService();
|
|
const mermaid = await (0, import_obsidian5.loadMermaid)();
|
|
const filteredSortedItems = items.filter((i) => i.categoryId === categoryId).sort((a, b) => a.sortingOrder - b.sortingOrder);
|
|
for (const [index, elem] of filteredSortedItems.entries()) {
|
|
const el = createToolbarElement(sectionContainer);
|
|
el.id = `mermaid-toolbar-element-${elem.categoryId}-${index}`;
|
|
const diagram = elemService.wrapAsCompleteDiagram(elem);
|
|
el.title = elem.description;
|
|
try {
|
|
const { svg } = await mermaid.render(createMermaidPreviewId2(), diagram);
|
|
setMermaidSvgContent(el, svg);
|
|
} catch (error) {
|
|
renderToolbarElementError(el, elem.description, error);
|
|
}
|
|
el.onclick = () => onElClick(elem.content);
|
|
sectionContainer.appendChild(el);
|
|
}
|
|
}
|
|
function createToolbarElement(parentEl) {
|
|
const itemEl = parentEl.createEl("pre");
|
|
itemEl.addClass(TOOLBAR_ELEMENT_CLASS_NAME);
|
|
return itemEl;
|
|
}
|
|
function renderToolbarElementError(el, description, error) {
|
|
el.empty();
|
|
el.addClass("mermaid-toolbar-element-error");
|
|
el.title = `${description}: ${getErrorMessage4(error)}`;
|
|
el.createDiv({ text: description });
|
|
const errorEl = el.createDiv({ text: "Preview unavailable" });
|
|
errorEl.addClass("mermaid-toolbar-element-error-message");
|
|
}
|
|
function getErrorMessage4(error) {
|
|
return error instanceof Error ? error.message : String(error);
|
|
}
|
|
function createMermaidPreviewId2() {
|
|
return `mermaid-tools-toolbar-preview-${crypto.randomUUID()}`;
|
|
}
|
|
|
|
// src/ui/toolbarView/mermaidToolbarButtons.ts
|
|
var MermaidToolbarButton = class {
|
|
constructor(tooltip, iconName, callback) {
|
|
this.tooltip = tooltip;
|
|
this.iconName = iconName;
|
|
this.callback = callback;
|
|
}
|
|
};
|
|
|
|
// src/ui/toolbarView/mermaidToolbarView.ts
|
|
var _MermaidToolbarView = class extends import_obsidian6.ItemView {
|
|
constructor(leaf, plugin) {
|
|
super(leaf);
|
|
this.topRowButtons = [
|
|
new MermaidToolbarButton("insert Mermaid code block with sample diagram", "code-2", () => this.insertTextAtCursor(this._plugin._mermaidElementService.getSampleDiagram(this._plugin.settings.selectedCategoryId))),
|
|
new MermaidToolbarButton("open Mermaid.js documentation web page", "external-link", () => window.open("https://mermaid.js.org/intro/", "_blank", "noopener")),
|
|
new MermaidToolbarButton("open settings", "settings", () => {
|
|
const settings = this.app.setting;
|
|
settings == null ? void 0 : settings.open();
|
|
settings == null ? void 0 : settings.openTabById("mermaid-tools");
|
|
})
|
|
];
|
|
this._plugin = plugin;
|
|
this.items = plugin.settings.elements;
|
|
this.categoryService = CategoryService.getInstance();
|
|
this.categoryService.loadCategories(plugin.settings.customCategories, plugin.settings.defaultCategorySortOrders, plugin.settings.categoryModifications);
|
|
this.containerEl.children[1].addClass("mermaid-toolbar-container");
|
|
}
|
|
async onOpen() {
|
|
await this.recreateToolbar(this._plugin.settings.selectedCategoryId);
|
|
}
|
|
async onClose() {
|
|
}
|
|
async recreateToolbar(selectedCategoryId) {
|
|
this.items = this._plugin.settings.elements;
|
|
this.categoryService.loadCategories(this._plugin.settings.customCategories, this._plugin.settings.defaultCategorySortOrders, this._plugin.settings.categoryModifications);
|
|
const container = this.containerEl.children[1];
|
|
container.empty();
|
|
const toolbarElement = await createMermaidToolbar(this.topRowButtons, this.items, selectedCategoryId, (newCategoryId) => {
|
|
this._plugin.settings.selectedCategoryId = newCategoryId;
|
|
void this._plugin.saveSettings({ refreshToolbar: false });
|
|
}, (text) => this.insertTextAtCursor(text), this.categoryService);
|
|
container.appendChild(toolbarElement);
|
|
}
|
|
insertTextAtCursor(text) {
|
|
this._plugin.insertTextAtCursor(text);
|
|
}
|
|
getViewType() {
|
|
return _MermaidToolbarView.VIEW_TYPE;
|
|
}
|
|
getDisplayText() {
|
|
return _MermaidToolbarView.VIEW_DESCRIPTION;
|
|
}
|
|
getIcon() {
|
|
return TRIDENT_ICON_NAME;
|
|
}
|
|
};
|
|
var MermaidToolbarView = _MermaidToolbarView;
|
|
MermaidToolbarView.VIEW_TYPE = "mermaid-toolbar-view";
|
|
MermaidToolbarView.VIEW_DESCRIPTION = "Mermaid Toolbar";
|
|
|
|
// main.ts
|
|
var TRIDENT_ICON_NAME = "trident-custom";
|
|
var MermaidPlugin = class extends import_obsidian7.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.activeEditor = null;
|
|
this._mermaidElementService = new MermaidElementService();
|
|
this._textEditorService = new TextEditorService();
|
|
}
|
|
async onload() {
|
|
var _a, _b;
|
|
await this.loadSettings();
|
|
addTridentIcon();
|
|
this.registerView(MermaidToolbarView.VIEW_TYPE, (leaf) => new MermaidToolbarView(leaf, this));
|
|
this.activeEditor = (_b = (_a = this.app.workspace.activeEditor) == null ? void 0 : _a.editor) != null ? _b : null;
|
|
this.registerEvent(this.app.workspace.on("active-leaf-change", (_leaf) => {
|
|
var _a2, _b2;
|
|
this.activeEditor = (_b2 = (_a2 = this.app.workspace.activeEditor) == null ? void 0 : _a2.editor) != null ? _b2 : this.activeEditor;
|
|
}));
|
|
this.addRibbonIcon(TRIDENT_ICON_NAME, "Open Mermaid Toolbar", () => {
|
|
void this.activateView();
|
|
});
|
|
this.addCommand({
|
|
id: "open-toolbar",
|
|
name: "Open Toolbar View",
|
|
callback: () => {
|
|
void this.activateView();
|
|
}
|
|
});
|
|
this.addSettingTab(new MermaidToolsSettingsTab(this.app, this));
|
|
}
|
|
async onunload() {
|
|
this.app.workspace.detachLeavesOfType(MermaidToolbarView.VIEW_TYPE);
|
|
}
|
|
async loadSettings() {
|
|
var _a, _b, _c, _d, _e, _f;
|
|
const defaultSettings = MermaidPluginSettings.DefaultSettings();
|
|
const loadedSettings = await this.loadData();
|
|
this.settings = Object.assign({}, defaultSettings, loadedSettings);
|
|
this.settings.elements = (_a = this.settings.elements) != null ? _a : defaultSettings.elements;
|
|
this.settings.customCategories = (_b = this.settings.customCategories) != null ? _b : defaultSettings.customCategories;
|
|
this.settings.selectedCategoryId = (_c = this.settings.selectedCategoryId) != null ? _c : defaultSettings.selectedCategoryId;
|
|
this.settings.defaultCategorySortOrders = (_d = this.settings.defaultCategorySortOrders) != null ? _d : defaultSettings.defaultCategorySortOrders;
|
|
this.settings.categoryModifications = (_e = this.settings.categoryModifications) != null ? _e : defaultSettings.categoryModifications;
|
|
this.settings.defaultElementCategoryIds = loadedSettings ? (_f = loadedSettings.defaultElementCategoryIds) != null ? _f : [] : defaultSettings.defaultElementCategoryIds;
|
|
if (this.addNewCategories()) {
|
|
await this.saveData(this.settings);
|
|
}
|
|
}
|
|
addNewCategories() {
|
|
const defaultCategoryElementSets = [
|
|
{ categoryId: "mindmap", elements: mindMapElements },
|
|
{ categoryId: "timeline", elements: timelineElements },
|
|
{ categoryId: "quadrantChart", elements: quadrantElements },
|
|
{ categoryId: "c4Diagram", elements: c4DiagramElements },
|
|
{ categoryId: "sankeyDiagram", elements: sankeyDiagramElements },
|
|
{ categoryId: "xyChart", elements: xyChartElements },
|
|
{ categoryId: "packet", elements: packetElements },
|
|
{ categoryId: "kanban", elements: kanbanElements },
|
|
{ categoryId: "block", elements: blockDiagramElements },
|
|
{ categoryId: "architecture", elements: architectureElements }
|
|
];
|
|
const installedCategoryIds = new Set(this.settings.defaultElementCategoryIds);
|
|
let settingsChanged = false;
|
|
for (const defaultCategory of defaultCategoryElementSets) {
|
|
if (installedCategoryIds.has(defaultCategory.categoryId)) {
|
|
continue;
|
|
}
|
|
if (!this.settings.elements.some((element) => element.categoryId === defaultCategory.categoryId)) {
|
|
this.settings.elements.push(...defaultCategory.elements);
|
|
}
|
|
installedCategoryIds.add(defaultCategory.categoryId);
|
|
settingsChanged = true;
|
|
}
|
|
this.settings.defaultElementCategoryIds = Array.from(installedCategoryIds);
|
|
return settingsChanged;
|
|
}
|
|
async saveSettings(options = {}) {
|
|
var _a;
|
|
await this.saveData(this.settings);
|
|
if ((_a = options.refreshToolbar) != null ? _a : true) {
|
|
await this.refreshToolbarViews();
|
|
}
|
|
}
|
|
async refreshToolbarViews() {
|
|
const toolbarLeaves = this.app.workspace.getLeavesOfType(MermaidToolbarView.VIEW_TYPE);
|
|
await Promise.all(toolbarLeaves.map(async (leaf) => {
|
|
if (leaf.view instanceof MermaidToolbarView) {
|
|
await leaf.view.recreateToolbar(this.settings.selectedCategoryId);
|
|
}
|
|
}));
|
|
}
|
|
async activateView() {
|
|
var _a;
|
|
this.app.workspace.detachLeavesOfType(MermaidToolbarView.VIEW_TYPE);
|
|
const leaf = (_a = this.app.workspace.getRightLeaf(false)) != null ? _a : this.app.workspace.getLeaf(true);
|
|
await leaf.setViewState({
|
|
type: MermaidToolbarView.VIEW_TYPE,
|
|
active: true
|
|
});
|
|
await this.app.workspace.revealLeaf(leaf);
|
|
}
|
|
insertTextAtCursor(text) {
|
|
var _a, _b;
|
|
const editor = (_b = (_a = this.app.workspace.activeEditor) == null ? void 0 : _a.editor) != null ? _b : this.activeEditor;
|
|
try {
|
|
this._textEditorService.insertTextAtCursor(editor, text);
|
|
this.activeEditor = editor != null ? editor : this.activeEditor;
|
|
} catch (error) {
|
|
new import_obsidian7.Notice(getErrorMessage5(error));
|
|
}
|
|
}
|
|
};
|
|
function getErrorMessage5(error) {
|
|
return error instanceof Error ? error.message : String(error);
|
|
}
|
|
|
|
/* nosourcemap */ |