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