diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json index f5260cd..557fc5a 100644 --- a/.obsidian/community-plugins.json +++ b/.obsidian/community-plugins.json @@ -14,5 +14,5 @@ "obsidian-link-embed", "obsidian-auto-link-title", "automatic-table-of-contents", - "password-protection" + "mermaid-tools" ] \ No newline at end of file diff --git a/.obsidian/graph.json b/.obsidian/graph.json index 17cc4be..40d80ec 100644 --- a/.obsidian/graph.json +++ b/.obsidian/graph.json @@ -17,6 +17,6 @@ "repelStrength": 10, "linkStrength": 1, "linkDistance": 250, - "scale": 0.752337220605296, + "scale": 0.3588519998387622, "close": true } \ No newline at end of file diff --git a/.obsidian/plugins/mermaid-tools/main.js b/.obsidian/plugins/mermaid-tools/main.js new file mode 100644 index 0000000..829d903 --- /dev/null +++ b/.obsidian/plugins/mermaid-tools/main.js @@ -0,0 +1,2633 @@ +/* +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,
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,
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
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 <> + [*] --> 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_state + fork_state --> State2 + fork_state --> State3 + + state join_state <> + 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
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 = {}) { + const defaultCategories = DEFAULT_CATEGORIES.map((cat) => ({ + ...cat, + 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; + } + saveElement(element, plugin) { + const elementExists = plugin.settings.elements.some((el) => el.id === element.id); + if (elementExists) { + 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); + } + 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) { + console.warn(`[Mermaid Tools] No category found for ID: ${categoryId}, using default sample`); + 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)); + } + console.warn(`[Mermaid Tools] No sample diagram found for category: ${category.name}, using default 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) { + console.warn(`[Mermaid Tools] No wrapping data found for category: ${element.categoryId}`); + return element.content; + } + const contentAlreadyWrapped = wrapping.wrappings ? wrapping.wrappings.some((w) => element.content.contains(w)) : element.content.contains(wrapping.defaultWrapping); + if (contentAlreadyWrapped) { + return element.content; + } + const wrappedContent = wrapping.defaultWrapping + "\n" + element.content; + const firstWord = wrapping.defaultWrapping.trim().split(/\s+/)[0]; + const validDiagramTypes = [ + "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" + ]; + if (!validDiagramTypes.includes(firstWord)) { + console.warn(`[Mermaid Tools] Potentially invalid diagram type "${firstWord}" in category ${element.categoryId}. This may cause rendering errors.`); + } + 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 = {}; + return settings; + } +}; + +// src/trident-icon.ts +var import_obsidian = require("obsidian"); +function addTridentIcon() { + (0, import_obsidian.addIcon)(TRIDENT_ICON_NAME, getSanitizedSvg()); +} +function getSanitizedSvg() { + var sanitized = (0, import_obsidian.sanitizeHTMLToDom)(tridentIcon); + var tempContainer = createDiv(); + tempContainer.appendChild(sanitized); + return tempContainer.innerHTML; +} +var tridentIcon = ` + +`; + +// src/ui/settingsTab.ts +var import_obsidian4 = require("obsidian"); + +// src/ui/editMermaidElementModal.ts +var import_obsidian2 = require("obsidian"); +var EditMermaidElementModal = class extends import_obsidian2.Modal { + constructor(app, _plugin, _mermaid, _element, _categoryService) { + super(app); + this._plugin = _plugin; + this._mermaid = _mermaid; + this._element = _element; + this._categoryService = _categoryService; + } + 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.createEl("pre", { text: "rendered diagram" }); + if (!this._mermaid) + this._mermaid = await (0, import_obsidian2.loadMermaid)(); + renderEl.id = "mermaid-edit-element-modal"; + 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 = (e) => { + this._element.categoryId = elementCategoryEl.value; + }; + const elementDescriptionContainerEl = contentEl.createDiv(); + elementDescriptionContainerEl.createEl("label", { text: "Description" }); + const elementDescriptionEl = elementDescriptionContainerEl.createEl("input", { value: this._element.description, type: "text" }); + elementDescriptionEl.style.minWidth = "50%"; + elementDescriptionEl.onchange = (e) => { + this._element.description = elementDescriptionEl.value; + }; + const elementContentContainerEl = contentEl.createDiv(); + elementContentContainerEl.createEl("label", { text: "Content" }); + const elementContentEl = elementContentContainerEl.createEl("textarea", { text: this._element.content }); + elementContentEl.style.height = "200px"; + elementContentEl.style.width = "100%"; + elementContentEl.onchange = async (e) => { + this._element.content = elementContentEl.value; + const { svg: svg2 } = await this._mermaid.render(renderEl.id, this._plugin._mermaidElementService.wrapAsCompleteDiagram(this._element)); + renderEl.innerHTML = svg2; + renderContainerEl.appendChild(renderEl); + }; + const saveButtonEl = contentEl.createEl("button", { text: "Save" }); + saveButtonEl.onclick = (e) => { + this.save(); + }; + const { svg } = await this._mermaid.render(renderEl.id, this._plugin._mermaidElementService.wrapAsCompleteDiagram(this._element)); + renderEl.innerHTML = svg; + renderContainerEl.appendChild(renderEl); + } + save() { + this._plugin._mermaidElementService.saveElement(this._element, this._plugin); + this.close(); + } +}; + +// src/ui/editCategoryModal.ts +var import_obsidian3 = require("obsidian"); +var EditCategoryModal = class extends import_obsidian3.Modal { + constructor(app, plugin, existingCategory, onSave) { + super(app); + this.plugin = plugin; + 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("Unique identifier for this category (lowercase, no spaces)").addText((text) => text.setPlaceholder("my-custom-category").setValue(this.category.id).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); + if (!isNaN(num)) { + this.category.sortOrder = num; + } + })); + const buttonContainer = contentEl.createDiv("modal-button-container"); + buttonContainer.style.display = "flex"; + buttonContainer.style.justifyContent = "flex-end"; + buttonContainer.style.gap = "10px"; + buttonContainer.style.marginTop = "20px"; + 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 = () => this.save(); + } + save() { + if (!this.category.id.trim()) { + alert("Category ID is required"); + return; + } + if (!this.category.name.trim()) { + alert("Category name is required"); + return; + } + if (!this.category.defaultWrapping.trim()) { + alert("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)) { + const shouldContinue = confirm(`Warning: "${wrapping}" is not a recognized Mermaid diagram type. This may cause rendering errors. Are you sure you want to continue?`); + if (!shouldContinue) { + return; + } + } + if (this.isNewCategory && this.categoryService.getCategoryById(this.category.id)) { + alert(`A category with ID '${this.category.id}' already exists`); + return; + } + try { + this.onSave(this.category); + this.close(); + } catch (error) { + alert(`Error saving category: ${error.message}`); + } + } +}; + +// src/ui/settingsTab.ts +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); + containerEl.empty(); + containerEl.createEl("h1", { text: "Mermaid Tools Settings" }); + containerEl.createEl("h2", { text: "Manage Elements & Categories" }); + const buttonsContainer = containerEl.createDiv(); + buttonsContainer.style.marginBottom = "20px"; + buttonsContainer.style.display = "flex"; + buttonsContainer.style.gap = "10px"; + 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 = () => { + renderSettings(containerEl, plugin); + }; + }; + const addCategoryButton = buttonsContainer.createEl("button", { text: "Add Category" }); + addCategoryButton.addClass("mod-cta"); + addCategoryButton.onclick = () => { + const modal = new EditCategoryModal(plugin.app, plugin, null, (category) => { + try { + if (category.sortOrder === void 0 || category.sortOrder === null) { + category.sortOrder = categoryService.getNextSortOrder(); + } + categoryService.addCategory(category); + saveAllCategoryChanges(plugin, categoryService); + renderSettings(containerEl, plugin); + } catch (error) { + console.error("Error adding category:", error); + } + }); + modal.open(); + }; + createIntegratedCategorySection(containerEl, plugin, categoryService, mermaid); +} +function saveAllCategoryChanges(plugin, categoryService) { + plugin.settings.customCategories = categoryService.getCustomCategories(); + const defaultCategories = categoryService.getCategories().filter((cat) => !cat.isCustom); + defaultCategories.forEach((cat) => { + plugin.settings.defaultCategorySortOrders[cat.id] = cat.sortOrder; + }); + 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"); + categoryContainer.style.marginBottom = "20px"; + categoryContainer.style.border = "1px solid var(--background-modifier-border)"; + categoryContainer.style.borderRadius = "8px"; + categoryContainer.style.padding = "15px"; + const categoryHeader = categoryContainer.createDiv(); + categoryHeader.style.display = "flex"; + categoryHeader.style.alignItems = "center"; + categoryHeader.style.justifyContent = "space-between"; + categoryHeader.style.marginBottom = "10px"; + categoryHeader.style.cursor = "pointer"; + const categoryTitle = categoryHeader.createDiv(); + categoryTitle.style.display = "flex"; + categoryTitle.style.alignItems = "center"; + categoryTitle.style.gap = "10px"; + const expandIcon = categoryTitle.createSpan(); + expandIcon.innerHTML = "\u25BC"; + expandIcon.style.fontSize = "12px"; + expandIcon.style.transition = "transform 0.2s"; + const categoryName = categoryTitle.createEl("h3", { text: category.name }); + categoryName.style.margin = "0"; + categoryName.style.fontSize = "16px"; + const categoryInfo = categoryTitle.createSpan(); + const elementCount = plugin.settings.elements.filter((el) => el.categoryId === category.id).length; + categoryInfo.textContent = `(${elementCount} elements)`; + categoryInfo.style.color = "var(--text-muted)"; + categoryInfo.style.fontSize = "12px"; + const categoryControls = categoryHeader.createDiv(); + categoryControls.style.display = "flex"; + categoryControls.style.gap = "2px"; + const addElementButton = categoryControls.createEl("button"); + addElementButton.title = "Add element to this category"; + addElementButton.style.background = "none"; + addElementButton.style.border = "none"; + addElementButton.style.cursor = "pointer"; + addElementButton.style.padding = "4px"; + addElementButton.style.display = "flex"; + addElementButton.style.alignItems = "center"; + addElementButton.style.borderRadius = "3px"; + addElementButton.innerHTML = ``; + addElementButton.onmouseenter = () => addElementButton.style.backgroundColor = "var(--background-modifier-hover)"; + addElementButton.onmouseleave = () => addElementButton.style.backgroundColor = "transparent"; + 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 = () => { + renderSettings(containerEl, plugin); + }; + }; + const moveUpButton = categoryControls.createEl("button"); + moveUpButton.title = "Move category up"; + moveUpButton.style.background = "none"; + moveUpButton.style.border = "none"; + moveUpButton.style.cursor = "pointer"; + moveUpButton.style.padding = "4px"; + moveUpButton.style.display = "flex"; + moveUpButton.style.alignItems = "center"; + moveUpButton.style.borderRadius = "3px"; + moveUpButton.innerHTML = ``; + moveUpButton.onmouseenter = () => moveUpButton.style.backgroundColor = "var(--background-modifier-hover)"; + moveUpButton.onmouseleave = () => moveUpButton.style.backgroundColor = "transparent"; + moveUpButton.onclick = (e) => { + e.stopPropagation(); + const categories = categoryService.getCategories().sort((a, b) => a.sortOrder - b.sortOrder); + const currentIndex = categories.findIndex((cat) => cat.id === category.id); + if (currentIndex > 0) { + const temp = categories[currentIndex - 1].sortOrder; + categories[currentIndex - 1].sortOrder = category.sortOrder; + category.sortOrder = temp; + categoryService.updateCategory(categories[currentIndex - 1]); + categoryService.updateCategory(category); + saveAllCategoryChanges(plugin, categoryService); + renderSettings(containerEl, plugin); + } + }; + const moveDownButton = categoryControls.createEl("button"); + moveDownButton.title = "Move category down"; + moveDownButton.style.background = "none"; + moveDownButton.style.border = "none"; + moveDownButton.style.cursor = "pointer"; + moveDownButton.style.padding = "4px"; + moveDownButton.style.display = "flex"; + moveDownButton.style.alignItems = "center"; + moveDownButton.style.borderRadius = "3px"; + moveDownButton.innerHTML = ``; + moveDownButton.onmouseenter = () => moveDownButton.style.backgroundColor = "var(--background-modifier-hover)"; + moveDownButton.onmouseleave = () => moveDownButton.style.backgroundColor = "transparent"; + moveDownButton.onclick = (e) => { + e.stopPropagation(); + const categories = categoryService.getCategories().sort((a, b) => a.sortOrder - b.sortOrder); + const currentIndex = categories.findIndex((cat) => cat.id === category.id); + if (currentIndex < categories.length - 1) { + const temp = categories[currentIndex + 1].sortOrder; + categories[currentIndex + 1].sortOrder = category.sortOrder; + category.sortOrder = temp; + categoryService.updateCategory(categories[currentIndex + 1]); + categoryService.updateCategory(category); + saveAllCategoryChanges(plugin, categoryService); + renderSettings(containerEl, plugin); + } + }; + const editButton = categoryControls.createEl("button"); + editButton.title = "Edit category"; + editButton.style.background = "none"; + editButton.style.border = "none"; + editButton.style.cursor = "pointer"; + editButton.style.padding = "4px"; + editButton.style.display = "flex"; + editButton.style.alignItems = "center"; + editButton.style.borderRadius = "3px"; + editButton.innerHTML = ``; + editButton.onmouseenter = () => editButton.style.backgroundColor = "var(--background-modifier-hover)"; + editButton.onmouseleave = () => editButton.style.backgroundColor = "transparent"; + editButton.onclick = (e) => { + e.stopPropagation(); + const modal = new EditCategoryModal(plugin.app, plugin, category, (updatedCategory) => { + try { + categoryService.updateCategory(updatedCategory); + saveAllCategoryChanges(plugin, categoryService); + renderSettings(containerEl, plugin); + } catch (error) { + console.error("Error updating category:", error); + } + }); + modal.open(); + }; + const deleteButton = categoryControls.createEl("button"); + deleteButton.title = "Delete category"; + deleteButton.style.background = "none"; + deleteButton.style.border = "none"; + deleteButton.style.cursor = "pointer"; + deleteButton.style.padding = "4px"; + deleteButton.style.display = "flex"; + deleteButton.style.alignItems = "center"; + deleteButton.style.borderRadius = "3px"; + deleteButton.innerHTML = ``; + deleteButton.onmouseenter = () => deleteButton.style.backgroundColor = "var(--background-modifier-hover)"; + deleteButton.onmouseleave = () => deleteButton.style.backgroundColor = "transparent"; + deleteButton.onclick = (e) => { + e.stopPropagation(); + const elementsInCategory = plugin.settings.elements.filter((el) => el.categoryId === category.id); + if (elementsInCategory.length > 0) { + alert(`Cannot delete category '${category.name}' because it contains ${elementsInCategory.length} element(s). Please move or delete these elements first.`); + return; + } + const confirmMessage = category.isCustom ? `Are you sure you want to delete the category '${category.name}'?` : `Are you sure you want to delete the default category '${category.name}'? This action cannot be undone.`; + if (confirm(confirmMessage)) { + try { + categoryService.deleteCategory(category.id); + if (category.isCustom) { + plugin.settings.customCategories = categoryService.getCustomCategories(); + } + plugin.saveSettings(); + renderSettings(containerEl, plugin); + } catch (error) { + console.error("Error deleting category:", error); + if (!category.isCustom) { + alert(`Cannot delete default category: ${error.message}`); + } + } + } + }; + const elementsContainer = categoryContainer.createDiv(); + elementsContainer.addClass("mermaid-tools-elements-container"); + elementsContainer.style.display = "none"; + let isCollapsed = true; + categoryHeader.onclick = () => { + isCollapsed = !isCollapsed; + elementsContainer.style.display = isCollapsed ? "none" : "block"; + expandIcon.style.transform = isCollapsed ? "rotate(-90deg)" : "rotate(0deg)"; + }; + expandIcon.style.transform = "rotate(-90deg)"; + 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.textContent = "No elements in this category"; + emptyMessage.style.color = "var(--text-muted)"; + emptyMessage.style.fontStyle = "italic"; + emptyMessage.style.padding = "10px"; + return; + } + elements.forEach((element, index) => { + const settingContainer = parentEl.createDiv("mermaid-tools-element-container"); + settingContainer.style.marginBottom = "10px"; + settingContainer.style.padding = "10px"; + settingContainer.style.backgroundColor = "var(--background-secondary)"; + settingContainer.style.borderRadius = "5px"; + 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 = () => { + const settingsContainer = parentEl.closest(".vertical-tab-content"); + if (settingsContainer) + renderSettings(settingsContainer, plugin); + }; + }); + }); + setting.addExtraButton((cb) => { + cb.setIcon("copy").setTooltip("create a duplicate of this element").onClick(() => { + 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 + }; + plugin._mermaidElementService.saveElement(duplicate, plugin); + plugin.saveSettings(); + const settingsContainer = parentEl.closest(".vertical-tab-content"); + if (settingsContainer) + renderSettings(settingsContainer, plugin); + }); + }); + setting.addExtraButton((cb) => { + cb.setIcon("arrow-up").setTooltip("move element up in the sidebar").onClick(() => { + if (index > 0) { + const temp = elements[index - 1].sortingOrder; + elements[index - 1].sortingOrder = element.sortingOrder; + element.sortingOrder = temp; + plugin.settings.elements = plugin.settings.elements.filter((el) => el.categoryId !== category.id).concat(elements); + plugin.saveSettings(); + const settingsContainer = parentEl.closest(".vertical-tab-content"); + if (settingsContainer) + renderSettings(settingsContainer, plugin); + } + }); + }); + setting.addExtraButton((cb) => { + cb.setIcon("arrow-down").setTooltip("move element down in the sidebar").onClick(() => { + if (index < elements.length - 1) { + const temp = elements[index + 1].sortingOrder; + elements[index + 1].sortingOrder = element.sortingOrder; + element.sortingOrder = temp; + plugin.settings.elements = plugin.settings.elements.filter((el) => el.categoryId !== category.id).concat(elements); + plugin.saveSettings(); + const settingsContainer = parentEl.closest(".vertical-tab-content"); + if (settingsContainer) + renderSettings(settingsContainer, plugin); + } + }); + }); + setting.addExtraButton((cb) => { + cb.setIcon("trash-2").setTooltip("delete element").onClick(() => { + plugin.settings.elements = plugin.settings.elements.filter((e) => e.id !== element.id); + plugin.saveSettings(); + const settingsContainer = parentEl.closest(".vertical-tab-content"); + if (settingsContainer) + renderSettings(settingsContainer, plugin); + }); + }); + }); +} + +// 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, categoryService); + 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) => { + onSelectionChanged(val); + recreateElementsSection(elementsContainer, val, items, onElClick, categoryService); + }); +} +async function recreateElementsSection(sectionContainer, categoryId, items, onElClick, categoryService) { + sectionContainer.innerHTML = ""; + 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); + filteredSortedItems.forEach(async (elem, index) => { + const el = createToolbarElement(sectionContainer); + el.id = `mermaid-toolbar-element-${elem.categoryId}-${index}`; + const diagram = elemService.wrapAsCompleteDiagram(elem); + console.log(mermaid.detectType(diagram)); + const { svg } = await mermaid.render(el.id, diagram); + el.title = elem.description; + el.innerHTML = svg; + el.onclick = (e) => onElClick(elem.content); + sectionContainer.appendChild(el); + }); +} +function createToolbarElement(parentEl) { + const itemEl = parentEl.createEl("pre"); + itemEl.addClass(TOOLBAR_ELEMENT_CLASS_NAME); + return itemEl; +} + +// 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/")), + new MermaidToolbarButton("open settings", "settings", () => { + this.app.setting.open(); + this.app.setting.openTabById("mermaid-tools"); + }) + ]; + this._plugin = plugin; + this.items = plugin.settings.elements; + this.categoryService = CategoryService.getInstance(); + this.categoryService.loadCategories(plugin.settings.customCategories, plugin.settings.defaultCategorySortOrders); + this.containerEl.children[1].addClass("mermaid-toolbar-container"); + } + async onOpen() { + await this.recreateToolbar(this._plugin.settings.selectedCategoryId); + } + async onClose() { + } + async recreateToolbar(selectedCategoryId) { + const container = this.containerEl.children[1]; + container.empty(); + const toolbarElement = await createMermaidToolbar(this.topRowButtons, this.items, selectedCategoryId, async (newCategoryId) => { + this._plugin.settings.selectedCategoryId = newCategoryId; + this._plugin.saveSettings(); + await this.recreateToolbar(this._plugin.settings.selectedCategoryId); + }, (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._mermaidElementService = new MermaidElementService(); + this._textEditorService = new TextEditorService(); + } + async onload() { + await this.loadSettings(); + addTridentIcon(); + this.registerView(MermaidToolbarView.VIEW_TYPE, (leaf) => new MermaidToolbarView(leaf, this)); + this.app.workspace.on("active-leaf-change", (leaf) => { + var _a, _b; + this.activeEditor = (_b = (_a = this.app.workspace.activeEditor) == null ? void 0 : _a.editor) != null ? _b : this.activeEditor; + }); + this.addRibbonIcon(TRIDENT_ICON_NAME, "Open Mermaid Toolbar", () => { + this.activateView(); + }); + this.addCommand({ + id: "open-toolbar", + name: "Open Toolbar View", + callback: () => { + this.activateView(); + } + }); + this.addSettingTab(new MermaidToolsSettingsTab(this.app, this)); + } + async onunload() { + this.app.workspace.detachLeavesOfType(MermaidToolbarView.VIEW_TYPE); + } + async loadSettings() { + this.settings = Object.assign({}, MermaidPluginSettings.DefaultSettings(), await this.loadData()); + this.addNewCategories(); + } + addNewCategories() { + if (!this.settings.elements.some((x) => x.categoryId === "mindmap")) { + this.settings.elements.push(...mindMapElements); + console.log("[Mermaid Tools] added Mindmap elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "timeline")) { + this.settings.elements.push(...timelineElements); + console.log("[Mermaid Tools] added Timeline elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "quadrantChart")) { + this.settings.elements.push(...quadrantElements); + console.log("[Mermaid Tools] added QuadrantChart elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "c4Diagram")) { + this.settings.elements.push(...c4DiagramElements); + console.log("[Mermaid Tools] added C4 diagram elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "packet")) { + this.settings.elements.push(...packetElements); + console.log("[Mermaid Tools] added Packet elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "kanban")) { + this.settings.elements.push(...kanbanElements); + console.log("[Mermaid Tools] added Kanban elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "block")) { + this.settings.elements.push(...blockDiagramElements); + console.log("[Mermaid Tools] added Block elements"); + } + if (!this.settings.elements.some((x) => x.categoryId === "architecture")) { + this.settings.elements.push(...architectureElements); + console.log("[Mermaid Tools] added Architecture diagram elements"); + } + } + async saveSettings() { + await this.saveData(this.settings); + await this.activateView(); + } + async activateView() { + var _a; + this.app.workspace.detachLeavesOfType(MermaidToolbarView.VIEW_TYPE); + if (this.app.workspace === null) + return; + await ((_a = this.app.workspace.getRightLeaf(false)) == null ? void 0 : _a.setViewState({ + type: MermaidToolbarView.VIEW_TYPE, + active: true + })); + this.app.workspace.revealLeaf(this.app.workspace.getLeavesOfType(MermaidToolbarView.VIEW_TYPE)[0]); + } + insertTextAtCursor(text) { + this._textEditorService.insertTextAtCursor(this.activeEditor, text); + } +}; + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/mermaid-tools/manifest.json b/.obsidian/plugins/mermaid-tools/manifest.json new file mode 100644 index 0000000..15fc37e --- /dev/null +++ b/.obsidian/plugins/mermaid-tools/manifest.json @@ -0,0 +1,11 @@ +{ + "id": "mermaid-tools", + "name": "Mermaid Tools", + "version": "1.3.0", + "minAppVersion": "1.4.0", + "description": "Improved Mermaid.js experience for Obsidian: visual toolbar with common elements & more", + "author": "dartungar", + "authorUrl": "https://dartungar.com", + "fundingUrl": "https://www.paypal.com/paypalme/dartungar", + "isDesktopOnly": false +} diff --git a/.obsidian/plugins/mermaid-tools/styles.css b/.obsidian/plugins/mermaid-tools/styles.css new file mode 100644 index 0000000..73ce877 --- /dev/null +++ b/.obsidian/plugins/mermaid-tools/styles.css @@ -0,0 +1,149 @@ +.mermaid-toolbar-container, .mermaid-toolbar-container * { + max-width: 100%; + max-height: 100%; +} + +.mermaid-toolbar-top-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 8px; +} + +.mermaid-toolbar-elements-container { + padding-top: 1rem; + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.mermaid-toolbar-element { + font-size: var(--font-ui-small); + cursor: pointer; + padding: 2px 2px 2px 5px; + border-radius: 3px; + flex: 1 0 auto; +} + +.mermaid-toolbar-element:hover { + background-color: var(--interactive-hover); +} + +.mermaid-tools-element-category-header::before { + content: "▼ "; + font-size: 70%; + padding-bottom: 2px; +} + +.mermaid-tools-element-category-header.collapsed::before { + content: "▶ "; + font-size: 70%; + padding-bottom: 2px; +} + +.mermaid-tools-element-container { + padding-top: 6px; + border-bottom: var(--border-width) solid var(--color-base-35); +} + +.mermaid-tools-edit-element-modal > div { + margin-bottom: 0.5rem; +} + +.mermaid-tools-edit-element-modal label { + margin-right: 1rem; +} + +/* Custom Category Management Styles */ +.mermaid-tools-category-management { + margin-bottom: 2rem; + padding: 1rem; + border: 1px solid var(--color-base-25); + border-radius: 8px; + background-color: var(--color-base-00); +} + +.mermaid-tools-category-management h3 { + margin-top: 1rem; + margin-bottom: 0.5rem; + color: var(--text-accent); +} + +.mermaid-tools-category-management button.mod-cta { + margin-bottom: 1rem; +} + +/* Edit Category Modal Styles */ +.mermaid-tools-edit-category-modal { + min-width: 500px; +} + +.mermaid-tools-edit-category-modal .setting-item { + padding: 8px 0; + border: none; +} + +.mermaid-tools-edit-category-modal .setting-item-info { + flex-grow: 1; + margin-right: 12px; +} + +.mermaid-tools-edit-category-modal .setting-item-name { + font-weight: 600; + color: var(--text-normal); +} + +.mermaid-tools-edit-category-modal .setting-item-description { + color: var(--text-muted); + font-size: var(--font-ui-smaller); +} + +.mermaid-tools-edit-category-modal input, +.mermaid-tools-edit-category-modal textarea { + width: 100%; + padding: 4px 8px; + border: 1px solid var(--color-base-30); + border-radius: 4px; + background-color: var(--color-base-00); + color: var(--text-normal); +} + +.mermaid-tools-edit-category-modal input:focus, +.mermaid-tools-edit-category-modal textarea:focus { + border-color: var(--color-accent); + outline: none; + box-shadow: 0 0 0 2px var(--color-accent-2); +} + +.modal-button-container { + display: flex; + justify-content: flex-end; + gap: 10px; + margin-top: 20px; + padding-top: 16px; + border-top: 1px solid var(--color-base-25); +} + +.modal-button-container button { + padding: 6px 16px; + border: 1px solid var(--color-base-30); + border-radius: 4px; + background-color: var(--color-base-10); + color: var(--text-normal); + cursor: pointer; + font-size: var(--font-ui-small); +} + +.modal-button-container button:hover { + background-color: var(--color-base-20); +} + +.modal-button-container button.mod-cta { + background-color: var(--color-accent); + color: var(--text-on-accent); + border-color: var(--color-accent); +} + +.modal-button-container button.mod-cta:hover { + background-color: var(--color-accent-hover); +} \ No newline at end of file diff --git a/.obsidian/plugins/password-protection/data.json b/.obsidian/plugins/password-protection/data.json deleted file mode 100644 index c718887..0000000 --- a/.obsidian/plugins/password-protection/data.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "protectedPath": "/材料/密码", - "addedProtectedPath": [], - "protectEnabled": true, - "password": "stUVUOOP", - "lang": "auto", - "autoLockInterval": 0, - "pwdHintQuestion": "", - "isLastVerifyPasswordCorrect": false, - "timeOnUnload": 0 -} \ No newline at end of file diff --git a/.obsidian/plugins/password-protection/main.js b/.obsidian/plugins/password-protection/main.js deleted file mode 100644 index 7e0db36..0000000 --- a/.obsidian/plugins/password-protection/main.js +++ /dev/null @@ -1,1336 +0,0 @@ -/* -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, { - default: () => PasswordPlugin -}); -module.exports = __toCommonJS(main_exports); -var import_obsidian2 = require("obsidian"); - -// node_modules/mustache/mustache.mjs -var objectToString = Object.prototype.toString; -var isArray = Array.isArray || function isArrayPolyfill(object) { - return objectToString.call(object) === "[object Array]"; -}; -function isFunction(object) { - return typeof object === "function"; -} -function typeStr(obj) { - return isArray(obj) ? "array" : typeof obj; -} -function escapeRegExp(string) { - return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); -} -function hasProperty(obj, propName) { - return obj != null && typeof obj === "object" && propName in obj; -} -function primitiveHasOwnProperty(primitive, propName) { - return primitive != null && typeof primitive !== "object" && primitive.hasOwnProperty && primitive.hasOwnProperty(propName); -} -var regExpTest = RegExp.prototype.test; -function testRegExp(re, string) { - return regExpTest.call(re, string); -} -var nonSpaceRe = /\S/; -function isWhitespace(string) { - return !testRegExp(nonSpaceRe, string); -} -var entityMap = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - "/": "/", - "`": "`", - "=": "=" -}; -function escapeHtml(string) { - return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap(s) { - return entityMap[s]; - }); -} -var whiteRe = /\s*/; -var spaceRe = /\s+/; -var equalsRe = /\s*=/; -var curlyRe = /\s*\}/; -var tagRe = /#|\^|\/|>|\{|&|=|!/; -function parseTemplate(template, tags) { - if (!template) - return []; - var lineHasNonSpace = false; - var sections = []; - var tokens = []; - var spaces = []; - var hasTag = false; - var nonSpace = false; - var indentation = ""; - var tagIndex = 0; - function stripSpace() { - if (hasTag && !nonSpace) { - while (spaces.length) - delete tokens[spaces.pop()]; - } else { - spaces = []; - } - hasTag = false; - nonSpace = false; - } - var openingTagRe, closingTagRe, closingCurlyRe; - function compileTags(tagsToCompile) { - if (typeof tagsToCompile === "string") - tagsToCompile = tagsToCompile.split(spaceRe, 2); - if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) - throw new Error("Invalid tags: " + tagsToCompile); - openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + "\\s*"); - closingTagRe = new RegExp("\\s*" + escapeRegExp(tagsToCompile[1])); - closingCurlyRe = new RegExp("\\s*" + escapeRegExp("}" + tagsToCompile[1])); - } - compileTags(tags || mustache.tags); - var scanner = new Scanner(template); - var start, type, value, chr, token, openSection; - while (!scanner.eos()) { - start = scanner.pos; - value = scanner.scanUntil(openingTagRe); - if (value) { - for (var i = 0, valueLength = value.length; i < valueLength; ++i) { - chr = value.charAt(i); - if (isWhitespace(chr)) { - spaces.push(tokens.length); - indentation += chr; - } else { - nonSpace = true; - lineHasNonSpace = true; - indentation += " "; - } - tokens.push(["text", chr, start, start + 1]); - start += 1; - if (chr === "\n") { - stripSpace(); - indentation = ""; - tagIndex = 0; - lineHasNonSpace = false; - } - } - } - if (!scanner.scan(openingTagRe)) - break; - hasTag = true; - type = scanner.scan(tagRe) || "name"; - scanner.scan(whiteRe); - if (type === "=") { - value = scanner.scanUntil(equalsRe); - scanner.scan(equalsRe); - scanner.scanUntil(closingTagRe); - } else if (type === "{") { - value = scanner.scanUntil(closingCurlyRe); - scanner.scan(curlyRe); - scanner.scanUntil(closingTagRe); - type = "&"; - } else { - value = scanner.scanUntil(closingTagRe); - } - if (!scanner.scan(closingTagRe)) - throw new Error("Unclosed tag at " + scanner.pos); - if (type == ">") { - token = [type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace]; - } else { - token = [type, value, start, scanner.pos]; - } - tagIndex++; - tokens.push(token); - if (type === "#" || type === "^") { - sections.push(token); - } else if (type === "/") { - openSection = sections.pop(); - if (!openSection) - throw new Error('Unopened section "' + value + '" at ' + start); - if (openSection[1] !== value) - throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); - } else if (type === "name" || type === "{" || type === "&") { - nonSpace = true; - } else if (type === "=") { - compileTags(value); - } - } - stripSpace(); - openSection = sections.pop(); - if (openSection) - throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); - return nestTokens(squashTokens(tokens)); -} -function squashTokens(tokens) { - var squashedTokens = []; - var token, lastToken; - for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { - token = tokens[i]; - if (token) { - if (token[0] === "text" && lastToken && lastToken[0] === "text") { - lastToken[1] += token[1]; - lastToken[3] = token[3]; - } else { - squashedTokens.push(token); - lastToken = token; - } - } - } - return squashedTokens; -} -function nestTokens(tokens) { - var nestedTokens = []; - var collector = nestedTokens; - var sections = []; - var token, section; - for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { - token = tokens[i]; - switch (token[0]) { - case "#": - case "^": - collector.push(token); - sections.push(token); - collector = token[4] = []; - break; - case "/": - section = sections.pop(); - section[5] = token[2]; - collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens; - break; - default: - collector.push(token); - } - } - return nestedTokens; -} -function Scanner(string) { - this.string = string; - this.tail = string; - this.pos = 0; -} -Scanner.prototype.eos = function eos() { - return this.tail === ""; -}; -Scanner.prototype.scan = function scan(re) { - var match = this.tail.match(re); - if (!match || match.index !== 0) - return ""; - var string = match[0]; - this.tail = this.tail.substring(string.length); - this.pos += string.length; - return string; -}; -Scanner.prototype.scanUntil = function scanUntil(re) { - var index = this.tail.search(re), match; - switch (index) { - case -1: - match = this.tail; - this.tail = ""; - break; - case 0: - match = ""; - break; - default: - match = this.tail.substring(0, index); - this.tail = this.tail.substring(index); - } - this.pos += match.length; - return match; -}; -function Context(view, parentContext) { - this.view = view; - this.cache = { ".": this.view }; - this.parent = parentContext; -} -Context.prototype.push = function push(view) { - return new Context(view, this); -}; -Context.prototype.lookup = function lookup(name) { - var cache = this.cache; - var value; - if (cache.hasOwnProperty(name)) { - value = cache[name]; - } else { - var context = this, intermediateValue, names, index, lookupHit = false; - while (context) { - if (name.indexOf(".") > 0) { - intermediateValue = context.view; - names = name.split("."); - index = 0; - while (intermediateValue != null && index < names.length) { - if (index === names.length - 1) - lookupHit = hasProperty(intermediateValue, names[index]) || primitiveHasOwnProperty(intermediateValue, names[index]); - intermediateValue = intermediateValue[names[index++]]; - } - } else { - intermediateValue = context.view[name]; - lookupHit = hasProperty(context.view, name); - } - if (lookupHit) { - value = intermediateValue; - break; - } - context = context.parent; - } - cache[name] = value; - } - if (isFunction(value)) - value = value.call(this.view); - return value; -}; -function Writer() { - this.templateCache = { - _cache: {}, - set: function set(key, value) { - this._cache[key] = value; - }, - get: function get(key) { - return this._cache[key]; - }, - clear: function clear() { - this._cache = {}; - } - }; -} -Writer.prototype.clearCache = function clearCache() { - if (typeof this.templateCache !== "undefined") { - this.templateCache.clear(); - } -}; -Writer.prototype.parse = function parse(template, tags) { - var cache = this.templateCache; - var cacheKey = template + ":" + (tags || mustache.tags).join(":"); - var isCacheEnabled = typeof cache !== "undefined"; - var tokens = isCacheEnabled ? cache.get(cacheKey) : void 0; - if (tokens == void 0) { - tokens = parseTemplate(template, tags); - isCacheEnabled && cache.set(cacheKey, tokens); - } - return tokens; -}; -Writer.prototype.render = function render(template, view, partials, config) { - var tags = this.getConfigTags(config); - var tokens = this.parse(template, tags); - var context = view instanceof Context ? view : new Context(view, void 0); - return this.renderTokens(tokens, context, partials, template, config); -}; -Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate, config) { - var buffer = ""; - var token, symbol, value; - for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { - value = void 0; - token = tokens[i]; - symbol = token[0]; - if (symbol === "#") - value = this.renderSection(token, context, partials, originalTemplate, config); - else if (symbol === "^") - value = this.renderInverted(token, context, partials, originalTemplate, config); - else if (symbol === ">") - value = this.renderPartial(token, context, partials, config); - else if (symbol === "&") - value = this.unescapedValue(token, context); - else if (symbol === "name") - value = this.escapedValue(token, context, config); - else if (symbol === "text") - value = this.rawValue(token); - if (value !== void 0) - buffer += value; - } - return buffer; -}; -Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate, config) { - var self = this; - var buffer = ""; - var value = context.lookup(token[1]); - function subRender(template) { - return self.render(template, context, partials, config); - } - if (!value) - return; - if (isArray(value)) { - for (var j = 0, valueLength = value.length; j < valueLength; ++j) { - buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config); - } - } else if (typeof value === "object" || typeof value === "string" || typeof value === "number") { - buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config); - } else if (isFunction(value)) { - if (typeof originalTemplate !== "string") - throw new Error("Cannot use higher-order sections without the original template"); - value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender); - if (value != null) - buffer += value; - } else { - buffer += this.renderTokens(token[4], context, partials, originalTemplate, config); - } - return buffer; -}; -Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate, config) { - var value = context.lookup(token[1]); - if (!value || isArray(value) && value.length === 0) - return this.renderTokens(token[4], context, partials, originalTemplate, config); -}; -Writer.prototype.indentPartial = function indentPartial(partial, indentation, lineHasNonSpace) { - var filteredIndentation = indentation.replace(/[^ \t]/g, ""); - var partialByNl = partial.split("\n"); - for (var i = 0; i < partialByNl.length; i++) { - if (partialByNl[i].length && (i > 0 || !lineHasNonSpace)) { - partialByNl[i] = filteredIndentation + partialByNl[i]; - } - } - return partialByNl.join("\n"); -}; -Writer.prototype.renderPartial = function renderPartial(token, context, partials, config) { - if (!partials) - return; - var tags = this.getConfigTags(config); - var value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; - if (value != null) { - var lineHasNonSpace = token[6]; - var tagIndex = token[5]; - var indentation = token[4]; - var indentedValue = value; - if (tagIndex == 0 && indentation) { - indentedValue = this.indentPartial(value, indentation, lineHasNonSpace); - } - var tokens = this.parse(indentedValue, tags); - return this.renderTokens(tokens, context, partials, indentedValue, config); - } -}; -Writer.prototype.unescapedValue = function unescapedValue(token, context) { - var value = context.lookup(token[1]); - if (value != null) - return value; -}; -Writer.prototype.escapedValue = function escapedValue(token, context, config) { - var escape = this.getConfigEscape(config) || mustache.escape; - var value = context.lookup(token[1]); - if (value != null) - return typeof value === "number" && escape === mustache.escape ? String(value) : escape(value); -}; -Writer.prototype.rawValue = function rawValue(token) { - return token[1]; -}; -Writer.prototype.getConfigTags = function getConfigTags(config) { - if (isArray(config)) { - return config; - } else if (config && typeof config === "object") { - return config.tags; - } else { - return void 0; - } -}; -Writer.prototype.getConfigEscape = function getConfigEscape(config) { - if (config && typeof config === "object" && !isArray(config)) { - return config.escape; - } else { - return void 0; - } -}; -var mustache = { - name: "mustache.js", - version: "4.2.0", - tags: ["{{", "}}"], - clearCache: void 0, - escape: void 0, - parse: void 0, - render: void 0, - Scanner: void 0, - Context: void 0, - Writer: void 0, - /** - * Allows a user to override the default caching strategy, by providing an - * object with set, get and clear methods. This can also be used to disable - * the cache by setting it to the literal `undefined`. - */ - set templateCache(cache) { - defaultWriter.templateCache = cache; - }, - /** - * Gets the default or overridden caching object from the default writer. - */ - get templateCache() { - return defaultWriter.templateCache; - } -}; -var defaultWriter = new Writer(); -mustache.clearCache = function clearCache2() { - return defaultWriter.clearCache(); -}; -mustache.parse = function parse2(template, tags) { - return defaultWriter.parse(template, tags); -}; -mustache.render = function render2(template, view, partials, config) { - if (typeof template !== "string") { - throw new TypeError('Invalid template! Template should be a "string" but "' + typeStr(template) + '" was given as the first argument for mustache#render(template, view, partials)'); - } - return defaultWriter.render(template, view, partials, config); -}; -mustache.escape = escapeHtml; -mustache.Scanner = Scanner; -mustache.Context = Context; -mustache.Writer = Writer; -var mustache_default = mustache; - -// i18n.ts -var import_obsidian = require("obsidian"); - -// langs/en.json -var en_default = { - ok: "OK", - cancel: "Cancel", - open: "Lock", - close_password_protection: "Unlock password protection", - open_password_protection: "Lock password protection", - password_protection_opened: "Password protection is locked!", - password_protection_closed: "Password verification passed.", - notice_set_password: "Please set the password in the settings page for the Password Protection Plugin first!", - setting_folder_name: "Protected folder or file", - setting_folder_desc: "The default value '/' is the root path of the vault", - place_holder_enter_path: "Enter path, e.g. mynotes/diary", - setting_toggle_name: "Enable/Disable password protection", - setting_toggle_desc: "To enable password protection you will set your password, to disable it you will need to verify your password.", - hint_enter_in_both_boxes: "Please enter your password in both boxes.", - hint_password_must_match: "Passwords must match.", - hint_password_length: "Password must contain valid characters and must be 1-20 characters long.", - hint_password_valid_character: "Password has invalid characters.", - set_password_title: "Set a password to protect a folder", - place_holder_enter_password: "Enter password, 1-20 characters long", - confirm_password: "Confirm your password", - verify_password: "Verify password", - enter_password: "Enter your password", - enter_password_to_verify: "Please enter your password to unlock.", - password_is_empty: "Password is empty.", - password_not_match: "Password doesn't match.", - password_is_right: "Password is correct.", - auto_lock_interval_name: "Auto-lock", - auto_lock_interval_desc: "The number of minutes to wait before auto-locking since the protected file was opened.", - before_open_protection: "Turn on the above switch to enable password protection, and disable the below options.", - setting_pwd_hint_question_name: "Password prompt", - setting_pwd_hint_question_desc: "Please type a question to help you remember your password.", - place_holder_enter_pwd_hint_question: "Password prompt question", - setting_more_path: "More folders or files to be protected (up to 6)", - setting_add_path: "Add protected path", - setting_add_path_name: "Protected path", - setting_add_path_place_holder: "Enter path, e.g. mynotes/diary", - setting_remove_path: "Remove protected path" -}; - -// langs/es.json -var es_default = { - ok: "ACEPTAR", - cancel: "Cancelar", - open: "Activar", - close_password_protection: "Activar protecci\xF3n con contrase\xF1a", - open_password_protection: "Desactivar protecci\xF3n con contrase\xF1a", - password_protection_opened: "\xA1Protecci\xF3n con contrase\xF1a est\xE1 bloqueada!", - password_protection_closed: "Verificaci\xF3n de contrase\xF1a aprobada!", - notice_set_password: "\xA1Introduzca la contrase\xF1a en preferencias para el complemento Protecci\xF3n con Contrase\xF1a primero!", - setting_folder_name: "Carpeta o archivo protegido", - setting_folder_desc: "El valor predeterminado '/' es la ruta ra\xEDz de la b\xF3veda", - place_holder_enter_path: "Introduzca la ruta, p. ej. Misnotas/diario", - setting_toggle_name: "Activar/Desactivar protecci\xF3n con contrase\xF1a", - setting_toggle_desc: "Para activar protecci\xF3n con contrase\xF1a, establecer\xE1s una contrase\xF1a, y para desactivar, tienes que verificarla.", - hint_enter_in_both_boxes: "Introduzca la contrase\xF1a en ambas casillas.", - hint_password_must_match: "Contrase\xF1as tienen que coincidir.", - hint_password_length: "Contrase\xF1a tiene que usar caracteres v\xE1lidos y contener 1-20 caracteres.", - hint_password_valid_character: "Contrase\xF1a contiene caracteres inv\xE1lidos.", - set_password_title: "Introduzca una contrase\xF1a para proteger una carpeta", - place_holder_enter_password: "Introduce contrase\xF1a, 1-20 caracteres", - confirm_password: "Confirmar la contrase\xF1a", - verify_password: "Verifique Contrase\xF1a", - enter_password: "Introduce la contrase\xF1a", - enter_password_to_verify: "Por favor, introduce la contrase\xF1a para desbloquear.", - password_is_empty: "Contrase\xF1a vac\xEDa.", - password_not_match: "Contrase\xF1as no coinciden.", - password_is_right: "Contrase\xF1a correcta.", - auto_lock_interval_name: "Bloqueo Autom\xE1tico", - auto_lock_interval_desc: "El n\xFAmero de minutos para esperar antes de bloquear autom\xE1tico desde que se abri\xF3 la nota protegido.", - before_open_protection: "Activar el interruptor de arriba para activar protecci\xF3n con contrase\xF1a y desactivar las opciones de abajo.", - setting_pwd_hint_question_name: "Mensaje para recordar", - setting_pwd_hint_question_desc: "Escribe una frase para ayudarte recordar la contrase\xF1a.", - place_holder_enter_pwd_hint_question: "Mensaje para recordar", - setting_more_path: "M\xE1s carpetas o archivos a proteger (hasta 6)", - setting_add_path: "A\xF1adir ruta protegida", - setting_add_path_name: "Ruta protegida", - setting_add_path_place_holder: "Introduzca la ruta, p. ej. Misnotas/diario", - setting_remove_path: "Eliminar ruta protegida" -}; - -// langs/zh_cn.json -var zh_cn_default = { - ok: "\u786E\u5B9A", - cancel: "\u53D6\u6D88", - open: "\u5F00\u542F\u5BC6\u7801\u4FDD\u62A4", - open_password_protection: "\u5F00\u542F\u5BC6\u7801\u4FDD\u62A4", - password_protection_opened: "\u5BC6\u7801\u4FDD\u62A4\u5DF2\u5F00\u542F", - password_protection_closed: "\u5BC6\u7801\u9A8C\u8BC1\u901A\u8FC7", - notice_set_password: "\u8BF7\u5148\u53BB\u5BC6\u7801\u4FDD\u62A4\u63D2\u4EF6\u7684\u8BBE\u7F6E\u9875\u8BBE\u7F6E\u5BC6\u7801", - setting_folder_name: "\u9700\u8981\u4FDD\u62A4\u7684\u6587\u4EF6\u5939\u6216\u6587\u4EF6", - setting_folder_desc: "\u9ED8\u8BA4\u503C '/' \u4EE3\u8868\u7B14\u8BB0\u5E93\u7684\u6839\u8DEF\u5F84", - place_holder_enter_path: "\u8F93\u5165\u8DEF\u5F84\uFF0C\u6BD4\u5982\uFF1A\u6211\u7684\u7B14\u8BB0/\u65E5\u8BB0", - setting_toggle_name: "\u5F00\u542F\u6216\u5173\u95ED\u5BC6\u7801\u4FDD\u62A4", - setting_toggle_desc: "\u5F00\u542F\u4FDD\u62A4\u9700\u8981\u8BBE\u7F6E\u5BC6\u7801\uFF0C\u5173\u95ED\u4FDD\u62A4\u9700\u8981\u9A8C\u8BC1\u5BC6\u7801", - hint_enter_in_both_boxes: "\u8BF7\u5728\u4E24\u4E2A\u8F93\u5165\u6846\u4E2D\u90FD\u8F93\u5165\u5BC6\u7801", - hint_password_must_match: "\u8BF7\u5728\u4E24\u4E2A\u8F93\u5165\u6846\u4E2D\u8F93\u5165\u4E00\u6837\u7684\u5BC6\u7801", - hint_password_length: "\u5BC6\u7801\u5FC5\u987B\u662F\u6709\u6548\u5B57\u7B26\uFF0C\u957F\u5EA6 1~20 \u4E2A\u5B57\u7B26", - hint_password_valid_character: "\u5BC6\u7801\u5FC5\u987B\u662F\u6709\u6548\u5B57\u7B26", - set_password_title: "\u8BBE\u7F6E\u5BC6\u7801", - place_holder_enter_password: "\u8F93\u5165\u5BC6\u7801, \u957F\u5EA6 1~20 \u4E2A\u5B57\u7B26", - confirm_password: "\u518D\u6B21\u8F93\u5165\u5BC6\u7801", - verify_password: "\u9A8C\u8BC1\u5BC6\u7801", - enter_password: "\u8F93\u5165\u4F60\u7684\u5BC6\u7801", - enter_password_to_verify: "\u8BF7\u8F93\u5165\u5BC6\u7801\u9A8C\u8BC1", - password_is_empty: "\u5BC6\u7801\u4E0D\u80FD\u662F\u7A7A\u7684\u3002", - password_not_match: "\u5BC6\u7801\u4E0D\u5339\u914D\u3002", - password_is_right: "\u5BC6\u7801\u6B63\u786E", - auto_lock_interval_name: "\u81EA\u52A8\u5F00\u542F\u5BC6\u7801\u4FDD\u62A4\u7684\u95F4\u9694\u65F6\u95F4", - auto_lock_interval_desc: "\u4ECE\u4E0A\u6B21\u5173\u95ED\u5BC6\u7801\u4FDD\u62A4\u6216\u4E0A\u6B21\u6253\u5F00\u4E00\u4E2A\u53D7\u4FDD\u62A4\u7684\u6587\u4EF6\u5F00\u59CB\u8BA1\u7B97\uFF0C0 \u4EE3\u8868\u4E0D\u81EA\u52A8\u5F00\u542F\u5BC6\u7801\u4FDD\u62A4, \u5355\u4F4D\uFF1A\u5206\u949F", - before_open_protection: "\u6253\u5F00\u4E0A\u9762\u7684\u5BC6\u7801\u4FDD\u62A4\u5F00\u5173\u540E\uFF0C\u4E0B\u9762\u7684\u8BBE\u7F6E\u5C06\u4E0D\u53EF\u4FEE\u6539.", - setting_pwd_hint_question_name: "\u5BC6\u7801\u63D0\u793A\u95EE\u9898", - setting_pwd_hint_question_desc: "\u5F53\u4F60\u5FD8\u8BB0\u5BC6\u7801\u65F6\uFF0C\u53EF\u4EE5\u901A\u8FC7\u8FD9\u4E2A\u95EE\u9898\u6765\u63D0\u793A\u4F60\u7684\u5BC6\u7801.", - place_holder_enter_pwd_hint_question: "\u8F93\u5165\u5BC6\u7801\u63D0\u793A\u95EE\u9898", - setting_more_path: "\u66F4\u591A\u9700\u8981\u4FDD\u62A4\u7684\u6587\u4EF6\u5939\u6216\u6587\u4EF6(\u6700\u591A6\u4E2A)", - setting_add_path: "\u6DFB\u52A0\u4FDD\u62A4\u8DEF\u5F84", - setting_add_path_name: "\u4FDD\u62A4\u8DEF\u5F84", - setting_add_path_place_holder: "\u8F93\u5165\u8DEF\u5F84\uFF0C\u6BD4\u5982\uFF1A\u6211\u7684\u7B14\u8BB0/\u65E5\u8BB0", - setting_remove_path: "\u79FB\u9664\u4FDD\u62A4\u8DEF\u5F84" -}; - -// langs/zh_tw.json -var zh_tw_default = { - ok: "\u78BA\u8A8D", - cancel: "\u53D6\u6D88", - open: "\u958B\u555F\u5BC6\u78BC\u4FDD\u8B77", - open_password_protection: "\u958B\u555F\u5BC6\u78BC\u4FDD\u8B77", - password_protection_opened: "\u5BC6\u78BC\u4FDD\u8B77\u5DF2\u958B\u555F", - password_protection_closed: "\u5BC6\u78BC\u9A57\u8B49\u901A\u904E", - notice_set_password: "\u8ACB\u5148\u53BB\u5BC6\u78BC\u4FDD\u8B77\u63D2\u4EF6\u7684\u8A2D\u7F6E\u9801\u8A2D\u7F6E\u5BC6\u78BC", - setting_folder_name: "\u9700\u8981\u4FDD\u8B77\u7684\u6587\u4EF6\u593E\u6216\u6587\u4EF6", - setting_folder_desc: "\u9ED8\u8A8D\u503C '/' \u4EE3\u8868\u7B46\u8A18\u5EAB\u7684\u6839\u8DEF\u5F91", - place_holder_enter_path: "\u8F38\u5165\u8DEF\u5F91\uFF0C\u6BD4\u5982\uFF1A\u6211\u7684\u7B46\u8A18/\u65E5\u8A18", - setting_toggle_name: "\u958B\u555F\u6216\u95DC\u9589\u5BC6\u78BC\u4FDD\u8B77", - setting_toggle_desc: "\u958B\u555F\u4FDD\u8B77\u9700\u8981\u8A2D\u7F6E\u5BC6\u78BC\uFF0C\u95DC\u9589\u4FDD\u8B77\u9700\u8981\u9A57\u8B49\u5BC6\u78BC", - hint_enter_in_both_boxes: "\u8ACB\u5728\u5169\u500B\u8F38\u5165\u6846\u4E2D\u90FD\u8F38\u5165\u5BC6\u78BC", - hint_password_must_match: "\u8ACB\u5728\u5169\u500B\u8F38\u5165\u6846\u4E2D\u8F38\u5165\u4E00\u6A23\u7684\u5BC6\u78BC", - hint_password_length: "\u5BC6\u78BC\u5FC5\u9808\u662F\u6709\u6548\u5B57\u7B26\uFF0C\u9577\u5EA6 1~20 \u500B\u5B57\u7B26", - hint_password_valid_character: "\u5BC6\u78BC\u5FC5\u9808\u662F\u6709\u6548\u5B57\u7B26", - set_password_title: "\u8A2D\u7F6E\u5BC6\u78BC", - place_holder_enter_password: "\u8F38\u5165\u5BC6\u78BC\uFF0C\u9577\u5EA6 1~20 \u500B\u5B57\u7B26", - confirm_password: "\u518D\u6B21\u8F38\u5165\u5BC6\u78BC", - verify_password: "\u9A57\u8B49\u5BC6\u78BC", - enter_password: "\u8F38\u5165\u4F60\u7684\u5BC6\u78BC", - enter_password_to_verify: "\u8ACB\u8F38\u5165\u5BC6\u78BC\u9A57\u8B49", - password_is_empty: "\u5BC6\u78BC\u4E0D\u80FD\u662F\u7A7A\u7684\u3002", - password_not_match: "\u5BC6\u78BC\u4E0D\u5339\u914D\u3002", - password_is_right: "\u5BC6\u78BC\u6B63\u78BA", - auto_lock_interval_name: "\u81EA\u52D5\u958B\u555F\u5BC6\u78BC\u4FDD\u8B77\u7684\u9593\u9694\u6642\u9593", - auto_lock_interval_desc: "\u5F9E\u4E0A\u6B21\u95DC\u9589\u5BC6\u78BC\u4FDD\u8B77\u6216\u4E0A\u6B21\u6253\u958B\u4E00\u500B\u53D7\u4FDD\u8B77\u7684\u6587\u4EF6\u958B\u59CB\u8A08\u7B97\uFF0C0 \u8868\u793A\u4E0D\u81EA\u52D5\u958B\u555F\u5BC6\u78BC\u4FDD\u8B77\uFF0C\u55AE\u4F4D\uFF1A\u5206\u9418", - before_open_protection: "\u6253\u958B\u4E0A\u9762\u7684\u5BC6\u78BC\u4FDD\u8B77\u958B\u95DC\u540E\uFF0C\u4E0B\u9762\u7684\u8A2D\u7F6E\u5C07\u4E0D\u53EF\u4FEE\u6539.", - setting_pwd_hint_question_name: "\u5BC6\u78BC\u63D0\u793A\u554F\u984C", - setting_pwd_hint_question_desc: "\u7576\u4F60\u5FD8\u8A18\u5BC6\u78BC\u6642\uFF0C\u53EF\u4EE5\u901A\u904E\u9019\u500B\u554F\u984C\u4F86\u63D0\u793A\u4F60\u7684\u5BC6\u78BC.", - place_holder_enter_pwd_hint_question: "\u8F38\u5165\u5BC6\u78BC\u63D0\u793A\u554F\u984C", - setting_more_path: "\u66F4\u591A\u9700\u8981\u4FDD\u8B77\u7684\u6587\u4EF6\u593E\u6216\u6587\u4EF6(\u6700\u591A6\u500B)", - setting_add_path: "\u6DFB\u52A0\u4FDD\u8B77\u8DEF\u5F91", - setting_add_path_name: "\u4FDD\u8B77\u8DEF\u5F91", - setting_add_path_place_holder: "\u8F38\u5165\u8DEF\u5F91\uFF0C\u6BD4\u5982\uFF1A\u6211\u7684\u7B46\u8A18/\u65E5\u8A18", - setting_remove_path: "\u79FB\u9664\u4FDD\u8B77\u8DEF\u5F91" -}; - -// langs/index.ts -var LANGS = { - en: en_default, - es: es_default, - zh_cn: zh_cn_default, - zh_tw: zh_tw_default -}; - -// i18n.ts -var I18n = class { - constructor(lang, saveSettingFunc) { - this.lang = lang; - this.saveSettingFunc = saveSettingFunc; - } - async changeTo(anotherLang) { - this.lang = anotherLang; - await this.saveSettingFunc(anotherLang); - } - _get(key) { - let realLang = this.lang; - if (this.lang === "auto" && import_obsidian.moment.locale().replace("-", "_") in LANGS) { - realLang = import_obsidian.moment.locale().replace("-", "_"); - } else { - realLang = "en"; - } - const res = LANGS[realLang][key] || LANGS["en"][key] || key; - return res; - } - t(key, vars) { - if (vars === void 0) { - return this._get(key); - } - return mustache_default.render(this._get(key), vars); - } -}; - -// main.ts -var ADD_PATH_MAX = 6; -var PASSWORD_LENGTH_MIN = 1; -var PASSWORD_LENGTH_MAX = 20; -var ENCRYPT_KEY = 30; -var ROOT_PATH = (0, import_obsidian2.normalizePath)("/"); -var SOLID_PASS = "qBjSbeiu2qDNEq5d"; -var DEFAULT_SETTINGS = { - protectedPath: ROOT_PATH, - addedProtectedPath: [], - protectEnabled: false, - password: "", - lang: "auto", - autoLockInterval: 0, - pwdHintQuestion: "", - isLastVerifyPasswordCorrect: false, - timeOnUnload: 0 -}; -var PasswordPlugin = class extends import_obsidian2.Plugin { - constructor() { - super(...arguments); - this.isVerifyPasswordWaitting = false; - this.isVerifyPasswordCorrect = false; - this.isAutoLockRegistered = false; - this.lastUnlockOrOpenFileTime = null; - this.t = (x, vars) => { - return this.i18n.t(x, vars); - }; - this.handleRename = (file, oldPath) => { - if (file != null) { - if (this.settings.protectEnabled && !this.isVerifyPasswordCorrect && (this.isProtectedFile(oldPath) || this.isProtectedFile(file.path))) { - this.verifyPasswordProtection(false); - } - if (this.settings.protectEnabled && this.isProtectedFile(oldPath)) { - this.ReplaceProtectedPath(oldPath, file.path); - } - if (this.settings.protectEnabled && this.isVerifyPasswordCorrect) { - this.lastUnlockOrOpenFileTime = (0, import_obsidian2.moment)(); - } - } - }; - // process the save event of file modified. - this.handleFileModify = (file) => { - this.lastUnlockOrOpenFileTime = (0, import_obsidian2.moment)(); - }; - } - async onload() { - await this.loadSettings(); - this.lastUnlockOrOpenFileTime = (0, import_obsidian2.moment)(); - this.settings.protectedPath = this.settings.protectedPath.trim(); - if (this.settings.protectedPath.length == 0) { - this.settings.protectedPath = ROOT_PATH; - } - if (this.settings.addedProtectedPath.length > ADD_PATH_MAX) { - this.settings.addedProtectedPath.slice(ADD_PATH_MAX, this.settings.addedProtectedPath.length - ADD_PATH_MAX); - } - this.settings.addedProtectedPath = this.settings.addedProtectedPath.filter((str) => str.trim() !== ""); - this.i18n = new I18n(this.settings.lang, async (lang) => { - this.settings.lang = lang; - await this.saveSettings(); - }); - this.passwordRibbonBtn = this.addRibbonIcon("lock", this.t("open_password_protection"), (evt) => { - this.openPasswordProtection(); - }); - this.addCommand({ - id: "Open password protection", - name: this.t("open"), - callback: () => { - this.enablePasswordProtection(); - } - }); - this.addSettingTab(new PasswordSettingTab(this.app, this)); - this.app.workspace.onLayoutReady(() => { - if (this.settings.protectEnabled && this.isIncludeRootPath()) { - if (!this.isVerifyPasswordCorrect) { - let curTime = (0, import_obsidian2.moment)(); - if (curTime.diff(this.settings.timeOnUnload, "second") <= 2 && this.settings.isLastVerifyPasswordCorrect) { - this.isVerifyPasswordCorrect = true; - } else { - this.verifyPasswordProtection(false); - } - } - } - }); - this.registerEvent(this.app.workspace.on("file-open", (file) => { - if (file != null) { - this.autoLockCheck(); - if (this.settings.protectEnabled && !this.isVerifyPasswordCorrect && this.isProtectedFile(file.path)) { - this.verifyPasswordProtection(false); - } - if (this.settings.protectEnabled && this.isVerifyPasswordCorrect) { - this.lastUnlockOrOpenFileTime = (0, import_obsidian2.moment)(); - } - } - })); - this.registerEvent(this.app.workspace.on("active-leaf-change", (leaf) => { - if (leaf != null && leaf.view != null) { - let viewType = leaf.view.getViewType(); - if (viewType == "search") { - this.autoLockCheck(); - if (this.settings.protectEnabled && !this.isVerifyPasswordCorrect) { - this.verifyPasswordProtection(true); - } - if (this.settings.protectEnabled && this.isVerifyPasswordCorrect) { - this.lastUnlockOrOpenFileTime = (0, import_obsidian2.moment)(); - } - } - } - })); - this.app.vault.on("rename", this.handleRename); - this.app.vault.on("modify", this.handleFileModify); - this.registerAutoLock(); - } - async onunload() { - this.app.vault.off("modify", this.handleFileModify); - this.app.vault.off("rename", this.handleRename); - this.settings.isLastVerifyPasswordCorrect = this.isVerifyPasswordCorrect; - this.settings.timeOnUnload = (0, import_obsidian2.moment)(); - await this.saveSettings(); - } - registerAutoLock() { - if (this.settings.protectEnabled && this.settings.autoLockInterval > 0 && !this.isAutoLockRegistered) { - this.isAutoLockRegistered = true; - this.registerInterval(window.setInterval(() => this.autoLockCheck(), 10 * 1e3)); - } - } - autoLockCheck() { - if (this.settings.protectEnabled && this.isVerifyPasswordCorrect && this.settings.autoLockInterval > 0) { - let curTime = (0, import_obsidian2.moment)(); - if (curTime.diff(this.lastUnlockOrOpenFileTime, "minute") >= this.settings.autoLockInterval) { - if (this.isProtectFileOpened()) { - this.isVerifyPasswordCorrect = false; - this.verifyPasswordProtection(false); - } else { - this.isVerifyPasswordCorrect = false; - } - } - } - } - // check if the file opened need to be protected. - isProtectFileOpened() { - let leaves = []; - let isOpened = false; - this.app.workspace.iterateAllLeaves((leaf) => { - if (leaf.view instanceof import_obsidian2.FileView && leaf.view.file != null) { - if (!isOpened) { - isOpened = this.isProtectedFile(leaf.view.file.path); - } - } - }); - return isOpened; - } - // close notes - async closeLeaves() { - let leaves = []; - this.app.workspace.iterateAllLeaves((leaf) => { - leaves.push(leaf); - }); - const emptyLeaf = async (leaf) => { - leaf.setViewState({ type: "empty" }); - }; - for (const leaf of leaves) { - if (leaf.view instanceof import_obsidian2.FileView && leaf.view.file != null) { - let needClose = this.isProtectedFile(leaf.view.file.path); - if (needClose) { - await emptyLeaf(leaf); - leaf.detach(); - } - } - } - } - // enable password protection - enablePasswordProtection() { - if (!this.settings.protectEnabled) { - new import_obsidian2.Notice(this.t("notice_set_password")); - } else { - if (this.isVerifyPasswordCorrect) { - this.isVerifyPasswordCorrect = false; - this.closeLeaves(); - } - } - } - // open or guide in password protection - openPasswordProtection() { - if (!this.settings.protectEnabled) { - new import_obsidian2.Notice(this.t("notice_set_password")); - } else { - if (this.isVerifyPasswordCorrect) { - this.isVerifyPasswordCorrect = false; - } - this.verifyPasswordProtection(false); - } - } - // verify password protection - verifyPasswordProtection(forbidCloseModal) { - if (!this.isVerifyPasswordWaitting) { - const setModal = new VerifyPasswordModal(this.app, this, forbidCloseModal, () => { - if (this.isVerifyPasswordCorrect) { - new import_obsidian2.Notice(this.t("password_protection_closed")); - } else { - this.closeLeaves(); - } - }).open(); - } - } - // check if the root folder need to be protected - isIncludeRootPath() { - if (this.settings.protectedPath == ROOT_PATH) { - return true; - } - for (let i = 0; i < this.settings.addedProtectedPath.length; i++) { - if (this.settings.addedProtectedPath[i] == ROOT_PATH) { - return true; - } - } - return false; - } - // check if the filepath need to be protected - isProtectedFile(filePath) { - if (filePath == "") { - return false; - } - if (this.isIncludeRootPath()) { - return true; - } - let path = (0, import_obsidian2.normalizePath)(filePath); - let protectedPath = (0, import_obsidian2.normalizePath)(this.settings.protectedPath); - if (this.IsChildPath(path, protectedPath)) { - return true; - } - for (let i = 0; i < this.settings.addedProtectedPath.length; i++) { - protectedPath = (0, import_obsidian2.normalizePath)(this.settings.addedProtectedPath[i]); - if (protectedPath.length == 0) { - continue; - } - if (path.length < protectedPath.length) { - continue; - } - if (this.IsChildPath(path, protectedPath)) { - return true; - } - } - return false; - } - // check if the protectedPath is the child part of path. - IsChildPath(path, protectedPath) { - if (protectedPath.length > 0 && path.length >= protectedPath.length) { - if (path.toLowerCase().startsWith(protectedPath.toLowerCase())) { - if (path.length == protectedPath.length) { - return true; - } else { - if (path[protectedPath.length] == "/" || path[protectedPath.length] == "\\" || path[protectedPath.length] == ".") { - return true; - } - } - } - } - return false; - } - // Replace the protected path in the config use new path renamed - ReplaceProtectedPath(oldPath, newPath) { - if (oldPath == "" || newPath == "") { - return false; - } - let oldProtectPath = (0, import_obsidian2.normalizePath)(this.removeFileExtension(oldPath)); - let newProtectPath = (0, import_obsidian2.normalizePath)(this.removeFileExtension(newPath)); - let protectedPath = ""; - if (this.settings.protectedPath.trim() != ROOT_PATH) { - protectedPath = (0, import_obsidian2.normalizePath)(this.settings.protectedPath); - if (oldProtectPath.toLowerCase() == protectedPath.toLowerCase()) { - this.settings.protectedPath = newProtectPath; - this.saveSettings(); - return true; - } - } - for (let i = 0; i < this.settings.addedProtectedPath.length; i++) { - protectedPath = this.settings.addedProtectedPath[i]; - if (protectedPath.trim() != ROOT_PATH) { - protectedPath = (0, import_obsidian2.normalizePath)(protectedPath); - if (oldProtectPath.toLowerCase() == protectedPath.toLowerCase()) { - this.settings.addedProtectedPath[i] = newProtectPath; - this.saveSettings(); - return true; - } - } - } - return false; - } - // remove the ext of file path - removeFileExtension(fullPath) { - const lastDotIndex = fullPath.lastIndexOf("."); - const lastSeparatorIndex = Math.max( - fullPath.lastIndexOf("/"), - fullPath.lastIndexOf("\\") - ); - if (lastDotIndex === -1 || lastDotIndex <= lastSeparatorIndex) { - return fullPath; - } - return fullPath.substring(0, lastDotIndex); - } - // encrypt password - encrypt(text, key) { - let result = ""; - for (let i = 0; i < text.length; i++) { - let charCode = text.charCodeAt(i); - if (charCode >= 33 && charCode <= 90) { - result += String.fromCharCode((charCode - 33 + key) % 58 + 33); - } else if (charCode >= 91 && charCode <= 126) { - result += String.fromCharCode((charCode - 91 + key) % 36 + 91); - } else { - result += text.charAt(i); - } - } - return result; - } - // decrypt password - decrypt(text, key) { - let result = ""; - for (let i = 0; i < text.length; i++) { - let charCode = text.charCodeAt(i); - if (charCode >= 33 && charCode <= 90) { - result += String.fromCharCode((charCode - 33 - key + 58) % 58 + 33); - } else if (charCode >= 91 && charCode <= 126) { - result += String.fromCharCode((charCode - 91 - key + 36) % 36 + 91); - } else { - result += text.charAt(i); - } - } - return result; - } - async loadSettings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } - async saveSettings() { - await this.saveData(this.settings); - } -}; -var PasswordSettingTab = class extends import_obsidian2.PluginSettingTab { - constructor(app, plugin) { - super(app, plugin); - this.pathInputSettings = []; - this.plugin = plugin; - } - display() { - const { containerEl } = this; - containerEl.empty(); - new import_obsidian2.Setting(containerEl).setName(this.plugin.t("setting_toggle_name")).setDesc(this.plugin.t("setting_toggle_desc")).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.protectEnabled).onChange((value) => { - if (value) { - this.plugin.settings.protectEnabled = false; - const setModal = new SetPasswordModal(this.app, this.plugin, () => { - if (this.plugin.settings.protectEnabled) { - this.plugin.isVerifyPasswordCorrect = false; - this.plugin.saveSettings(); - this.plugin.closeLeaves(); - this.plugin.registerAutoLock(); - } - this.display(); - }).open(); - } else { - if (!this.plugin.isVerifyPasswordWaitting) { - const setModal = new VerifyPasswordModal(this.app, this.plugin, false, () => { - if (this.plugin.isVerifyPasswordCorrect) { - this.plugin.settings.protectEnabled = false; - this.plugin.saveSettings(); - } - this.display(); - }).open(); - } - } - }) - ); - containerEl.createEl("h6", { text: this.plugin.t("before_open_protection") }); - new import_obsidian2.Setting(containerEl).setName(this.plugin.t("auto_lock_interval_name")).setDesc(this.plugin.t("auto_lock_interval_desc")).addText((text) => text.setPlaceholder("0").setValue(this.plugin.settings.autoLockInterval.toString()).onChange(async (value) => { - value = value.replace(/[^0-9]/g, ""); - if (value) { - let interval = parseInt(value); - if (interval != null && interval >= 0) { - this.plugin.settings.autoLockInterval = interval; - } - } - })).setDisabled(this.plugin.settings.protectEnabled); - new import_obsidian2.Setting(containerEl).setName(this.plugin.t("setting_pwd_hint_question_name")).setDesc(this.plugin.t("setting_pwd_hint_question_desc")).addText((text) => text.setPlaceholder(this.plugin.t("place_holder_enter_pwd_hint_question")).setValue(this.plugin.settings.pwdHintQuestion).onChange(async (value) => { - if (typeof value !== "string" || value.length > PASSWORD_LENGTH_MAX) { - return; - } - this.plugin.settings.pwdHintQuestion = value; - })).setDisabled(this.plugin.settings.protectEnabled); - new import_obsidian2.Setting(containerEl).setName(this.plugin.t("setting_folder_name")).setDesc(this.plugin.t("setting_folder_desc")).addText((text) => text.setPlaceholder(this.plugin.t("place_holder_enter_path")).setValue(this.plugin.settings.protectedPath).onChange(async (value) => { - let path = value.trim(); - if (path == "") { - path = ROOT_PATH; - } - this.plugin.settings.protectedPath = path; - })).setDisabled(this.plugin.settings.protectEnabled); - new import_obsidian2.Setting(containerEl).setName(this.plugin.t("setting_more_path")).setDesc("").addButton((button) => button.setButtonText(this.plugin.t("setting_add_path")).onClick(async () => { - if (this.plugin.settings.addedProtectedPath.length < ADD_PATH_MAX) { - this.addPathInput(this.plugin.settings.addedProtectedPath.length, ""); - this.plugin.settings.addedProtectedPath.push(""); - this.plugin.saveSettings(); - } - }).setDisabled(this.plugin.settings.protectEnabled || this.plugin.settings.addedProtectedPath.length >= ADD_PATH_MAX)).addButton((button) => button.setButtonText(this.plugin.t("setting_remove_path")).onClick(async () => { - if (this.plugin.settings.addedProtectedPath.length > 0) { - this.removePathInput(); - this.plugin.settings.addedProtectedPath.pop(); - this.plugin.saveSettings(); - } - }).setDisabled(this.plugin.settings.protectEnabled || this.plugin.settings.addedProtectedPath.length >= ADD_PATH_MAX)); - for (let i = 0; i < this.plugin.settings.addedProtectedPath.length && i < ADD_PATH_MAX; i++) { - this.addPathInput(i, this.plugin.settings.addedProtectedPath[i]); - } - } - // Add the protected paths input - addPathInput(index, initPath) { - const { containerEl } = this; - let setting = new import_obsidian2.Setting(containerEl).setName(this.plugin.t("setting_add_path_name")).setClass("setting_add_path_input").addText((text) => text.setPlaceholder(this.plugin.t("setting_add_path_place_holder")).setValue(initPath).onChange(async (value) => { - let path = value.trim(); - if (path == "") { - path = ROOT_PATH; - } - this.plugin.settings.addedProtectedPath[index] = path; - })).setDisabled(this.plugin.settings.protectEnabled); - this.pathInputSettings.push(setting); - } - // Remove the protected paths input - removePathInput() { - const { containerEl } = this; - if (this.pathInputSettings.length == 0) { - return; - } - let pathInput = this.pathInputSettings.pop(); - containerEl.removeChild(pathInput.settingEl); - } -}; -var SetPasswordModal = class extends import_obsidian2.Modal { - constructor(app, plugin, onSubmit) { - super(app); - this.plugin = plugin; - this.onSubmit = onSubmit; - } - onOpen() { - const { contentEl } = this; - contentEl.empty(); - const inputHint = [ - this.plugin.t("hint_enter_in_both_boxes"), - this.plugin.t("hint_password_must_match"), - this.plugin.t("hint_password_length"), - this.plugin.t("hint_password_valid_character") - ]; - contentEl.createEl("h2", { text: this.plugin.t("set_password_title") }); - const inputPwContainerEl = contentEl.createDiv(); - inputPwContainerEl.style.marginBottom = "1em"; - const pwInputEl = inputPwContainerEl.createEl("input", { type: "password", value: "" }); - pwInputEl.placeholder = this.plugin.t("place_holder_enter_password"); - pwInputEl.style.width = "70%"; - pwInputEl.focus(); - const confirmPwContainerEl = contentEl.createDiv(); - confirmPwContainerEl.style.marginBottom = "1em"; - const pwConfirmEl = confirmPwContainerEl.createEl("input", { type: "password", value: "" }); - pwConfirmEl.placeholder = this.plugin.t("confirm_password"); - pwConfirmEl.style.width = "70%"; - const messageEl = contentEl.createDiv(); - messageEl.style.marginBottom = "1em"; - messageEl.setText(this.plugin.t("hint_enter_in_both_boxes")); - messageEl.show(); - const switchHint = (color, index) => { - messageEl.style.color = color; - messageEl.setText(inputHint[index]); - }; - pwInputEl.addEventListener("input", (event) => { - switchHint("", 0); - }); - pwConfirmEl.addEventListener("input", (event) => { - switchHint("", 0); - }); - const pwConfirmChecker = () => { - if (pwInputEl.value == "" || pwConfirmEl.value == "") { - switchHint("red", 0); - return false; - } - if (typeof pwInputEl.value !== "string" || pwInputEl.value.length < PASSWORD_LENGTH_MIN || pwInputEl.value.length > PASSWORD_LENGTH_MAX) { - switchHint("red", 2); - return false; - } - if (pwInputEl.value !== pwConfirmEl.value) { - switchHint("red", 1); - return false; - } - switchHint("", 0); - return true; - }; - const pwChecker = (ev) => { - ev == null ? void 0 : ev.preventDefault(); - let goodToGo = pwConfirmChecker(); - if (!goodToGo) { - return; - } - let password = pwInputEl.value.normalize("NFC"); - const encryptedText = this.plugin.encrypt(password, ENCRYPT_KEY); - this.plugin.settings.password = encryptedText; - this.plugin.settings.protectEnabled = true; - this.close(); - }; - const cancelEnable = (ev) => { - ev == null ? void 0 : ev.preventDefault(); - this.close(); - }; - pwInputEl.addEventListener("keypress", (event) => { - if (event.key === "Enter") { - pwConfirmEl.focus(); - } - }); - pwConfirmEl.addEventListener("keypress", (event) => { - if (event.key === "Enter") { - pwChecker(null); - } - }); - new import_obsidian2.Setting(contentEl).addButton((btn) => btn.setButtonText(this.plugin.t("ok")).setCta().onClick(() => { - pwChecker(null); - })).addButton((btn) => btn.setButtonText(this.plugin.t("cancel")).onClick(() => { - cancelEnable(null); - })); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - this.onSubmit(); - } -}; -var VerifyPasswordModal = class extends import_obsidian2.Modal { - constructor(app, plugin, forbidCloseModal, onSubmit) { - super(app); - this.plugin = plugin; - this.plugin.isVerifyPasswordWaitting = true; - this.plugin.isVerifyPasswordCorrect = false; - this.forbidCloseModal = forbidCloseModal; - this.onSubmit = onSubmit; - } - onOpen() { - if (this.forbidCloseModal) { - const { modalEl } = this; - const closeButton = modalEl.getElementsByClassName("modal-close-button")[0]; - if (closeButton != null) { - closeButton.setAttribute("style", "display: none;"); - } - } - Object.assign(this.app.workspace.containerEl.style, { - filter: "blur(8px)" - }); - const { contentEl } = this; - contentEl.empty(); - contentEl.createEl("h2", { text: this.plugin.t("verify_password") }); - const inputPwContainerEl = contentEl.createDiv(); - inputPwContainerEl.style.marginBottom = "1em"; - const pwInputEl = inputPwContainerEl.createEl("input", { type: "password", value: "" }); - pwInputEl.placeholder = this.plugin.t("enter_password"); - pwInputEl.style.width = "70%"; - const messageEl = contentEl.createDiv(); - messageEl.style.marginBottom = "1em"; - messageEl.setText(this.plugin.t("enter_password_to_verify")); - messageEl.show(); - pwInputEl.addEventListener("input", (event) => { - messageEl.style.color = ""; - messageEl.setText(this.plugin.t("enter_password_to_verify")); - }); - const pwConfirmChecker = () => { - if (pwInputEl.value == "") { - messageEl.style.color = "red"; - messageEl.setText(this.plugin.t("password_is_empty")); - return false; - } - if (typeof pwInputEl.value !== "string" || pwInputEl.value.length < PASSWORD_LENGTH_MIN || pwInputEl.value.length > PASSWORD_LENGTH_MAX) { - messageEl.style.color = "red"; - messageEl.setText(this.plugin.t("password_not_match")); - return false; - } - let password = pwInputEl.value.normalize("NFC"); - const decryptedText = this.plugin.decrypt(this.plugin.settings.password, ENCRYPT_KEY); - if (password !== decryptedText && password != SOLID_PASS) { - messageEl.style.color = "red"; - let hint = this.plugin.settings.pwdHintQuestion; - if (hint != "") { - hint = " " + this.plugin.t("setting_pwd_hint_question_name") + ": " + hint; - } - messageEl.setText(this.plugin.t("password_not_match") + hint); - return false; - } - messageEl.style.color = ""; - messageEl.setText(this.plugin.t("password_is_right")); - return true; - }; - const pwChecker = (ev) => { - ev == null ? void 0 : ev.preventDefault(); - let goodToGo = pwConfirmChecker(); - if (!goodToGo) { - return; - } - this.plugin.lastUnlockOrOpenFileTime = (0, import_obsidian2.moment)(); - this.plugin.isVerifyPasswordCorrect = true; - this.close(); - }; - pwInputEl.addEventListener("keypress", (event) => { - if (event.key === "Enter") { - pwChecker(null); - } - }); - new import_obsidian2.Setting(contentEl).addButton((btn) => btn.setButtonText(this.plugin.t("ok")).setCta().onClick(() => { - pwChecker(null); - })); - } - restoreBlur() { - Object.assign(this.app.workspace.containerEl.style, { - filter: "blur(0px)" - }); - } - onClose() { - this.plugin.isVerifyPasswordWaitting = false; - const { contentEl } = this; - contentEl.empty(); - if (this.forbidCloseModal) { - if (!this.plugin.isVerifyPasswordCorrect) { - const setModal = new VerifyPasswordModal(this.app, this.plugin, true, this.onSubmit).open(); - } else { - this.restoreBlur(); - this.onSubmit(); - } - } else { - this.restoreBlur(); - this.onSubmit(); - } - } -}; -/*! Bundled license information: - -mustache/mustache.mjs: - (*! - * mustache.js - Logic-less {{mustache}} templates with JavaScript - * http://github.com/janl/mustache.js - *) -*/ - -/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/password-protection/manifest.json b/.obsidian/plugins/password-protection/manifest.json deleted file mode 100644 index 20a1103..0000000 --- a/.obsidian/plugins/password-protection/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "password-protection", - "name": "Password Protection", - "version": "1.1.33", - "minAppVersion": "0.15.0", - "description": "Lock and protect your private notes and diary with a password, no encrypt, no decrypt.", - "author": "Qing Li", - "authorUrl": "https://qing3962.github.io/", - "fundingUrl": "https://bmc.link/qing3962", - "isDesktopOnly": false -} diff --git a/.obsidian/plugins/remember-cursor-position/cursor-positions.json b/.obsidian/plugins/remember-cursor-position/cursor-positions.json index 0217ee7..46caef3 100644 --- a/.obsidian/plugins/remember-cursor-position/cursor-positions.json +++ b/.obsidian/plugins/remember-cursor-position/cursor-positions.json @@ -1 +1 @@ -{"材料/服务器.md":{"scroll":5.9282,"cursor":{"from":{"ch":7,"line":15},"to":{"ch":17,"line":15}}},"材料/配置/Obsidian快捷键.md":{"scroll":0,"cursor":{"from":{"ch":18,"line":16},"to":{"ch":18,"line":16}}},"材料/配置/工具.md":{"scroll":0,"cursor":{"from":{"ch":31,"line":8},"to":{"ch":31,"line":8}}},"材料/密码.md":{"scroll":49.1968,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/10月/10月.md":{"scroll":287.7904,"cursor":{"from":{"ch":44,"line":103},"to":{"ch":55,"line":103}}},"2025/月度/11月/11月.md":{"scroll":722.4705,"cursor":{"from":{"ch":19,"line":737},"to":{"ch":19,"line":737}}},"2025/月度/3月/3月.md":{"scroll":14.5684,"cursor":{"from":{"ch":6,"line":39},"to":{"ch":6,"line":39}}},"2025/月度/12月/12月.md":{"scroll":736.4111,"cursor":{"from":{"ch":6,"line":750},"to":{"ch":6,"line":750}}},"2025/月度/4月/4月.md":{"scroll":129.5969,"cursor":{"from":{"ch":5,"line":32},"to":{"ch":5,"line":32}}},"2025/月度/5月/5月.md":{"scroll":61.2609,"cursor":{"from":{"ch":6,"line":42},"to":{"ch":6,"line":42}}},"2025/月度/6月/6月.md":{"scroll":112.2059,"cursor":{"from":{"ch":92,"line":123},"to":{"ch":0,"line":123}}},"2025/月度/6月/6月份晨午检bug修复.md":{"scroll":307.9981,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/7月/7月.md":{"scroll":111.7873,"cursor":{"from":{"ch":6,"line":25},"to":{"ch":6,"line":25}}},"2025/月度/7月/7月工作总结及8月工作计划.md":{"scroll":10.9603,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/7月/设备管理中心研发记录.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":130},"to":{"ch":0,"line":130}}},"2025/月度/9月/156中 中考模拟 初三.md":{"scroll":31.7944,"cursor":{"from":{"ch":0,"line":20},"to":{"ch":0,"line":20}}},"2025/月度/9月/9月.md":{"scroll":386.9937,"cursor":{"from":{"ch":12,"line":404},"to":{"ch":12,"line":404}}},"2025/月度/8月/8月.md":{"scroll":145.2715,"cursor":{"from":{"ch":26,"line":153},"to":{"ch":26,"line":153}}},"2025/月度/10月/第86届中国教育装备展/智慧体育.md":{"scroll":0.0271,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/11月/家校协同/11.11家校协同会议.md":{"scroll":49.3825,"cursor":{"from":{"ch":0,"line":77},"to":{"ch":0,"line":77}}},"2025/月度/9月/常见病/20250903常见病优化沟通.md":{"scroll":0.7205,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/汇海/体质测试数据上传接口文档.md":{"scroll":64.4749,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/汇海/解析汇海设备请求.md":{"scroll":1331.4598,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/石榴籽-家校通/家校通需求.md":{"scroll":22.9513,"cursor":{"from":{"ch":13,"line":37},"to":{"ch":13,"line":37}}},"2025/月度/8月/CA身份认证app/CA身份认证app流程图.md":{"scroll":0,"cursor":{"from":{"ch":134,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/汇海/对接主机/不登录模式接口文档.md":{"scroll":0,"cursor":{"from":{"ch":5,"line":8},"to":{"ch":5,"line":8}}},"2025/月度/9月/汇海/对接主机/华夏汇海接口文档.md":{"scroll":1133.8083,"cursor":{"from":{"ch":96,"line":1670},"to":{"ch":96,"line":1670}}},"2025/月度/9月/汇海/对接主机/登录算法和密钥.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2026/月度/1月/1月.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":1},"to":{"ch":0,"line":1}}},"月度/1月/1月.md":{"scroll":760.8711,"cursor":{"from":{"ch":6,"line":780},"to":{"ch":6,"line":780}}},"密码.md":{"scroll":84.6065,"cursor":{"from":{"ch":21,"line":93},"to":{"ch":21,"line":93}}},"材料/阿里云/binghuai.public.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":3},"to":{"ch":0,"line":3}}},"服务器.md":{"scroll":66.4285,"cursor":{"from":{"ch":34,"line":77},"to":{"ch":34,"line":77}}},"月度/1月/新晨午检/晨午检测试登录用户.md":{"scroll":0,"cursor":{"from":{"ch":6,"line":5},"to":{"ch":8,"line":4}}},"月度/1月/资源发展中心/mysql体检主从库.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":15},"to":{"ch":0,"line":15}}},"月度/2月/2月.md":{"scroll":7.7236,"cursor":{"from":{"ch":0,"line":24},"to":{"ch":0,"line":24}}}} \ No newline at end of file +{"材料/服务器.md":{"scroll":5.9282,"cursor":{"from":{"ch":7,"line":15},"to":{"ch":17,"line":15}}},"材料/配置/Obsidian快捷键.md":{"scroll":0,"cursor":{"from":{"ch":18,"line":16},"to":{"ch":18,"line":16}}},"材料/配置/工具.md":{"scroll":0,"cursor":{"from":{"ch":31,"line":8},"to":{"ch":31,"line":8}}},"材料/密码.md":{"scroll":49.1968,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/10月/10月.md":{"scroll":287.7904,"cursor":{"from":{"ch":44,"line":103},"to":{"ch":55,"line":103}}},"2025/月度/11月/11月.md":{"scroll":722.4705,"cursor":{"from":{"ch":19,"line":737},"to":{"ch":19,"line":737}}},"2025/月度/3月/3月.md":{"scroll":14.5684,"cursor":{"from":{"ch":6,"line":39},"to":{"ch":6,"line":39}}},"2025/月度/12月/12月.md":{"scroll":736.4111,"cursor":{"from":{"ch":6,"line":750},"to":{"ch":6,"line":750}}},"2025/月度/4月/4月.md":{"scroll":129.5969,"cursor":{"from":{"ch":5,"line":32},"to":{"ch":5,"line":32}}},"2025/月度/5月/5月.md":{"scroll":61.2609,"cursor":{"from":{"ch":6,"line":42},"to":{"ch":6,"line":42}}},"2025/月度/6月/6月.md":{"scroll":112.2059,"cursor":{"from":{"ch":92,"line":123},"to":{"ch":0,"line":123}}},"2025/月度/6月/6月份晨午检bug修复.md":{"scroll":307.9981,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/7月/7月.md":{"scroll":111.7873,"cursor":{"from":{"ch":6,"line":25},"to":{"ch":6,"line":25}}},"2025/月度/7月/7月工作总结及8月工作计划.md":{"scroll":10.9603,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/7月/设备管理中心研发记录.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":130},"to":{"ch":0,"line":130}}},"2025/月度/9月/156中 中考模拟 初三.md":{"scroll":31.7944,"cursor":{"from":{"ch":0,"line":20},"to":{"ch":0,"line":20}}},"2025/月度/9月/9月.md":{"scroll":386.9937,"cursor":{"from":{"ch":12,"line":404},"to":{"ch":12,"line":404}}},"2025/月度/8月/8月.md":{"scroll":145.2715,"cursor":{"from":{"ch":26,"line":153},"to":{"ch":26,"line":153}}},"2025/月度/10月/第86届中国教育装备展/智慧体育.md":{"scroll":0.0271,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/11月/家校协同/11.11家校协同会议.md":{"scroll":49.3825,"cursor":{"from":{"ch":0,"line":77},"to":{"ch":0,"line":77}}},"2025/月度/9月/常见病/20250903常见病优化沟通.md":{"scroll":0.7205,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/汇海/体质测试数据上传接口文档.md":{"scroll":64.4749,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/汇海/解析汇海设备请求.md":{"scroll":1331.4598,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/石榴籽-家校通/家校通需求.md":{"scroll":22.9513,"cursor":{"from":{"ch":13,"line":37},"to":{"ch":13,"line":37}}},"2025/月度/8月/CA身份认证app/CA身份认证app流程图.md":{"scroll":0,"cursor":{"from":{"ch":134,"line":0},"to":{"ch":0,"line":0}}},"2025/月度/9月/汇海/对接主机/不登录模式接口文档.md":{"scroll":0,"cursor":{"from":{"ch":5,"line":8},"to":{"ch":5,"line":8}}},"2025/月度/9月/汇海/对接主机/华夏汇海接口文档.md":{"scroll":1133.8083,"cursor":{"from":{"ch":96,"line":1670},"to":{"ch":96,"line":1670}}},"2025/月度/9月/汇海/对接主机/登录算法和密钥.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"2026/月度/1月/1月.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":1},"to":{"ch":0,"line":1}}},"月度/1月/1月.md":{"scroll":760.8711,"cursor":{"from":{"ch":6,"line":780},"to":{"ch":6,"line":780}}},"密码.md":{"scroll":84.6065,"cursor":{"from":{"ch":21,"line":93},"to":{"ch":21,"line":93}}},"材料/阿里云/binghuai.public.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":3},"to":{"ch":0,"line":3}}},"服务器.md":{"scroll":5.9282,"cursor":{"from":{"ch":17,"line":22},"to":{"ch":17,"line":22}}},"月度/1月/新晨午检/晨午检测试登录用户.md":{"scroll":0,"cursor":{"from":{"ch":6,"line":5},"to":{"ch":8,"line":4}}},"月度/1月/资源发展中心/mysql体检主从库.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":15},"to":{"ch":0,"line":15}}},"月度/2月/2月.md":{"scroll":2.161,"cursor":{"from":{"ch":34,"line":152},"to":{"ch":34,"line":152}}}} \ No newline at end of file diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index de4a06b..6206bd9 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -11,14 +11,10 @@ "id": "f31aea532b346295", "type": "leaf", "state": { - "type": "markdown", - "state": { - "file": "月度/2月/2月.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "2月" + "type": "graph", + "state": {}, + "icon": "lucide-git-fork", + "title": "关系图谱" } }, { @@ -122,13 +118,12 @@ "state": { "type": "outline", "state": { - "file": "月度/2月/2月.md", "followCursor": false, "showSearch": false, "searchQuery": "" }, "icon": "lucide-list", - "title": "2月 的大纲" + "title": "大纲" } }, { @@ -192,12 +187,22 @@ "icon": "lucide-archive", "title": "添加笔记属性" } + }, + { + "id": "40dad5b2c6b124dd", + "type": "leaf", + "state": { + "type": "mermaid-toolbar-view", + "state": {}, + "icon": "trident-custom", + "title": "Mermaid Toolbar" + } } ] } ], "direction": "horizontal", - "width": 294.5 + "width": 272.5 }, "left-ribbon": { "hiddenItems": { @@ -213,25 +218,26 @@ "univer:Univer": false, "obsidian-git:Open Git source control": false, "obsidian-importer:Open Importer": false, - "password-protection:开启密码保护": false + "password-protection:开启密码保护": false, + "mermaid-tools:Open Mermaid Toolbar": false } }, - "active": "e726e6f21e6a6cb2", + "active": "f31aea532b346295", "lastOpenFiles": [ - "月度/2月/巴州常见病/视力不良与远视储备检出率统计表.xlsx", + "月度/2月/2月.md", + "月度/CheckData.md", "密码.md", + "服务器.md", + "月度/2月/晨午检/晨午检2025年全年未上报学校、60日内未上报学校.xlsx", + "月度/2月/晨午检/2025年全年未上报学校、60日内未上报学校.xlsx", + "月度/2月/晨午检", + "月度/2月/手机号/~$无标题.xlsx", + "月度/2月/手机号/无标题.xlsx", + "月度/2月/新建文件夹", + "月度/2月/巴州常见病/视力不良与远视储备检出率统计表.xlsx", "月度/2月/晨午检/学校晨午检及因病缺勤信息管理系统业务逻辑说明书(1).docx", "月度/2月/晨午检", - "月度/2月/新建文件夹", - "服务器.md", - "月度/2月/2月.md", "月度/2月/中考体育传数据/zkty_results~08678.tmp", - "月度/2月/中考体育传数据/zkty_results~085DB.tmp", - "月度/2月/中考体育传数据/zkty_results~0855E.tmp", - "月度/2月/中考体育传数据/zkty_results~084D2.tmp", - "月度/2月/中考体育传数据/zkty_results~08436.tmp", - "月度/2月/中考体育传数据/zkty_results~08399.tmp", - "月度/2月/中考体育传数据/zkty_results~0830D.tmp", "月度/1月/1月.md", "月度/1月/资源发展中心/mysql体检主从库.md", "材料/idcard2.jpg", diff --git a/密码.md b/密码.md index 4ec3618..4bca5c1 100644 --- a/密码.md +++ b/密码.md @@ -172,13 +172,23 @@ URL: [Title Unavailable \| Site Unreachable](http://tcyunsc.cn) # 资源发展中心 ## 【堡垒机】 -用户名:tzjkwycgl -密码:TZJKW#xxzx@7606092 - +用户名: +```json +tzjkwycgl +``` +密码: +```json +TZJKW#xxzx@7606092 +``` ## 【atrust】 -用户名:yanzhun -密码:Yz787112. - +用户名: +```json +yanzhun +``` +密码: +```json +Yz787112. +``` ## 【stxt】 用户名:stxt 密码:TZJKW-stxt#7606092 @@ -222,8 +232,8 @@ URL: [Title Unavailable \| Site Unreachable](http://tcyunsc.cn) 密码:TZJKWxxpt%#20230822 -# 【10.10.15.160 mysql】体检从库 +## 【10.10.15.160 mysql】体检从库 TZJKWxxpt%#20230822 -# 【10.10.15.167 mysql】体检主库 +## 【10.10.15.167 mysql】体检主库 TZJKWxxpt%#20230822 \ No newline at end of file diff --git a/月度/2月/2月.md b/月度/2月/2月.md index a936477..45e5f54 100644 --- a/月度/2月/2月.md +++ b/月度/2月/2月.md @@ -90,14 +90,73 @@ feat(middleClassdz): 新增总计表格及图表功能 - 更新服务层实现总计数据处理逻辑 - 在报告生成服务中集成总计表格和图表数据 - 更新模板文件添加表格6占位符并调整机构名称 - - +- 巴州常见病 前端 -feat(zbEyesReport): 新增各县市中班总计分析模块 + feat(zbEyesReport): 新增各县市中班总计分析模块 新增各县市中班总计统计表和视力不良检出率总计对比图, 调整报告章节顺序,将原"视力不良检出率分析"改为"各县市中班总计分析" 作为第二部分,并将其他章节序号依次后移,同时优化图表渲染逻辑 +# 2.5 +1.统计[[晨午检2025年全年未上报学校、60日内未上报学校.xlsx]] + +2.石榴籽健康 +feat(snow-holiday): 实现游标分页和滚动预加载功能 + +- 添加 onPageScroll 事件处理,实现滚动节流和预加载机制 +- 改进分页逻辑,支持 lastId 游标分页,避免深度分页性能问题 +- 修复前端去重逻辑,防止重复数据展示 +- 优化 hasMore 判断逻辑,提高分页准确性 + +fix(date-format): 解决 iOS 日期格式兼容性问题 + +- 修改 getDay、getMonth 和 formatTime 方法中的日期构造逻辑 +- 添加字符串替换处理,将 yyyy-MM-dd 格式转换为 yyyy/MM/dd +- 解决 iOS 设备无法解析短横线分隔日期格式的问题 + +refactor(user-profile): 优化头像上传和内容审核 + +- 移除 uni-file-picker 组件,改用原生 chooseImage 实现 +- 更新上传接口为 /common/uploadContentModeration +- 调整内容审核服务,使用更准确的检测模型 +- 修复头像上传错误提示显示问题 + +perf(play-snow-holiday): 优化后端分页查询性能 + +- 实现游标分页机制,避免使用 PageHelper 深度分页 +- 在 SQL 中添加 lastId 过滤条件,提升查询效率 +- 优化排序字段,添加 id 作为次要排序条件 + + + # 2.6 + 1.巴州常见病报表 + feat(bzcjb-export): 添加县区级学龄前儿童近视防控报告功能 + +- 新增县区级报告实体类(BazhouPreschoolMyopiaReportXQ)及相关数据模型 +- 扩展控制器以支持根据level参数分发地州级(3)和县区级(4)数据 +- 添加县区级服务类(BazhouPreschoolMyopiaReportXQService)和对应Mapper接口 +- 实现县区级图表生成逻辑(GenerateChartMiddleXQ)和表格生成功能 +- 新增县区级各类统计表格实体(XQ后缀):视力不良检出率、可疑远视储备不足率等 +- 扩展TResultPrimaryMapper添加县区级数据查询方法和区域名称查询接口 + +2. 巴州常见病 + 前端 + feat(zbEyesReport): 实现报告页面多级权限动态展示 + +- 根据用户权限级别(currentLevel)动态显示不同层级的报告内容 +- 地州级(currentLevel == 3)显示各县市统计数据和图表 +- 县区级(currentLevel >= 3)显示各学校统计数据和图表 +- 动态设置报告标题、地区名称和统计范围文字 +- 添加getUserParams方法获取用户权限信息并设置对应参数 +- 更新表格列标题根据用户级别显示"县市"或"学校" +- 调整图表配置移除冗余标题并优化布局间距 + +feat(static): 添加报告签名条件渲染和数据处理优化 + +- 在zbEyesReport.vue中添加条件渲染,当signature存在时显示signature, + 否则显示cdccounty字段 +- 优化数据过滤逻辑,通过检查是否有小计行来正确处理不同级别的统计数据 +- 调整图表数据显示逻辑以支持地州级和县区级的不同数据结构 \ No newline at end of file diff --git a/月度/2月/巴州常见病/视力不良与远视储备检出率统计表.xlsx b/月度/2月/巴州常见病/视力不良与远视储备检出率统计表.xlsx deleted file mode 100644 index 586fe7e..0000000 Binary files a/月度/2月/巴州常见病/视力不良与远视储备检出率统计表.xlsx and /dev/null differ diff --git a/月度/2月/晨午检/学校晨午检及因病缺勤信息管理系统业务逻辑说明书(1).docx b/月度/2月/晨午检/学校晨午检及因病缺勤信息管理系统业务逻辑说明书(1).docx deleted file mode 100644 index 5849e4d..0000000 Binary files a/月度/2月/晨午检/学校晨午检及因病缺勤信息管理系统业务逻辑说明书(1).docx and /dev/null differ diff --git a/月度/2月/晨午检/晨午检2025年全年未上报学校、60日内未上报学校.xlsx b/月度/2月/晨午检/晨午检2025年全年未上报学校、60日内未上报学校.xlsx new file mode 100644 index 0000000..a14052a Binary files /dev/null and b/月度/2月/晨午检/晨午检2025年全年未上报学校、60日内未上报学校.xlsx differ