archsight 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -1
  3. data/README.md +6 -1
  4. data/docs/icons.md +29 -2
  5. data/docs/index.md.erb +22 -4
  6. data/docs/modeling.md +268 -6
  7. data/docs/pages.md +12 -3
  8. data/docs/search.md +9 -2
  9. data/docs/togaf.md +8 -1
  10. data/lib/archsight/annotations/asset_annotations.rb +34 -0
  11. data/lib/archsight/annotations/relation_resolver.rb +15 -6
  12. data/lib/archsight/annotations/risk_annotations.rb +21 -0
  13. data/lib/archsight/cli.rb +6 -0
  14. data/lib/archsight/database.rb +57 -3
  15. data/lib/archsight/diagram.rb +7 -0
  16. data/lib/archsight/documentation.rb +10 -6
  17. data/lib/archsight/editor.rb +2 -2
  18. data/lib/archsight/helpers/requirements_blocks.rb +1 -1
  19. data/lib/archsight/helpers/resource_resolver.rb +1 -1
  20. data/lib/archsight/helpers/wiki_links.rb +11 -0
  21. data/lib/archsight/linter.rb +110 -0
  22. data/lib/archsight/mcp/analyze_resource_tool.rb +2 -2
  23. data/lib/archsight/mcp/resource_doc_tool.rb +2 -2
  24. data/lib/archsight/query/ast.rb +2 -1
  25. data/lib/archsight/query/evaluator.rb +2 -2
  26. data/lib/archsight/references.rb +129 -0
  27. data/lib/archsight/requirements.rb +4 -4
  28. data/lib/archsight/resources/application_component.rb +11 -1
  29. data/lib/archsight/resources/application_event.rb +79 -0
  30. data/lib/archsight/resources/application_interface.rb +1 -1
  31. data/lib/archsight/resources/application_service.rb +10 -5
  32. data/lib/archsight/resources/base.rb +40 -5
  33. data/lib/archsight/resources/business_actor.rb +9 -1
  34. data/lib/archsight/resources/business_control.rb +88 -0
  35. data/lib/archsight/resources/business_event.rb +79 -0
  36. data/lib/archsight/resources/business_process.rb +11 -3
  37. data/lib/archsight/resources/business_product.rb +2 -2
  38. data/lib/archsight/resources/business_role.rb +69 -0
  39. data/lib/archsight/resources/compliance_evidence.rb +44 -3
  40. data/lib/archsight/resources/data_object.rb +7 -2
  41. data/lib/archsight/resources/implementation_deliverable.rb +62 -0
  42. data/lib/archsight/resources/implementation_event.rb +52 -0
  43. data/lib/archsight/resources/implementation_gap.rb +49 -0
  44. data/lib/archsight/resources/implementation_plateau.rb +61 -0
  45. data/lib/archsight/resources/implementation_work_package.rb +83 -0
  46. data/lib/archsight/resources/motivation_assessment.rb +121 -0
  47. data/lib/archsight/resources/{business_constraint.rb → motivation_constraint.rb} +11 -5
  48. data/lib/archsight/resources/motivation_driver.rb +50 -0
  49. data/lib/archsight/resources/motivation_goal.rb +14 -2
  50. data/lib/archsight/resources/motivation_principle.rb +75 -0
  51. data/lib/archsight/resources/{business_requirement.rb → motivation_requirement.rb} +27 -7
  52. data/lib/archsight/resources/motivation_stakeholder.rb +9 -2
  53. data/lib/archsight/resources/page.rb +5 -0
  54. data/lib/archsight/resources/strategy_capability.rb +2 -2
  55. data/lib/archsight/resources/technology_event.rb +80 -0
  56. data/lib/archsight/resources/technology_node.rb +8 -2
  57. data/lib/archsight/resources/technology_service.rb +3 -3
  58. data/lib/archsight/resources/technology_system_software.rb +3 -3
  59. data/lib/archsight/resources.rb +34 -3
  60. data/lib/archsight/template.rb +2 -2
  61. data/lib/archsight/version.rb +1 -1
  62. data/lib/archsight/web/api/docs.rb +1 -1
  63. data/lib/archsight/web/api/json_helpers.rb +14 -10
  64. data/lib/archsight/web/api/openapi/spec.yaml +2 -2
  65. data/lib/archsight/web/api/page_helpers.rb +8 -7
  66. data/lib/archsight/web/api/routes.rb +1 -1
  67. data/lib/archsight/web/application.rb +6 -1
  68. data/lib/archsight/web/public/vue/{ApiDocsPage-D-cPRZCT.js → ApiDocsPage-BgqnQgwa.js} +1 -1
  69. data/lib/archsight/web/public/vue/{DocPage-DK6vNDbF.js → DocPage-CNO71nBH.js} +1 -1
  70. data/lib/archsight/web/public/vue/{EditorPage-BoJpQaVw.js → EditorPage-DR0FCNTz.js} +1 -1
  71. data/lib/archsight/web/public/vue/{ErrorPage-PGyjdtEf.js → ErrorPage-BfYArv6s.js} +1 -1
  72. data/lib/archsight/web/public/vue/{GraphView-BLiKR4zP.js → GraphView-BVTW30Ak.js} +1 -1
  73. data/lib/archsight/web/public/vue/HomePage-Wk9P4Pma.js +2 -0
  74. data/lib/archsight/web/public/vue/InstanceRouter-BV8ycydz.js +1 -0
  75. data/lib/archsight/web/public/vue/{InstanceRouter-60Tt3ZNM.css → InstanceRouter-jeavM6PW.css} +1 -1
  76. data/lib/archsight/web/public/vue/KindList-C8yMsN5J.js +1 -0
  77. data/lib/archsight/web/public/vue/{PageView-9MgHtrgl.js → PageView-BaN6TyJB.js} +1 -1
  78. data/lib/archsight/web/public/vue/{QueryError-D1FL1xgA.js → QueryError-D790wH-a.js} +1 -1
  79. data/lib/archsight/web/public/vue/ResourceList-D-66nas2.js +2 -0
  80. data/lib/archsight/web/public/vue/{SearchResults-DiW5XVYW.css → SearchResults-BewvsfOc.css} +1 -1
  81. data/lib/archsight/web/public/vue/SearchResults-CHyqIerQ.js +1 -0
  82. data/lib/archsight/web/public/vue/{WikiPage-CeCQBTDS.js → WikiPage-D2svpk6B.js} +3 -3
  83. data/lib/archsight/web/public/vue/WikiPage-DoFJ0dbW.css +1 -0
  84. data/lib/archsight/web/public/vue/{index-D7m61Ahx.js → index-BXXkUK1V.js} +2 -2
  85. data/lib/archsight/web/public/vue/index-Cov1SnzY.css +1 -0
  86. data/lib/archsight/web/public/vue/{useGraphviz-DweKV7Kg.js → useGraphviz-DlSnFeCL.js} +12 -0
  87. data/lib/archsight/web/public/vue.html +2 -2
  88. metadata +38 -22
  89. data/lib/archsight/web/public/vue/HomePage-C0lR8i2C.js +0 -2
  90. data/lib/archsight/web/public/vue/InstanceRouter-D3W2jJHV.js +0 -1
  91. data/lib/archsight/web/public/vue/KindList-BlsaRBNO.js +0 -1
  92. data/lib/archsight/web/public/vue/ResourceList-vkgFyeOY.js +0 -2
  93. data/lib/archsight/web/public/vue/SearchResults-Cl3O_OEr.js +0 -1
  94. data/lib/archsight/web/public/vue/WikiPage-C-8SG67a.css +0 -1
  95. data/lib/archsight/web/public/vue/index-Dbx3MXWG.css +0 -1
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # BusinessRequirement represents functional or non-functional requirements
4
- class Archsight::Resources::BusinessRequirement < Archsight::Resources::Base
5
- include_annotations :git, :architecture
3
+ # MotivationRequirement represents functional or non-functional requirements
4
+ class Archsight::Resources::MotivationRequirement < Archsight::Resources::Base
5
+ include_annotations :git, :architecture, :risk
6
6
 
7
7
  description <<~MD
8
8
  Represents a statement of need that must be realized by the architecture.
@@ -18,28 +18,47 @@ class Archsight::Resources::BusinessRequirement < Archsight::Resources::Base
18
18
 
19
19
  ## Usage
20
20
 
21
- Use BusinessRequirement to represent:
21
+ Use MotivationRequirement to represent:
22
22
 
23
23
  - Compliance requirements (C5, ISO 27001)
24
24
  - Security requirements
25
25
  - Performance requirements
26
26
  - Functional specifications
27
27
  - Legal obligations (GDPR, NIS2)
28
+
29
+ ## Who addresses it
30
+
31
+ A requirement is where the process side and the application side meet:
32
+
33
+ - **Process side:** a `BusinessControl` `satisfies` the requirement; a process is `guidedBy` the control
34
+ - **Application side:** applications `realize` or `plan` the requirement and are `evidencedBy` `ComplianceEvidence`,
35
+ which `satisfies` it
36
+
37
+ Both show as incoming relations on the requirement's page.
38
+
39
+ ## Security and risk modelling
40
+
41
+ - **Control measure:** `requirement/type` `control-measure` is a measure that a control objective
42
+ (`MotivationGoal`) `realizes`; the risk is `mitigatedBy` the objective or directly by the measure, and the
43
+ asset or control that implements the measure `realizes` or `satisfies` it.
44
+ - **Control requirement / catalogue control:** a control of a standard (C5, ISO 27001) is a requirement of type
45
+ `compliance`, listed in `requirement/reference`.
46
+ - **Policy:** a requirement can `realize` a `MotivationPrinciple` (the policy it implements).
28
47
  MD
29
48
 
30
49
  icon "task-list"
31
- layer "business"
50
+ layer "motivation"
32
51
 
33
52
  annotation "requirement/type",
34
53
  description: "Type of requirement (business or legal)",
35
- enum: %w[business legal compliance functional non-functional],
54
+ enum: %w[business legal compliance functional non-functional control-measure],
36
55
  summary: true
37
56
 
38
57
  annotation "requirement/reference",
39
58
  description: "Regulatory or standard reference (comma-separated for multiple)",
40
59
  filter: :list,
41
60
  enum: %w[c5-2020 itgs-2023 gdpr-2018 nis1 nis2 iso27001 sox pci-dss hipaa eu-data-act-2025 ens
42
- iso27001-2022],
61
+ iso27001-2022 vsa-2023 con-11-1],
43
62
  summary: true
44
63
 
45
64
  annotation "requirement/priority",
@@ -54,4 +73,5 @@ class Archsight::Resources::BusinessRequirement < Archsight::Resources::Base
54
73
  format: :markdown
55
74
 
56
75
  relation :realizes, :outcomes, :MotivationOutcome
76
+ relation :realizes, :motivationPrinciples, :MotivationPrinciple
57
77
  end
@@ -26,13 +26,20 @@ class Archsight::Resources::MotivationStakeholder < Archsight::Resources::Base
26
26
  - Customer representatives
27
27
  - Regulatory bodies
28
28
  - Technical leadership
29
+
30
+ ## Security and risk modelling
31
+
32
+ A stakeholder (CISO, risk committee, data protection officer) can `hasConcern` for threats
33
+ (`MotivationDriver`) and risks (`MotivationAssessment`) in addition to goals and requirements.
29
34
  MD
30
35
 
31
36
  icon "user-crown"
32
37
  layer "motivation"
33
38
 
34
39
  relation :hasConcern, :strategyCapabilities, :StrategyCapability
35
- relation :hasConcern, :businessRequirements, :BusinessRequirement
36
- relation :hasConcern, :businessConstraints, :BusinessConstraint
40
+ relation :hasConcern, :motivationRequirements, :MotivationRequirement
41
+ relation :hasConcern, :motivationConstraints, :MotivationConstraint
37
42
  relation :hasConcern, :goals, :MotivationGoal
43
+ relation :hasConcern, :motivationDrivers, :MotivationDriver
44
+ relation :hasConcern, :motivationAssessments, :MotivationAssessment
38
45
  end
@@ -20,6 +20,11 @@ class Archsight::Resources::Page < Archsight::Resources::Base
20
20
 
21
21
  `title`, `author`, `owner`, `status`, `tags` (comma-separated), `toc` (yes/no), `confluence`
22
22
  (URL of the linked Confluence page) and an optional `name` (defaults to the file path).
23
+
24
+ ## Security and risk modelling
25
+
26
+ The text of a policy, a risk register narrative or an incident report is a `Page`. Link the structured
27
+ resources (`MotivationPrinciple`, `MotivationAssessment`, events) to it with `[[Page]]`.
23
28
  MD
24
29
 
25
30
  icon "page"
@@ -30,8 +30,8 @@ class Archsight::Resources::StrategyCapability < Archsight::Resources::Base
30
30
  icon "strategy"
31
31
  layer "strategy"
32
32
 
33
- relation :realizes, :businessConstraints, :BusinessConstraint
34
- relation :realizes, :businessRequirements, :BusinessRequirement
33
+ relation :realizes, :motivationConstraints, :MotivationConstraint
34
+ relation :realizes, :motivationRequirements, :MotivationRequirement
35
35
  relation :servedBy, :businessActors, :BusinessActor
36
36
  relation :servedBy, :applicationServices, :ApplicationService
37
37
  relation :servedBy, :businessProcesses, :BusinessProcess
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TechnologyEvent represents a technology event: something that happens in the infrastructure and triggers or interrupts technology behavior
4
+ class Archsight::Resources::TechnologyEvent < Archsight::Resources::Base
5
+ include_annotations :git, :architecture, :risk
6
+
7
+ description <<~MD
8
+ Represents a technology event: something that happens in the infrastructure and triggers or interrupts technology behavior.
9
+
10
+ ## ArchiMate Definition
11
+
12
+ **Layer:** Technology
13
+ **Aspect:** Behavior
14
+
15
+ An event is something that happens and influences behavior. It does not last: it triggers or interrupts
16
+ processes and services. In the risk and security overlay of the Open Group paper (*Modeling Enterprise Risk
17
+ Management and Security with the ArchiMate Language*) a threat event and a loss event are events that carry a
18
+ type; set `event/type` to say which.
19
+
20
+ ## Usage
21
+
22
+ Use TechnologyEvent for events on the technology level:
23
+
24
+ - Threat events and loss events of the infrastructure (a host compromise, an outage, a failed disk)
25
+ - Findings of a scan or a penetration test on a host or network
26
+ - Infrastructure alerts and changes
27
+
28
+ ## Event types
29
+
30
+ - `threat-event`: an event with the potential to harm an asset; it can trigger a loss event
31
+ - `attack`: a threat event caused by intentional malicious activity
32
+ - `loss-event`: an event that harms an asset (a hazard materialises, a vulnerability is exploited)
33
+ - `incident`: a loss event that has happened
34
+ - `opportunity-event`: an event that can add value
35
+ - `audit`, `scan`, `change`: events that produce assessments or alter the architecture
36
+ - `other`
37
+
38
+ Filter, group and query by `event/type`, `risk/domain` and `risk/category` to see, for example, every loss
39
+ event of a risk domain.
40
+
41
+ ## How it connects
42
+
43
+ - A threat event `triggers` a loss event or a process or service; threat and loss events may sit on different
44
+ layers (a technology event triggers an application or business event)
45
+ - `causedBy` the threat agent (an actor, component or node)
46
+ - `affects` the assets it harms
47
+ - A `MotivationDriver` (the threat) `triggers` it; a vulnerability `MotivationAssessment` `influences` it
48
+ MD
49
+
50
+ icon "warning-triangle"
51
+ layer "technology"
52
+
53
+ annotation "event/type",
54
+ description: "What kind of event this is (specialization of the event, see the risk and security overlay)",
55
+ enum: %w[threat-event attack loss-event incident opportunity-event audit scan change other],
56
+ filter: :word,
57
+ summary: true
58
+
59
+ annotation "event/severity",
60
+ description: "Severity of the event",
61
+ enum: %w[info low medium high critical],
62
+ filter: :word,
63
+ summary: true
64
+
65
+ annotation "event/occurred",
66
+ description: "When the event happened or is expected (ISO 8601 date or time)",
67
+ title: "Occurred",
68
+ validator: ->(value) { Archsight::Resources::Page.timestamp_error(value) }
69
+
70
+ relation :triggers, :technologyServices, :TechnologyService
71
+ relation :triggers, :technologyEvents, :TechnologyEvent
72
+ relation :triggers, :applicationEvents, :ApplicationEvent
73
+ relation :triggers, :businessEvents, :BusinessEvent
74
+ relation :causedBy, :businessActors, :BusinessActor
75
+ relation :causedBy, :applicationComponents, :ApplicationComponent
76
+ relation :causedBy, :technologyNodes, :TechnologyNode
77
+ relation :affects, :technologyNodes, :TechnologyNode
78
+ relation :affects, :technologyServices, :TechnologyService
79
+ relation :affects, :technologySystemSoftwares, :TechnologySystemSoftware
80
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  # TechnologyNode represents physical infrastructure (VMs, servers, Kubernetes nodes)
4
4
  class Archsight::Resources::TechnologyNode < Archsight::Resources::Base
5
- include_annotations :git, :architecture
5
+ include_annotations :git, :architecture, :asset, :risk
6
6
 
7
7
  description <<~MD
8
8
  Represents physical infrastructure hosting application components.
@@ -25,6 +25,12 @@ class Archsight::Resources::TechnologyNode < Archsight::Resources::Base
25
25
  - Kubernetes nodes
26
26
  - Network appliances
27
27
  - Storage arrays
28
+
29
+ ## Security and risk modelling
30
+
31
+ A node is the typical asset of a vulnerability assessment: a scan result is a `MotivationAssessment` of type
32
+ `vulnerability` that `assesses` the nodes it was found on (one vulnerability, many nodes) and `influences` the
33
+ loss events it makes possible. Set the `asset/*` profile and `risk/domain` to group nodes by context.
28
34
  MD
29
35
 
30
36
  icon "server-connection"
@@ -36,7 +42,7 @@ class Archsight::Resources::TechnologyNode < Archsight::Resources::Base
36
42
  enum: %w[vm bare-metal kubernetes-node network-appliance storage-array],
37
43
  summary: true
38
44
 
39
- relation :realizes, :businessConstraints, :BusinessConstraint
45
+ relation :realizes, :motivationConstraints, :MotivationConstraint
40
46
  relation :servedBy, :technologyServices, :TechnologyService
41
47
  relation :servedBy, :businessActors, :BusinessActor
42
48
  end
@@ -37,8 +37,8 @@ class Archsight::Resources::TechnologyService < Archsight::Resources::Base
37
37
 
38
38
  relation :suppliedBy, :technologyComponents, :TechnologySystemSoftware
39
39
  relation :servedBy, :businessActors, :BusinessActor
40
- relation :realizes, :businessRequirements, :BusinessRequirement
41
- relation :partiallyRealizes, :businessRequirements, :BusinessRequirement
42
- relation :plans, :businessRequirements, :BusinessRequirement
40
+ relation :realizes, :motivationRequirements, :MotivationRequirement
41
+ relation :partiallyRealizes, :motivationRequirements, :MotivationRequirement
42
+ relation :plans, :motivationRequirements, :MotivationRequirement
43
43
  relation :evidencedBy, :complianceEvidences, :ComplianceEvidence
44
44
  end
@@ -34,8 +34,8 @@ class Archsight::Resources::TechnologySystemSoftware < Archsight::Resources::Bas
34
34
  relation :realizedThrough, :technologyArtifacts, :TechnologyArtifact
35
35
  relation :exposes, :applicationInterfaces, :ApplicationInterface
36
36
  relation :dependsOn, :applicationInterfaces, :ApplicationInterface
37
- relation :realizes, :businessRequirements, :BusinessRequirement
38
- relation :partiallyRealizes, :businessRequirements, :BusinessRequirement
39
- relation :plans, :businessRequirements, :BusinessRequirement
37
+ relation :realizes, :motivationRequirements, :MotivationRequirement
38
+ relation :partiallyRealizes, :motivationRequirements, :MotivationRequirement
39
+ relation :plans, :motivationRequirements, :MotivationRequirement
40
40
  relation :evidencedBy, :complianceEvidences, :ComplianceEvidence
41
41
  end
@@ -6,6 +6,37 @@ module Archsight
6
6
  # Store the class mapping
7
7
  @resource_classes = {}
8
8
 
9
+ # Kinds that were renamed: the old name is still accepted (see Database#create_valid_instance) and reported
10
+ # as deprecated by `archsight lint`. The table is only consulted by lookups; `each` and `resource_classes`
11
+ # list every kind once, under its new name. Remove an entry (and its relation keys below) to end the transition.
12
+ KIND_ALIASES = {
13
+ "BusinessRequirement" => "MotivationRequirement",
14
+ "BusinessConstraint" => "MotivationConstraint"
15
+ }.freeze
16
+
17
+ # Relation keys (the plural kind names under `spec.<verb>`) that were renamed together with their kind
18
+ RELATION_KEY_ALIASES = {
19
+ "businessRequirements" => "motivationRequirements",
20
+ "businessConstraints" => "motivationConstraints"
21
+ }.freeze
22
+
23
+ # Relations that are never written in a file: they are derived from what a resource's text and diagram say
24
+ # (see Archsight::References). `mentions` comes from links in text, `depicts` from the nodes of a diagram.
25
+ # Every kind can have them towards every kind, so instead of one relation per target kind a class gets one per
26
+ # verb, under the key DERIVED_KEY, that holds resources of any kind (relations are followed by looking at the
27
+ # resources they hold, not at the kind they were declared for).
28
+ DERIVED_VERBS = %i[mentions depicts].freeze
29
+ DERIVED_KEY = :resources
30
+
31
+ # The derived relations of every class, next to the ones it declares: [verb, key, kind]
32
+ DERIVED_RELATIONS = DERIVED_VERBS.map { |verb| [verb, DERIVED_KEY, "Resource"] }.freeze
33
+
34
+ # The current name of a kind, whichever of its names is given
35
+ def self.canonical(klass_name)
36
+ name = klass_name.to_s
37
+ KIND_ALIASES.fetch(name, name)
38
+ end
39
+
9
40
  # Register a resource class
10
41
  def self.register(klass)
11
42
  # Skip anonymous classes (used in tests)
@@ -20,9 +51,9 @@ module Archsight
20
51
  @resource_classes
21
52
  end
22
53
 
23
- # Returns the class by name
54
+ # Returns the class by name; a renamed kind is found under its old name too
24
55
  def self.[](klass_name)
25
- @resource_classes[klass_name.to_s]
56
+ @resource_classes[canonical(klass_name)]
26
57
  end
27
58
 
28
59
  # Iterate over all resource class names (sorted)
@@ -32,7 +63,7 @@ module Archsight
32
63
 
33
64
  # Get the constant by name (for backward compatibility with const_get)
34
65
  def self.const_get(name)
35
- @resource_classes[name.to_s] || super
66
+ @resource_classes[canonical(name)] || super
36
67
  end
37
68
  end
38
69
  end
@@ -35,10 +35,10 @@ module Archsight
35
35
  end
36
36
 
37
37
  def add_relations(yaml, klass)
38
- return if klass.relations.empty?
38
+ return if klass.declared_relations.empty?
39
39
 
40
40
  yaml["spec"] = {} if yaml["spec"].nil?
41
- klass.relations.each do |verb, relation_kind, _relation_klass|
41
+ klass.declared_relations.each do |verb, relation_kind, _relation_klass|
42
42
  relation_verb = verb.to_s.delete_prefix(":")
43
43
  yaml["spec"][relation_verb] ||= {}
44
44
  yaml["spec"][relation_verb][relation_kind.to_s] = []
@@ -4,5 +4,5 @@
4
4
  # Do not edit manually.
5
5
 
6
6
  module Archsight
7
- VERSION = "0.3.1"
7
+ VERSION = "0.3.3"
8
8
  end
@@ -18,7 +18,7 @@ module Archsight::Web::API::Docs
18
18
  # GET /api/v1/docs/resources/:filename — auto-generated resource docs
19
19
  get "/api/v1/docs/resources/:filename" do
20
20
  filename = params["filename"].gsub(/[^a-zA-Z0-9_-]/, "")
21
- kind_name = filename.split("_").map(&:capitalize).join
21
+ kind_name = Archsight::Resources.canonical(filename.split("_").map(&:capitalize).join) # an old help link shows the renamed kind
22
22
 
23
23
  begin
24
24
  content = Archsight::Documentation.generate(kind_name)
@@ -74,7 +74,7 @@ module Archsight::Web::API::JsonHelpers
74
74
 
75
75
  def build_list_response(kind, pagination, instances)
76
76
  {
77
- kind: kind,
77
+ kind: Archsight::Resources.canonical(kind),
78
78
  total: pagination[:total],
79
79
  limit: pagination[:limit],
80
80
  offset: pagination[:offset],
@@ -88,9 +88,10 @@ module Archsight::Web::API::JsonHelpers
88
88
 
89
89
  def build_instance_response(kind, instance)
90
90
  {
91
- kind: kind,
91
+ kind: Archsight::Resources.canonical(kind),
92
92
  name: instance.name,
93
- metadata: { annotations: render_annotations(instance.annotations, base: Archsight::Assets.base_dir_for(instance, resources_dir: Archsight.resources_dir)) },
93
+ metadata: { annotations: render_annotations(instance.annotations, base: Archsight::Assets.base_dir_for(instance, resources_dir: Archsight.resources_dir), kind: kind) },
94
+ annotation_formats: Archsight::Resources[kind]&.annotation_formats(instance.annotations.keys) || {},
94
95
  spec: serialize_spec(instance.spec),
95
96
  relations: extract_relations(instance),
96
97
  references: extract_references(instance),
@@ -106,10 +107,14 @@ module Archsight::Web::API::JsonHelpers
106
107
  Archsight::Helpers::DiagramBlocks.render_diagram(source, resolver: Archsight::Helpers::ResourceResolver.new(db))
107
108
  end
108
109
 
110
+ # The values of markdown annotations are rendered to HTML: architecture/description and every annotation the
111
+ # kind defines with `format: :markdown`.
109
112
  # @param base [String, nil] directory of the file the resource comes from, for the images of its markdown
110
- def render_annotations(annotations, base: nil)
113
+ # @param kind [String, nil] the kind of the resource, to find which of its annotations are markdown
114
+ def render_annotations(annotations, base: nil, kind: nil)
115
+ klass = kind && Archsight::Resources[kind]
111
116
  annotations.each_with_object({}) do |(key, value), result|
112
- result[key] = if MARKDOWN_ANNOTATION_KEYS.include?(key) && value.is_a?(String)
117
+ result[key] = if value.is_a?(String) && (MARKDOWN_ANNOTATION_KEYS.include?(key) || klass&.annotation_format(key) == :markdown)
113
118
  markdown(value, base: base)
114
119
  else
115
120
  value
@@ -167,11 +172,10 @@ module Archsight::Web::API::JsonHelpers
167
172
  relations = {}
168
173
 
169
174
  instance.class.relations.each do |verb, spec_key, kind|
170
- rels = instance.relations(verb, spec_key).map(&:name)
171
- next if rels.empty?
172
-
173
- relations[verb] ||= {}
174
- relations[verb][kind] = rels
175
+ found = instance.relations(verb, spec_key)
176
+ # derived relations hold resources of any kind: grouped by the kind each one is
177
+ groups = Archsight::Resources::DERIVED_VERBS.include?(verb) ? found.group_by(&:klass) : { kind => found }
178
+ groups.each { |target_kind, rels| (relations[verb] ||= {})[target_kind] = rels.map(&:name) unless rels.empty? }
175
179
  end
176
180
 
177
181
  relations
@@ -705,9 +705,9 @@ paths:
705
705
 
706
706
  /api/v1/requirements:
707
707
  get:
708
- summary: Business requirements of a selection of resources
708
+ summary: Requirements of a selection of resources
709
709
  description: |
710
- The business requirements that the resources selected by `of` realize (`implemented`), partially realize
710
+ The requirements that the resources selected by `of` realize (`implemented`), partially realize
711
711
  (`partial`) or plan (`planned`), merged over all of them: one entry per requirement with the best status and
712
712
  the resources it comes from (`by`). Sorted by priority (must, should, may, none), then name. `story` is
713
713
  rendered HTML.
@@ -67,13 +67,14 @@ module Archsight::Web::API::PageHelpers
67
67
  rest.to_s.lstrip
68
68
  end
69
69
 
70
- # Other pages linking to this page with [[name]], [[title]] (optionally with |label)
70
+ # The other pages that link to this page with [[name]] or [[title]] (optionally with |label): the pages that mention it
71
+ # (see Archsight::References), so a link in code does not count and a page is not listed twice.
71
72
  def page_backlinks(page)
72
- targets = [page.name, page.title].map { |t| Regexp.escape(t.to_s) }.uniq.join("|")
73
- pattern = /\[\[\s*(?:#{targets})\s*(?:\||\]\])/i
74
- db.instances_by_kind("Page").values
75
- .select { |other| other != page && other.annotations["page/content"].to_s.match?(pattern) }
76
- .sort_by(&:name)
77
- .map { |other| { name: other.name, title: other.title } }
73
+ page.references
74
+ .select { |ref| ref[:verb] == :mentions && ref[:instance].klass == "Page" && !ref[:instance].equal?(page) }
75
+ .map { |ref| ref[:instance] }
76
+ .uniq
77
+ .sort_by(&:name)
78
+ .map { |other| { name: other.name, title: other.title } }
78
79
  end
79
80
  end
@@ -112,7 +112,7 @@ module Archsight::Web::API::Routes
112
112
  end
113
113
  end
114
114
 
115
- # GET /api/v1/requirements - The business requirements of the resources a query selects (see Archsight::Requirements)
115
+ # GET /api/v1/requirements - The requirements of the resources a query selects (see Archsight::Requirements)
116
116
  get "/api/v1/requirements" do
117
117
  query = params[:of]
118
118
  json_error("Query parameter 'of' is required", status: 400, error_type: "BadRequest") unless query
@@ -87,9 +87,14 @@ class Archsight::Web::Application < Sinatra::Base
87
87
  mcp_server.register_tool(Archsight::MCP::ResourceDocTool)
88
88
  mcp_server.register_tool(Archsight::MCP::ExecuteAnalysisTool)
89
89
 
90
+ # The server is meant to be deployed (behind an ingress under its own hostname), and the web UI and API do not
91
+ # restrict who may reach them either. FastMcp's default would only accept the Origin / Host `localhost`
92
+ # (DNS-rebinding protection) and answer every other hostname with 403, so the check is switched off: an empty
93
+ # list of allowed origins disables it.
90
94
  use FastMcp::Transports::RackTransport, mcp_server,
91
95
  path_prefix: "/mcp",
92
- localhost_only: false
96
+ localhost_only: false,
97
+ allowed_origins: []
93
98
  end
94
99
 
95
100
  helpers Archsight::GraphvisRenderer, Archsight::Helpers
@@ -1 +1 @@
1
- import{$ as e,B as t,H as n,M as r,T as i,X as a,Y as o,j as s,k as c,t as l,x as u}from"./index-D7m61Ahx.js";var d={class:`api-docs-page`},f={key:0,class:`pico-color-red-500`},p=l({__name:`ApiDocsPage`,setup(l){let p=u(),m=o(null),h=o(null);function g(e){return new Promise((t,n)=>{if(window.Redoc)return t();let r=document.createElement(`script`);r.src=e,r.onload=t,r.onerror=()=>n(Error(`Failed to load ReDoc`)),document.head.appendChild(r)})}return t(async()=>{try{await g(`https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js`),window.Redoc.init(`/api/v1/openapi.yaml`,{},m.value)}catch(e){h.value=e.message}}),(t,o)=>(n(),r(`div`,d,[c(`a`,{href:`#`,class:`back-link`,onClick:o[0]||=i(e=>a(p).back(),[`prevent`])},`← Back`),h.value?(n(),r(`div`,f,e(h.value),1)):s(``,!0),c(`div`,{ref_key:`container`,ref:m},null,512)]))}},[[`__scopeId`,`data-v-4823b89b`]]);export{p as default};
1
+ import{$ as e,B as t,H as n,M as r,T as i,X as a,Y as o,j as s,k as c,t as l,x as u}from"./index-BXXkUK1V.js";var d={class:`api-docs-page`},f={key:0,class:`pico-color-red-500`},p=l({__name:`ApiDocsPage`,setup(l){let p=u(),m=o(null),h=o(null);function g(e){return new Promise((t,n)=>{if(window.Redoc)return t();let r=document.createElement(`script`);r.src=e,r.onload=t,r.onerror=()=>n(Error(`Failed to load ReDoc`)),document.head.appendChild(r)})}return t(async()=>{try{await g(`https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js`),window.Redoc.init(`/api/v1/openapi.yaml`,{},m.value)}catch(e){h.value=e.message}}),(t,o)=>(n(),r(`div`,d,[c(`a`,{href:`#`,class:`back-link`,onClick:o[0]||=i(e=>a(p).back(),[`prevent`])},`← Back`),h.value?(n(),r(`div`,f,e(h.value),1)):s(``,!0),c(`div`,{ref_key:`container`,ref:m},null,512)]))}},[[`__scopeId`,`data-v-4823b89b`]]);export{p as default};
@@ -1 +1 @@
1
- import{A as e,H as t,K as n,M as r,Y as i,k as a,s as o}from"./index-D7m61Ahx.js";import{t as s}from"./WikiPage-CeCQBTDS.js";var c={key:1},l={__name:`DocPage`,props:{filename:String},setup(l){let u=l,d=i(null);function f(e,t){let n=new DOMParser().parseFromString(e,`text/html`).body,r=n.querySelector(`:scope > article`)||n,i=r.querySelector(`h1`),a=i?.textContent.trim()||t.split(`/`).pop().replace(/[-_]/g,` `);i?.remove();let o=[...r.querySelectorAll(`h2[id], h3[id], h4[id]`)].map(e=>({level:Number(e.tagName[1]),id:e.id,text:e.textContent.trim()})),s=[{title:`Documentation`}];return t.startsWith(`resources/`)&&s.push({title:`Resource types`}),{title:a,html:r.innerHTML,toc:o.length>=2?o:[],breadcrumb:s}}async function p(){let e=await o(u.filename);d.value=e?f(e,u.filename):{title:`Not found`,html:`<p>Documentation not found.</p>`,toc:[],breadcrumb:[{title:`Documentation`}]},document.title=`${d.value.title} - Archsight`}return n(()=>u.filename,p,{immediate:!0}),(n,i)=>d.value?(t(),e(s,{key:0,title:d.value.title,html:d.value.html,breadcrumb:d.value.breadcrumb,toc:d.value.toc},null,8,[`title`,`html`,`breadcrumb`,`toc`])):(t(),r(`article`,c,[...i[0]||=[a(`p`,null,`Loading...`,-1)]]))}};export{l as default};
1
+ import{A as e,H as t,K as n,M as r,Y as i,k as a,s as o}from"./index-BXXkUK1V.js";import{t as s}from"./WikiPage-D2svpk6B.js";var c={key:1},l={__name:`DocPage`,props:{filename:String},setup(l){let u=l,d=i(null);function f(e,t){let n=new DOMParser().parseFromString(e,`text/html`).body,r=n.querySelector(`:scope > article`)||n,i=r.querySelector(`h1`),a=i?.textContent.trim()||t.split(`/`).pop().replace(/[-_]/g,` `);i?.remove();let o=[...r.querySelectorAll(`h2[id], h3[id], h4[id]`)].map(e=>({level:Number(e.tagName[1]),id:e.id,text:e.textContent.trim()})),s=[{title:`Documentation`}];return t.startsWith(`resources/`)&&s.push({title:`Resource types`}),{title:a,html:r.innerHTML,toc:o.length>=2?o:[],breadcrumb:s}}async function p(){let e=await o(u.filename);d.value=e?f(e,u.filename):{title:`Not found`,html:`<p>Documentation not found.</p>`,toc:[],breadcrumb:[{title:`Documentation`}]},document.title=`${d.value.title} - Archsight`}return n(()=>u.filename,p,{immediate:!0}),(n,i)=>d.value?(t(),e(s,{key:0,title:d.value.title,html:d.value.html,breadcrumb:d.value.breadcrumb,toc:d.value.toc},null,8,[`title`,`html`,`breadcrumb`,`toc`])):(t(),r(`article`,c,[...i[0]||=[a(`p`,null,`Loading...`,-1)]]))}};export{l as default};
@@ -1,4 +1,4 @@
1
- import{i as e,n as t,t as n}from"./useHighlight-D5Gf8DLl.js";import{$ as r,A as i,B as a,C as o,E as s,F as c,G as l,H as u,J as d,K as f,L as p,M as m,O as h,P as g,R as _,S as v,T as ee,U as y,V as b,X as x,Y as S,Z as C,_ as w,a as T,c as te,j as E,k as D,l as ne,o as re,q as ie,t as ae,v as oe,x as se,z as ce}from"./index-D7m61Ahx.js";var le=`archsight.diagramPreview.layout`,ue=[`bottom`,`right`,`full`,`hidden`],de=`(min-width: 1400px)`;function fe(){try{let e=localStorage.getItem(le);return ue.includes(e)?e:null}catch{return null}}var pe=S(fe()),me=S(typeof matchMedia==`function`&&matchMedia(de).matches);typeof matchMedia==`function`&&matchMedia(de).addEventListener(`change`,e=>{me.value=e.matches});var he=h(()=>pe.value||(me.value?`right`:`bottom`));function ge(e){if(ue.includes(e)){pe.value=e;try{localStorage.setItem(le,e)}catch{}}}function _e(){return{layout:he,setLayout:ge}}var ve={class:`preview-head`},ye={class:`preview-tools`},be={key:0,class:`preview-state`},xe={class:`preview-layout`,role:`group`,"aria-label":`Preview layout`},Se=[`aria-pressed`,`title`,`aria-label`,`onClick`],Ce={key:0,class:`preview-error`,role:`alert`},we=[`innerHTML`],Te={key:2,class:`preview-empty`},Ee=300,De=ae({__name:`DiagramPreview`,props:{source:String},setup(e){let t=e,{layout:n,setLayout:i}=_e(),a=h(()=>n.value===`hidden`),o=[{value:`bottom`,icon:`iconoir-table-rows`,label:`Below the editor`},{value:`right`,icon:`iconoir-view-columns-2`,label:`Right of the editor`},{value:`full`,icon:`iconoir-expand`,label:`Preview only`},{value:`hidden`,icon:`iconoir-eye-closed`,label:`Hide preview`}],c=S(``),l=S(null),d=S(!1),p=null,_=null;function v(){clearTimeout(p),p=null,_?.abort(),_=null}async function ee(e){_=new AbortController;let t=_;d.value=!0;try{let n=await w(e,{signal:t.signal});if(t!==_)return;n.html&&(c.value=n.html),l.value=n.error}catch(e){if(e.name===`AbortError`||t!==_)return;l.value=e.message}finally{t===_&&(d.value=!1)}}f([()=>t.source,a],([e,t],[,n])=>{if(v(),t){d.value=!1;return}if(!e||!e.trim()){c.value=``,l.value=null,d.value=!1;return}d.value=!0,p=setTimeout(()=>ee(e),n?0:Ee)},{immediate:!0}),ce(v);function b(e){e.target.closest(`a`)&&e.preventDefault()}return(e,t)=>(u(),m(`div`,{class:C([`diagram-preview`,`layout-${x(n)}`])},[D(`div`,ve,[D(`span`,null,[t[0]||=D(`i`,{class:`iconoir-eye`},null,-1),t[1]||=g(` Preview`,-1),a.value?(u(),m(s,{key:0},[g(` hidden`)],64)):E(``,!0)]),D(`span`,ye,[d.value&&!a.value?(u(),m(`span`,be,`Rendering…`)):E(``,!0),D(`span`,xe,[(u(!0),m(s,null,y(o.filter(e=>!a.value||e.value!==`hidden`),e=>(u(),m(`button`,{key:e.value,type:`button`,class:C({active:x(n)===e.value}),"aria-pressed":x(n)===e.value,title:e.label,"aria-label":e.label,onClick:t=>x(i)(e.value)},[D(`i`,{class:C(e.icon)},null,2)],10,Se))),128))])])]),a.value?E(``,!0):(u(),m(s,{key:0},[l.value?(u(),m(`div`,Ce,[t[2]||=D(`i`,{class:`iconoir-warning-triangle`},null,-1),g(` `+r(l.value),1)])):E(``,!0),c.value?(u(),m(`div`,{key:1,class:C([`preview-body`,{stale:!!l.value}]),title:`Links are disabled in the preview`,onClick:b,innerHTML:c.value},null,10,we)):!l.value&&!d.value?(u(),m(`p`,Te,`Nothing to preview yet.`)):E(``,!0)],64))],2))}},[[`__scopeId`,`data-v-11568657`]]),Oe={class:`label-row`},ke=[`for`,`title`],Ae={key:0,class:`required`},je=[`id`,`aria-invalid`],Me=[`value`],Ne=[`id`,`aria-invalid`,`placeholder`],Pe={key:0,class:`future-hint`},Fe={class:`code-source`},Ie=[`id`,`aria-invalid`,`placeholder`],Le={class:`future-hint`},Re=[`id`,`step`,`aria-invalid`],ze=[`id`,`aria-invalid`],Be=[`id`,`aria-invalid`],Ve=[`id`,`aria-invalid`],He={key:7,class:`field-description`},Ue={key:8,class:`field-error`},We=ae({__name:`EditorField`,props:{field:Object,modelValue:[String,Number,null],error:[Array,null]},emits:[`update:modelValue`,`openMarkdown`],setup(e,{emit:t}){let n=e,a=t,c=h({get:()=>n.modelValue??``,set:e=>a(`update:modelValue`,e)}),l=h(()=>[`textarea`,`markdown`,`code`].includes(n.field.input_type)),f=h(()=>n.field.key===`page/content`),p=h(()=>n.field.code_language===`asd`),{layout:_}=_e(),ee={asd:`Archsight Diagram`},b=h(()=>{let e=n.field.code_language||``;return ee[e]||e.charAt(0).toUpperCase()+e.slice(1)}),S=h(()=>n.error&&n.error.length>0);return(t,n)=>(u(),m(`div`,{class:C([`field-group`,{"field-full-width":l.value}])},[D(`div`,Oe,[D(`label`,{for:e.field.key,title:e.field.description},[g(r(e.field.title)+` `,1),e.field.required?(u(),m(`span`,Ae,`*`)):E(``,!0)],8,ke),e.field.input_type===`markdown`?(u(),m(`button`,{key:0,type:`button`,class:`btn-edit-markdown`,title:`Open rich text editor`,onClick:n[0]||=n=>t.$emit(`openMarkdown`,e.field.key)},[...n[8]||=[D(`i`,{class:`iconoir-edit-pencil`},null,-1),g(` Edit `,-1)]])):E(``,!0)]),e.field.input_type===`select`?d((u(),m(`select`,{key:0,id:e.field.key,"onUpdate:modelValue":n[1]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0},[n[9]||=D(`option`,{value:``},`Select...`,-1),(u(!0),m(s,null,y(e.field.options,e=>(u(),m(`option`,{key:e,value:e},r(e),9,Me))),128))],8,je)),[[v,c.value]]):e.field.input_type===`textarea`||e.field.input_type===`markdown`?(u(),m(`div`,{key:1,class:C([`markdown-field`,{"page-body":f.value}])},[d(D(`textarea`,{id:e.field.key,"onUpdate:modelValue":n[2]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0,placeholder:e.field.input_type===`markdown`?`Enter markdown content...`:`One entry per line...`},null,8,Ne),[[o,c.value]]),e.field.input_type===`markdown`?(u(),m(`small`,Pe,[...n[10]||=[D(`i`,{class:`iconoir-info-circle`},null,-1),g(` Markdown, `,-1),D(`code`,null,`[[links]]`,-1),g(` and `,-1),D(`code`,null,"```asd",-1),g(` diagrams. Use Edit for the rich text editor `,-1)]])):E(``,!0)],2)):e.field.input_type===`code`?(u(),m(`div`,{key:2,class:C([`code-field`,p.value&&[`with-preview`,`layout-${x(_)}`]])},[D(`div`,Fe,[d(D(`textarea`,{id:e.field.key,"onUpdate:modelValue":n[3]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0,placeholder:`Enter ${e.field.code_language||``} code...`,spellcheck:`false`},null,8,Ie),[[o,c.value]]),D(`small`,Le,[n[11]||=D(`i`,{class:`iconoir-code`},null,-1),g(` `+r(b.value)+` code `,1)])]),p.value?(u(),i(De,{key:0,class:`field-diagram-preview`,source:String(c.value)},null,8,[`source`])):E(``,!0)],2)):e.field.input_type===`number`?d((u(),m(`input`,{key:3,id:e.field.key,type:`number`,"onUpdate:modelValue":n[4]||=e=>c.value=e,step:e.field.step,"aria-invalid":S.value?`true`:void 0},null,8,Re)),[[o,c.value]]):e.field.input_type===`url`?d((u(),m(`input`,{key:4,id:e.field.key,type:`url`,"onUpdate:modelValue":n[5]||=e=>c.value=e,placeholder:`https://...`,"aria-invalid":S.value?`true`:void 0},null,8,ze)),[[o,c.value]]):e.field.input_type===`list`?d((u(),m(`input`,{key:5,id:e.field.key,type:`text`,"onUpdate:modelValue":n[6]||=e=>c.value=e,placeholder:`Comma-separated values`,"aria-invalid":S.value?`true`:void 0},null,8,Be)),[[o,c.value]]):d((u(),m(`input`,{key:6,id:e.field.key,type:`text`,"onUpdate:modelValue":n[7]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0},null,8,Ve)),[[o,c.value]]),e.field.description&&![`textarea`,`markdown`,`code`].includes(e.field.input_type)?(u(),m(`small`,He,r(e.field.description),1)):E(``,!0),S.value?(u(),m(`div`,Ue,r(e.error.join(`, `)),1)):E(``,!0)],2))}},[[`__scopeId`,`data-v-fe1221de`]]),Ge={class:`relations-editor`},Ke={key:0,class:`no-relations`},qe={id:`relations-list`},Je={class:`relation-text`},Ye=[`onClick`],Xe={class:`add-relation-row`},Ze=[`value`],Qe=[`value`],$e=ae({__name:`EditorRelations`,props:{relations:Array,relationOptions:Array,instancesByKind:Object},emits:[`update:relations`],setup(e,{emit:t}){let n=e,i=t,a=S(``),o=S(``),c=h(()=>[...n.relations].sort((e,t)=>(e.verb+e.kind+e.name).localeCompare(t.verb+t.kind+t.name))),l=h(()=>a.value?n.relationOptions.find(e=>e.combo===a.value)?.target_kind:null),p=h(()=>l.value&&n.instancesByKind[l.value]||[]);f(a,()=>{o.value=``});function _(){if(!a.value||!o.value)return;let e=n.relationOptions.find(e=>e.combo===a.value);if(!e||n.relations.some(t=>t.verb===e.verb&&t.kind===e.target_kind&&t.name===o.value))return;let t=[...n.relations,{verb:e.verb,kind:e.target_kind,name:o.value}];i(`update:relations`,t),a.value=``,o.value=``}function ee(e){let t=n.relations.filter((t,n)=>n!==e);i(`update:relations`,t)}return(t,n)=>(u(),m(`div`,Ge,[!e.relationOptions||e.relationOptions.length===0?(u(),m(`p`,Ke,` This resource type has no defined relations. `)):(u(),m(s,{key:1},[D(`div`,qe,[(u(!0),m(s,null,y(c.value,(e,t)=>(u(),m(`div`,{key:`${e.verb}:${e.kind}:${e.name}`,class:`relation-item`},[D(`span`,Je,[D(`strong`,null,r(e.verb),1),g(` → `+r(e.kind)+`: `,1),D(`em`,null,r(e.name),1)]),D(`button`,{class:`btn-remove`,type:`button`,title:`Remove`,onClick:e=>ee(t)},[...n[2]||=[D(`i`,{class:`iconoir-xmark`},null,-1)]],8,Ye)]))),128))]),D(`div`,Xe,[d(D(`select`,{"onUpdate:modelValue":n[0]||=e=>a.value=e},[n[3]||=D(`option`,{value:``},`Select relation...`,-1),(u(!0),m(s,null,y(e.relationOptions,e=>(u(),m(`option`,{key:e.combo,value:e.combo},r(e.verb)+` → `+r(e.target_kind),9,Ze))),128))],512),[[v,a.value]]),d(D(`select`,{"onUpdate:modelValue":n[1]||=e=>o.value=e},[n[4]||=D(`option`,{value:``},`Select instance...`,-1),(u(!0),m(s,null,y(p.value,e=>(u(),m(`option`,{key:e,value:e},r(e),9,Qe))),128))],512),[[v,o.value]]),D(`button`,{class:`secondary btn-add`,type:`button`,onClick:_},[...n[5]||=[D(`i`,{class:`iconoir-plus`},null,-1),g(` Add `,-1)]])])],64))]))}},[[`__scopeId`,`data-v-a987a6fe`]]),et={class:`yaml-output-container`},tt={key:0,class:`conflict-error`},nt={class:`yaml-success`},rt={id:`yaml-content`},it={key:0,class:`yaml-file-info`},at={key:1,class:`yaml-instructions`},ot={class:`yaml-actions`},st=[`disabled`],ct=ae({__name:`EditorYamlOutput`,props:{yaml:String,format:{type:String,default:`yaml`},kind:String,name:String,contentHash:String,pathRef:String,inlineEditEnabled:Boolean},emits:[`editAgain`],setup(e,{emit:t}){let i=e,o=S(null),c=S(`idle`),l=S(`idle`),d=S(null),p=h(()=>i.format===`markdown`),v=h(()=>p.value?`Markdown`:`YAML`),ee=h(()=>p.value?`.md`:`.yaml`);a(()=>{o.value&&n(o.value)}),f(()=>i.yaml,async()=>{await _(),o.value&&n(o.value)});async function y(){try{await navigator.clipboard.writeText(i.yaml),c.value=`copied`,setTimeout(()=>{c.value=`idle`},2e3)}catch{let e=document.createElement(`textarea`);e.value=i.yaml,e.style.position=`fixed`,e.style.opacity=`0`,document.body.appendChild(e),e.select(),document.execCommand(`copy`),document.body.removeChild(e),c.value=`copied`,setTimeout(()=>{c.value=`idle`},2e3)}}async function b(){l.value=`saving`,d.value=null;try{let e=await oe(i.kind,i.name,i.yaml,i.contentHash);e.success?(l.value=`saved`,setTimeout(()=>{l.value=`idle`},2e3)):e.conflict?(d.value=e.error,l.value=`idle`):(alert(`Save failed: `+e.error),l.value=`idle`)}catch(e){alert(`Save failed: `+e.message),l.value=`idle`}}return(t,n)=>(u(),m(`div`,et,[d.value?(u(),m(`div`,tt,[n[1]||=D(`i`,{class:`iconoir-warning-triangle`},null,-1),D(`span`,null,r(d.value),1)])):E(``,!0),D(`p`,nt,[n[2]||=D(`i`,{class:`iconoir-check-circle`},null,-1),g(` Generated `+r(v.value),1)]),D(`div`,{ref_key:`codeEl`,ref:o},[D(`pre`,rt,[D(`code`,{class:C(`language-${e.format}`)},r(e.yaml),3)])],512),D(`footer`,null,[e.pathRef?(u(),m(`p`,it,[n[3]||=D(`i`,{class:`iconoir-folder`},null,-1),D(`span`,null,`Source: `+r(e.pathRef),1)])):(u(),m(`p`,at,[n[10]||=D(`i`,{class:`iconoir-info-circle`},null,-1),D(`span`,null,[g(` Copy this `+r(v.value)+` and save it to a `,1),D(`code`,null,r(ee.value),1),n[6]||=g(` file in your resources directory`,-1),p.value?(u(),m(s,{key:0},[n[4]||=g(` (named `,-1),D(`code`,null,r(e.name)+`.md`,1),n[5]||=g(`)`,-1)],64)):E(``,!0),n[7]||=g(`, `,-1),n[8]||=D(`br`,null,null,-1),n[9]||=g(`then reload the application. `,-1)])])),D(`div`,ot,[e.pathRef&&e.inlineEditEnabled?(u(),m(`button`,{key:0,type:`button`,onClick:b,disabled:l.value===`saving`,class:C({saved:l.value===`saved`})},[D(`i`,{class:C(l.value===`saving`?`iconoir-refresh`:l.value===`saved`?`iconoir-check`:`iconoir-check-circle`)},null,2),g(` `+r(l.value===`saving`?`Saving...`:l.value===`saved`?`Saved!`:`Save to File`),1)],10,st)):E(``,!0),D(`button`,{type:`button`,onClick:y,class:C({copied:c.value===`copied`})},[D(`i`,{class:C(c.value===`copied`?`iconoir-check`:`iconoir-copy`)},null,2),g(` `+r(c.value===`copied`?`Copied!`:`Copy to Clipboard`),1)],2),D(`button`,{class:`secondary`,type:`button`,onClick:n[0]||=e=>t.$emit(`editAgain`)},[...n[11]||=[D(`i`,{class:`iconoir-edit-pencil`},null,-1),g(` Edit Again `,-1)]])])])]))}},[[`__scopeId`,`data-v-b5ea938f`]]);function O(e,...t){let n=new URL(`https://lexical.dev/docs/error`),r=new URLSearchParams;r.append(`code`,e);for(let e of t)r.append(`v`,e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function lt(e,...t){let n=new URL(`https://lexical.dev/docs/error`),r=new URLSearchParams;r.append(`code`,e);for(let e of t)r.append(`v`,e);n.search=r.toString(),console.warn(`Minified Lexical warning #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}var ut=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0,dt=ut&&`documentMode`in document?document.documentMode:null,ft=ut&&/Mac|iPod|iPhone|iPad/.test(navigator.platform),pt=ut&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent),mt=!(!ut||!(`InputEvent`in window)||dt)&&`getTargetRanges`in new window.InputEvent(`input`),ht=ut&&/Version\/[\d.]+.*Safari/.test(navigator.userAgent),gt=ut&&/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream,_t=ut&&/Android/.test(navigator.userAgent),vt=ut&&/^(?=.*Chrome).*/i.test(navigator.userAgent),yt=ut&&_t&&vt,bt=ut&&/AppleWebKit\/[\d.]+/.test(navigator.userAgent)&&ft&&!vt,xt=0,St=1,Ct=2,wt=1,Tt=2,Et=3,Dt=4,Ot=5,kt=6,At=ht||gt||bt?`\xA0`:`​`,jt=`
1
+ import{i as e,n as t,t as n}from"./useHighlight-D5Gf8DLl.js";import{$ as r,A as i,B as a,C as o,E as s,F as c,G as l,H as u,J as d,K as f,L as p,M as m,O as h,P as g,R as _,S as v,T as ee,U as y,V as b,X as x,Y as S,Z as C,_ as w,a as T,c as te,j as E,k as D,l as ne,o as re,q as ie,t as ae,v as oe,x as se,z as ce}from"./index-BXXkUK1V.js";var le=`archsight.diagramPreview.layout`,ue=[`bottom`,`right`,`full`,`hidden`],de=`(min-width: 1400px)`;function fe(){try{let e=localStorage.getItem(le);return ue.includes(e)?e:null}catch{return null}}var pe=S(fe()),me=S(typeof matchMedia==`function`&&matchMedia(de).matches);typeof matchMedia==`function`&&matchMedia(de).addEventListener(`change`,e=>{me.value=e.matches});var he=h(()=>pe.value||(me.value?`right`:`bottom`));function ge(e){if(ue.includes(e)){pe.value=e;try{localStorage.setItem(le,e)}catch{}}}function _e(){return{layout:he,setLayout:ge}}var ve={class:`preview-head`},ye={class:`preview-tools`},be={key:0,class:`preview-state`},xe={class:`preview-layout`,role:`group`,"aria-label":`Preview layout`},Se=[`aria-pressed`,`title`,`aria-label`,`onClick`],Ce={key:0,class:`preview-error`,role:`alert`},we=[`innerHTML`],Te={key:2,class:`preview-empty`},Ee=300,De=ae({__name:`DiagramPreview`,props:{source:String},setup(e){let t=e,{layout:n,setLayout:i}=_e(),a=h(()=>n.value===`hidden`),o=[{value:`bottom`,icon:`iconoir-table-rows`,label:`Below the editor`},{value:`right`,icon:`iconoir-view-columns-2`,label:`Right of the editor`},{value:`full`,icon:`iconoir-expand`,label:`Preview only`},{value:`hidden`,icon:`iconoir-eye-closed`,label:`Hide preview`}],c=S(``),l=S(null),d=S(!1),p=null,_=null;function v(){clearTimeout(p),p=null,_?.abort(),_=null}async function ee(e){_=new AbortController;let t=_;d.value=!0;try{let n=await w(e,{signal:t.signal});if(t!==_)return;n.html&&(c.value=n.html),l.value=n.error}catch(e){if(e.name===`AbortError`||t!==_)return;l.value=e.message}finally{t===_&&(d.value=!1)}}f([()=>t.source,a],([e,t],[,n])=>{if(v(),t){d.value=!1;return}if(!e||!e.trim()){c.value=``,l.value=null,d.value=!1;return}d.value=!0,p=setTimeout(()=>ee(e),n?0:Ee)},{immediate:!0}),ce(v);function b(e){e.target.closest(`a`)&&e.preventDefault()}return(e,t)=>(u(),m(`div`,{class:C([`diagram-preview`,`layout-${x(n)}`])},[D(`div`,ve,[D(`span`,null,[t[0]||=D(`i`,{class:`iconoir-eye`},null,-1),t[1]||=g(` Preview`,-1),a.value?(u(),m(s,{key:0},[g(` hidden`)],64)):E(``,!0)]),D(`span`,ye,[d.value&&!a.value?(u(),m(`span`,be,`Rendering…`)):E(``,!0),D(`span`,xe,[(u(!0),m(s,null,y(o.filter(e=>!a.value||e.value!==`hidden`),e=>(u(),m(`button`,{key:e.value,type:`button`,class:C({active:x(n)===e.value}),"aria-pressed":x(n)===e.value,title:e.label,"aria-label":e.label,onClick:t=>x(i)(e.value)},[D(`i`,{class:C(e.icon)},null,2)],10,Se))),128))])])]),a.value?E(``,!0):(u(),m(s,{key:0},[l.value?(u(),m(`div`,Ce,[t[2]||=D(`i`,{class:`iconoir-warning-triangle`},null,-1),g(` `+r(l.value),1)])):E(``,!0),c.value?(u(),m(`div`,{key:1,class:C([`preview-body`,{stale:!!l.value}]),title:`Links are disabled in the preview`,onClick:b,innerHTML:c.value},null,10,we)):!l.value&&!d.value?(u(),m(`p`,Te,`Nothing to preview yet.`)):E(``,!0)],64))],2))}},[[`__scopeId`,`data-v-11568657`]]),Oe={class:`label-row`},ke=[`for`,`title`],Ae={key:0,class:`required`},je=[`id`,`aria-invalid`],Me=[`value`],Ne=[`id`,`aria-invalid`,`placeholder`],Pe={key:0,class:`future-hint`},Fe={class:`code-source`},Ie=[`id`,`aria-invalid`,`placeholder`],Le={class:`future-hint`},Re=[`id`,`step`,`aria-invalid`],ze=[`id`,`aria-invalid`],Be=[`id`,`aria-invalid`],Ve=[`id`,`aria-invalid`],He={key:7,class:`field-description`},Ue={key:8,class:`field-error`},We=ae({__name:`EditorField`,props:{field:Object,modelValue:[String,Number,null],error:[Array,null]},emits:[`update:modelValue`,`openMarkdown`],setup(e,{emit:t}){let n=e,a=t,c=h({get:()=>n.modelValue??``,set:e=>a(`update:modelValue`,e)}),l=h(()=>[`textarea`,`markdown`,`code`].includes(n.field.input_type)),f=h(()=>n.field.key===`page/content`),p=h(()=>n.field.code_language===`asd`),{layout:_}=_e(),ee={asd:`Archsight Diagram`},b=h(()=>{let e=n.field.code_language||``;return ee[e]||e.charAt(0).toUpperCase()+e.slice(1)}),S=h(()=>n.error&&n.error.length>0);return(t,n)=>(u(),m(`div`,{class:C([`field-group`,{"field-full-width":l.value}])},[D(`div`,Oe,[D(`label`,{for:e.field.key,title:e.field.description},[g(r(e.field.title)+` `,1),e.field.required?(u(),m(`span`,Ae,`*`)):E(``,!0)],8,ke),e.field.input_type===`markdown`?(u(),m(`button`,{key:0,type:`button`,class:`btn-edit-markdown`,title:`Open rich text editor`,onClick:n[0]||=n=>t.$emit(`openMarkdown`,e.field.key)},[...n[8]||=[D(`i`,{class:`iconoir-edit-pencil`},null,-1),g(` Edit `,-1)]])):E(``,!0)]),e.field.input_type===`select`?d((u(),m(`select`,{key:0,id:e.field.key,"onUpdate:modelValue":n[1]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0},[n[9]||=D(`option`,{value:``},`Select...`,-1),(u(!0),m(s,null,y(e.field.options,e=>(u(),m(`option`,{key:e,value:e},r(e),9,Me))),128))],8,je)),[[v,c.value]]):e.field.input_type===`textarea`||e.field.input_type===`markdown`?(u(),m(`div`,{key:1,class:C([`markdown-field`,{"page-body":f.value}])},[d(D(`textarea`,{id:e.field.key,"onUpdate:modelValue":n[2]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0,placeholder:e.field.input_type===`markdown`?`Enter markdown content...`:`One entry per line...`},null,8,Ne),[[o,c.value]]),e.field.input_type===`markdown`?(u(),m(`small`,Pe,[...n[10]||=[D(`i`,{class:`iconoir-info-circle`},null,-1),g(` Markdown, `,-1),D(`code`,null,`[[links]]`,-1),g(` and `,-1),D(`code`,null,"```asd",-1),g(` diagrams. Use Edit for the rich text editor `,-1)]])):E(``,!0)],2)):e.field.input_type===`code`?(u(),m(`div`,{key:2,class:C([`code-field`,p.value&&[`with-preview`,`layout-${x(_)}`]])},[D(`div`,Fe,[d(D(`textarea`,{id:e.field.key,"onUpdate:modelValue":n[3]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0,placeholder:`Enter ${e.field.code_language||``} code...`,spellcheck:`false`},null,8,Ie),[[o,c.value]]),D(`small`,Le,[n[11]||=D(`i`,{class:`iconoir-code`},null,-1),g(` `+r(b.value)+` code `,1)])]),p.value?(u(),i(De,{key:0,class:`field-diagram-preview`,source:String(c.value)},null,8,[`source`])):E(``,!0)],2)):e.field.input_type===`number`?d((u(),m(`input`,{key:3,id:e.field.key,type:`number`,"onUpdate:modelValue":n[4]||=e=>c.value=e,step:e.field.step,"aria-invalid":S.value?`true`:void 0},null,8,Re)),[[o,c.value]]):e.field.input_type===`url`?d((u(),m(`input`,{key:4,id:e.field.key,type:`url`,"onUpdate:modelValue":n[5]||=e=>c.value=e,placeholder:`https://...`,"aria-invalid":S.value?`true`:void 0},null,8,ze)),[[o,c.value]]):e.field.input_type===`list`?d((u(),m(`input`,{key:5,id:e.field.key,type:`text`,"onUpdate:modelValue":n[6]||=e=>c.value=e,placeholder:`Comma-separated values`,"aria-invalid":S.value?`true`:void 0},null,8,Be)),[[o,c.value]]):d((u(),m(`input`,{key:6,id:e.field.key,type:`text`,"onUpdate:modelValue":n[7]||=e=>c.value=e,"aria-invalid":S.value?`true`:void 0},null,8,Ve)),[[o,c.value]]),e.field.description&&![`textarea`,`markdown`,`code`].includes(e.field.input_type)?(u(),m(`small`,He,r(e.field.description),1)):E(``,!0),S.value?(u(),m(`div`,Ue,r(e.error.join(`, `)),1)):E(``,!0)],2))}},[[`__scopeId`,`data-v-fe1221de`]]),Ge={class:`relations-editor`},Ke={key:0,class:`no-relations`},qe={id:`relations-list`},Je={class:`relation-text`},Ye=[`onClick`],Xe={class:`add-relation-row`},Ze=[`value`],Qe=[`value`],$e=ae({__name:`EditorRelations`,props:{relations:Array,relationOptions:Array,instancesByKind:Object},emits:[`update:relations`],setup(e,{emit:t}){let n=e,i=t,a=S(``),o=S(``),c=h(()=>[...n.relations].sort((e,t)=>(e.verb+e.kind+e.name).localeCompare(t.verb+t.kind+t.name))),l=h(()=>a.value?n.relationOptions.find(e=>e.combo===a.value)?.target_kind:null),p=h(()=>l.value&&n.instancesByKind[l.value]||[]);f(a,()=>{o.value=``});function _(){if(!a.value||!o.value)return;let e=n.relationOptions.find(e=>e.combo===a.value);if(!e||n.relations.some(t=>t.verb===e.verb&&t.kind===e.target_kind&&t.name===o.value))return;let t=[...n.relations,{verb:e.verb,kind:e.target_kind,name:o.value}];i(`update:relations`,t),a.value=``,o.value=``}function ee(e){let t=n.relations.filter((t,n)=>n!==e);i(`update:relations`,t)}return(t,n)=>(u(),m(`div`,Ge,[!e.relationOptions||e.relationOptions.length===0?(u(),m(`p`,Ke,` This resource type has no defined relations. `)):(u(),m(s,{key:1},[D(`div`,qe,[(u(!0),m(s,null,y(c.value,(e,t)=>(u(),m(`div`,{key:`${e.verb}:${e.kind}:${e.name}`,class:`relation-item`},[D(`span`,Je,[D(`strong`,null,r(e.verb),1),g(` → `+r(e.kind)+`: `,1),D(`em`,null,r(e.name),1)]),D(`button`,{class:`btn-remove`,type:`button`,title:`Remove`,onClick:e=>ee(t)},[...n[2]||=[D(`i`,{class:`iconoir-xmark`},null,-1)]],8,Ye)]))),128))]),D(`div`,Xe,[d(D(`select`,{"onUpdate:modelValue":n[0]||=e=>a.value=e},[n[3]||=D(`option`,{value:``},`Select relation...`,-1),(u(!0),m(s,null,y(e.relationOptions,e=>(u(),m(`option`,{key:e.combo,value:e.combo},r(e.verb)+` → `+r(e.target_kind),9,Ze))),128))],512),[[v,a.value]]),d(D(`select`,{"onUpdate:modelValue":n[1]||=e=>o.value=e},[n[4]||=D(`option`,{value:``},`Select instance...`,-1),(u(!0),m(s,null,y(p.value,e=>(u(),m(`option`,{key:e,value:e},r(e),9,Qe))),128))],512),[[v,o.value]]),D(`button`,{class:`secondary btn-add`,type:`button`,onClick:_},[...n[5]||=[D(`i`,{class:`iconoir-plus`},null,-1),g(` Add `,-1)]])])],64))]))}},[[`__scopeId`,`data-v-a987a6fe`]]),et={class:`yaml-output-container`},tt={key:0,class:`conflict-error`},nt={class:`yaml-success`},rt={id:`yaml-content`},it={key:0,class:`yaml-file-info`},at={key:1,class:`yaml-instructions`},ot={class:`yaml-actions`},st=[`disabled`],ct=ae({__name:`EditorYamlOutput`,props:{yaml:String,format:{type:String,default:`yaml`},kind:String,name:String,contentHash:String,pathRef:String,inlineEditEnabled:Boolean},emits:[`editAgain`],setup(e,{emit:t}){let i=e,o=S(null),c=S(`idle`),l=S(`idle`),d=S(null),p=h(()=>i.format===`markdown`),v=h(()=>p.value?`Markdown`:`YAML`),ee=h(()=>p.value?`.md`:`.yaml`);a(()=>{o.value&&n(o.value)}),f(()=>i.yaml,async()=>{await _(),o.value&&n(o.value)});async function y(){try{await navigator.clipboard.writeText(i.yaml),c.value=`copied`,setTimeout(()=>{c.value=`idle`},2e3)}catch{let e=document.createElement(`textarea`);e.value=i.yaml,e.style.position=`fixed`,e.style.opacity=`0`,document.body.appendChild(e),e.select(),document.execCommand(`copy`),document.body.removeChild(e),c.value=`copied`,setTimeout(()=>{c.value=`idle`},2e3)}}async function b(){l.value=`saving`,d.value=null;try{let e=await oe(i.kind,i.name,i.yaml,i.contentHash);e.success?(l.value=`saved`,setTimeout(()=>{l.value=`idle`},2e3)):e.conflict?(d.value=e.error,l.value=`idle`):(alert(`Save failed: `+e.error),l.value=`idle`)}catch(e){alert(`Save failed: `+e.message),l.value=`idle`}}return(t,n)=>(u(),m(`div`,et,[d.value?(u(),m(`div`,tt,[n[1]||=D(`i`,{class:`iconoir-warning-triangle`},null,-1),D(`span`,null,r(d.value),1)])):E(``,!0),D(`p`,nt,[n[2]||=D(`i`,{class:`iconoir-check-circle`},null,-1),g(` Generated `+r(v.value),1)]),D(`div`,{ref_key:`codeEl`,ref:o},[D(`pre`,rt,[D(`code`,{class:C(`language-${e.format}`)},r(e.yaml),3)])],512),D(`footer`,null,[e.pathRef?(u(),m(`p`,it,[n[3]||=D(`i`,{class:`iconoir-folder`},null,-1),D(`span`,null,`Source: `+r(e.pathRef),1)])):(u(),m(`p`,at,[n[10]||=D(`i`,{class:`iconoir-info-circle`},null,-1),D(`span`,null,[g(` Copy this `+r(v.value)+` and save it to a `,1),D(`code`,null,r(ee.value),1),n[6]||=g(` file in your resources directory`,-1),p.value?(u(),m(s,{key:0},[n[4]||=g(` (named `,-1),D(`code`,null,r(e.name)+`.md`,1),n[5]||=g(`)`,-1)],64)):E(``,!0),n[7]||=g(`, `,-1),n[8]||=D(`br`,null,null,-1),n[9]||=g(`then reload the application. `,-1)])])),D(`div`,ot,[e.pathRef&&e.inlineEditEnabled?(u(),m(`button`,{key:0,type:`button`,onClick:b,disabled:l.value===`saving`,class:C({saved:l.value===`saved`})},[D(`i`,{class:C(l.value===`saving`?`iconoir-refresh`:l.value===`saved`?`iconoir-check`:`iconoir-check-circle`)},null,2),g(` `+r(l.value===`saving`?`Saving...`:l.value===`saved`?`Saved!`:`Save to File`),1)],10,st)):E(``,!0),D(`button`,{type:`button`,onClick:y,class:C({copied:c.value===`copied`})},[D(`i`,{class:C(c.value===`copied`?`iconoir-check`:`iconoir-copy`)},null,2),g(` `+r(c.value===`copied`?`Copied!`:`Copy to Clipboard`),1)],2),D(`button`,{class:`secondary`,type:`button`,onClick:n[0]||=e=>t.$emit(`editAgain`)},[...n[11]||=[D(`i`,{class:`iconoir-edit-pencil`},null,-1),g(` Edit Again `,-1)]])])])]))}},[[`__scopeId`,`data-v-b5ea938f`]]);function O(e,...t){let n=new URL(`https://lexical.dev/docs/error`),r=new URLSearchParams;r.append(`code`,e);for(let e of t)r.append(`v`,e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}function lt(e,...t){let n=new URL(`https://lexical.dev/docs/error`),r=new URLSearchParams;r.append(`code`,e);for(let e of t)r.append(`v`,e);n.search=r.toString(),console.warn(`Minified Lexical warning #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}var ut=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0,dt=ut&&`documentMode`in document?document.documentMode:null,ft=ut&&/Mac|iPod|iPhone|iPad/.test(navigator.platform),pt=ut&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent),mt=!(!ut||!(`InputEvent`in window)||dt)&&`getTargetRanges`in new window.InputEvent(`input`),ht=ut&&/Version\/[\d.]+.*Safari/.test(navigator.userAgent),gt=ut&&/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream,_t=ut&&/Android/.test(navigator.userAgent),vt=ut&&/^(?=.*Chrome).*/i.test(navigator.userAgent),yt=ut&&_t&&vt,bt=ut&&/AppleWebKit\/[\d.]+/.test(navigator.userAgent)&&ft&&!vt,xt=0,St=1,Ct=2,wt=1,Tt=2,Et=3,Dt=4,Ot=5,kt=6,At=ht||gt||bt?`\xA0`:`​`,jt=`
2
2
 
3
3
  `,Mt=pt?`\xA0`:At,Nt=RegExp(`^[^A-Za-zÀ-ÖØ-öø-ʸ̀-֐ࠀ-῿‎Ⰰ-﬜︀-﹯﻽-￿]*[֑-߿יִ-﷽ﹰ-ﻼ]`),Pt=RegExp(`^[^֑-߿יִ-﷽ﹰ-ﻼ]*[A-Za-zÀ-ÖØ-öø-ʸ̀-֐ࠀ-῿‎Ⰰ-﬜︀-﹯﻽-￿]`),Ft={bold:1,capitalize:1024,code:16,highlight:128,italic:2,lowercase:256,strikethrough:4,subscript:32,superscript:64,underline:8,uppercase:512},It={directionless:1,unmergeable:2},Lt={center:2,end:6,justify:4,left:1,right:3,start:5},Rt={[Tt]:`center`,[kt]:`end`,[Dt]:`justify`,[wt]:`left`,[Et]:`right`,[Ot]:`start`},zt={normal:0,segmented:2,token:1},Bt={[xt]:`normal`,[Ct]:`segmented`,[St]:`token`},Vt=`$config`;function Ht(e,t,n,r,i,a){let o=e.getFirstChild();for(;o!==null;){let e=o.__key;o.__parent===t&&(B(o)&&Ht(o,e,n,r,i,a),n.has(e)||a.delete(e),i.push(e)),o=o.getNextSibling()}}var Ut=!1,Wt=0;function Gt(e){Wt=e.timeStamp}function Kt(e,t,n){let r=e.nodeName===`BR`,i=t.__lexicalLineBreak;return i&&(e===i||r&&e.previousSibling===i)||r&&Jo(e,n)!==void 0}function qt(e,t,n){let r=Fs(Ds(n)),i=null,a=null;r!==null&&r.anchorNode===e&&(i=r.anchorOffset,a=r.focusOffset);let o=e.nodeValue;o!==null&&os(t,o,i,a,!1)}function Jt(e,t,n){if(P(e)){let t=e.anchor.getNode();if(t.is(n)&&e.format!==t.getFormat())return!1}return Lo(t)&&n.isAttached()}function Yt(e,t,n,r){for(let i=e;i&&!Xs(i);i=xs(i)){let e=Jo(i,t);if(e!==void 0){let t=W(e,n);if(t)return V(t)||!J(i)?void 0:[i,t]}else if(i===r)return[r,Qo(n)]}}function Xt(e,t,n){Ut=!0;let r=performance.now()-Wt>100;try{no(e,()=>{let i=F()||function(e){return e.getEditorState().read(()=>{let e=F();return e===null?null:e.clone()})}(e),a=new Map,o=e.getRootElement(),s=e._editorState,c=e._blockCursorElement,l=!1,u=``;for(let n=0;n<t.length;n++){let d=t[n],f=d.type,p=d.target,m=Yt(p,e,s,o);if(!m)continue;let[h,g]=m;if(f===`characterData`)r&&N(g)&&Lo(p)&&Jt(i,p,g)&&qt(p,g,e);else if(f===`childList`){l=!0;let t=d.addedNodes;for(let n=0;n<t.length;n++){let r=t[n],i=qo(r),a=r.parentNode;if(a!=null&&r!==c&&i===null&&!Kt(r,a,e)){if(pt){let e=(J(r)?r.innerText:null)||r.nodeValue;e&&(u+=e)}a.removeChild(r)}}let n=d.removedNodes,r=n.length;if(r>0){let t=0;for(let i=0;i<r;i++){let r=n[i];(Kt(r,p,e)||c===r)&&(p.appendChild(r),t++)}r!==t&&a.set(h,g)}}}if(a.size>0)for(let[t,n]of a)n.reconcileObservedMutation(t,e);let d=n.takeRecords();if(d.length>0){for(let t=0;t<d.length;t++){let n=d[t],r=n.addedNodes,i=n.target;for(let t=0;t<r.length;t++){let n=r[t],a=n.parentNode;a==null||n.nodeName!==`BR`||Kt(n,i,e)||a.removeChild(n)}}n.takeRecords()}i!==null&&(l&&$o(i),pt&&ys(e)&&i.insertRawText(u))})}finally{Ut=!1}}function Zt(e){let t=e._observer;t!==null&&Xt(e,t.takeRecords(),t)}function Qt(e){(function(e){Wt===0&&Ds(e).addEventListener(`textInput`,Gt,!0)})(e),e._observer=new MutationObserver((t,n)=>{Xt(e,t,n)})}var $t=class{key;parse;unparse;isEqual;defaultValue;constructor(e,t){this.key=e,this.parse=t.parse.bind(t),this.unparse=(t.unparse||ln).bind(t),this.isEqual=(t.isEqual||Object.is).bind(t),this.defaultValue=this.parse(void 0)}};function en(e,t){return new $t(e,t)}function tn(e,t,n=`latest`){let r=(n===`latest`?e.getLatest():e).__state;return r?r.getValue(t):t.defaultValue}function nn(e,t,n){let r;if(R(),typeof n==`function`){let i=e.getLatest(),a=tn(i,t);if(r=n(a),t.isEqual(a,r))return i}else r=n;let i=e.getWritable();return on(i).updateFromKnown(t,r),i}function rn(e){let t=new Map,n=new Set;for(let r=typeof e==`function`?e:e.replace;r.prototype&&r.prototype.getType!==void 0;r=Object.getPrototypeOf(r)){let{ownNodeConfig:e}=Qs(r);if(e&&e.stateConfigs)for(let r of e.stateConfigs){let e;`stateConfig`in r?(e=r.stateConfig,r.flat&&n.add(e.key)):e=r,t.set(e.key,e)}}return{flatKeys:n,sharedConfigMap:t}}var an=class e{node;knownState;unknownState;sharedNodeState;size;constructor(e,t,n=void 0,r=new Map,i=void 0){this.node=e,this.sharedNodeState=t,this.unknownState=n,this.knownState=r;let{sharedConfigMap:a}=this.sharedNodeState,o=i===void 0?function(e,t,n){let r=n.size;if(t)for(let i in t){let t=e.get(i);t&&n.has(t)||r++}return r}(a,n,r):i;this.size=o}getValue(e){let t=this.knownState.get(e);if(t!==void 0)return t;this.sharedNodeState.sharedConfigMap.set(e.key,e);let n=e.defaultValue;if(this.unknownState&&e.key in this.unknownState){let t=this.unknownState[e.key];t!==void 0&&(n=e.parse(t)),this.updateFromKnown(e,n)}return n}getInternalState(){return[this.unknownState,this.knownState]}toJSON(){let e={...this.unknownState},t={};for(let[t,n]of this.knownState)t.isEqual(n,t.defaultValue)?delete e[t.key]:e[t.key]=t.unparse(n);for(let n of this.sharedNodeState.flatKeys)n in e&&(t[n]=e[n],delete e[n]);return cn(e)&&(t.$=e),t}getWritable(t){if(this.node===t)return this;let{sharedNodeState:n,unknownState:r}=this,i=new Map(this.knownState);return new e(t,n,function(e,t,n){let r;if(n)for(let[i,a]of Object.entries(n)){let n=e.get(i);n?t.has(n)||t.set(n,n.parse(a)):(r||={},r[i]=a)}return r}(n.sharedConfigMap,i,r),i,this.size)}updateFromKnown(e,t){let n=e.key;this.sharedNodeState.sharedConfigMap.set(n,e);let{knownState:r,unknownState:i}=this;r.has(e)||i&&n in i||(i&&(delete i[n],this.unknownState=cn(i)),this.size++),r.set(e,t)}updateFromUnknown(e,t){let n=this.sharedNodeState.sharedConfigMap.get(e);n?this.updateFromKnown(n,n.parse(t)):(this.unknownState=this.unknownState||{},e in this.unknownState||this.size++,this.unknownState[e]=t)}updateFromJSON(e){let{knownState:t}=this;for(let e of t.keys())t.set(e,e.defaultValue);if(this.size=t.size,this.unknownState=void 0,e)for(let[t,n]of Object.entries(e))this.updateFromUnknown(t,n)}};function on(e){let t=e.getWritable(),n=t.__state?t.__state.getWritable(t):new an(t,sn(t));return t.__state=n,n}function sn(e){return e.__state?e.__state.sharedNodeState:To(Us(),e.getType()).sharedNodeState}function cn(e){if(e)for(let t in e)return e}function ln(e){return e}function un(e,t,n){for(let[r,i]of t.knownState){if(e.has(r.key))continue;e.add(r.key);let t=n?n.getValue(r):r.defaultValue;if(t!==i&&!r.isEqual(t,i))return!0}return!1}function dn(e,t,n){let{unknownState:r}=t,i=n?n.unknownState:void 0;if(r){for(let[t,n]of Object.entries(r))if(!e.has(t)&&(e.add(t),n!==(i?i[t]:void 0)))return!0}return!1}function fn(e,t){let n=e.__state;return n&&n.node===e?n.getWritable(t):n}function pn(e,t){let n=e.__mode,r=e.__format,i=e.__style,a=t.__mode,o=t.__format,s=t.__style,c=e.__state,l=t.__state;return(n===null||n===a)&&(r===null||r===o)&&(i===null||i===s)&&(e.__state===null||c===l||function(e,t){if(e===t)return!0;if(e&&t&&e.size!==t.size)return!1;let n=new Set;return!(e&&un(n,e,t)||t&&un(n,t,e)||e&&dn(n,e,t)||t&&dn(n,t,e))}(c,l))}function mn(e,t){let n=e.mergeWithSibling(t),r=z()._normalizedNodes;return r.add(e.__key),r.add(t.__key),n}function hn(e){let t,n,r=e;if(r.__text!==``||!r.isSimpleText()||r.isUnmergeable()){for(;(t=r.getPreviousSibling())!==null&&N(t)&&t.isSimpleText()&&!t.isUnmergeable();){if(t.__text!==``){if(pn(t,r)){r=mn(t,r);break}break}t.remove()}for(;(n=r.getNextSibling())!==null&&N(n)&&n.isSimpleText()&&!n.isUnmergeable();){if(n.__text!==``){if(pn(r,n)){r=mn(r,n);break}break}n.remove()}}else r.remove()}function gn(e){return _n(e.anchor),_n(e.focus),e}function _n(e){for(;e.type===`element`;){let t=e.getNode(),n=e.offset,r,i;if(n===t.getChildrenSize()?(r=t.getChildAtIndex(n-1),i=!0):(r=t.getChildAtIndex(n),i=!1),N(r)){e.set(r.__key,i?r.getTextContentSize():0,`text`,!0);break}if(!B(r))break;e.set(r.__key,i?r.getChildrenSize():0,`element`,!0)}}var vn,yn,bn,xn,Sn,Cn,wn,Tn,En,Dn,k=``,On=null,kn=null,An=!1,jn=!1;function Mn(e,t){let n=wn.get(e);if(t!==null){let n=Xn(e);n.parentNode===t&&t.removeChild(n)}if(Tn.has(e)||yn._keyToDOMMap.delete(e),B(n)){let e=Wn(n,wn);Nn(e,0,e.length-1,null)}n!==void 0&&gs(Dn,bn,xn,n,`destroyed`)}function Nn(e,t,n,r){for(let i=t;i<=n;++i){let t=e[i];t!==void 0&&Mn(t,r)}}function Pn(e,t){e.setProperty(`text-align`,t)}var Fn=`40px`;function In(e,t){let n=vn.theme.indent;if(typeof n==`string`){let r=e.classList.contains(n);t>0&&!r?e.classList.add(n):t<1&&r&&e.classList.remove(n)}if(t===0)return void e.style.setProperty(`padding-inline-start`,``);let r=getComputedStyle(yn._rootElement||e).getPropertyValue(`--lexical-indent-base-value`)||Fn;e.style.setProperty(`padding-inline-start`,`calc(${t} * ${r})`)}function Ln(e,t){let n=e.style;t===0?Pn(n,``):t===1?Pn(n,`left`):t===2?Pn(n,`center`):t===3?Pn(n,`right`):t===4?Pn(n,`justify`):t===5?Pn(n,`start`):t===6&&Pn(n,`end`)}function Rn(e,t){let n=function(e){let t=e.__dir;if(t!==null)return t;if(H(e))return null;let n=e.getParentOrThrow();return H(n)&&n.__dir===null?`auto`:null}(t);n===null?e.removeAttribute(`dir`):e.dir=n}function zn(e,t){let n=Tn.get(e);n===void 0&&O(60);let r=n.createDOM(vn,yn);if(function(e,t,n){let r=n._keyToDOMMap;(function(e,t,n){let r=`__lexicalKey_${t._key}`;e[r]=n})(t,n,e),r.set(e,t)}(e,r,yn),N(n)?r.setAttribute(`data-lexical-text`,`true`):V(n)&&r.setAttribute(`data-lexical-decorator`,`true`),B(n)){let e=n.__indent,t=n.__size;if(Rn(r,n),e!==0&&In(r,e),t!==0){let e=t-1;Bn(Wn(n,Tn),n,0,e,n.getDOMSlot(r))}let i=n.__format;i!==0&&Ln(r,i),n.isInline()||Hn(null,n,r)}else{let t=n.getTextContent();if(V(n)){let t=n.decorate(yn,vn);t!==null&&Kn(e,t),r.contentEditable=`false`}k+=t}return t!==null&&t.insertChild(r),gs(Dn,bn,xn,n,`created`),r}function Bn(e,t,n,r,i){let a=k;k=``;let o=n;for(;o<=r;++o){zn(e[o],i);let t=Tn.get(e[o]);t!==null&&N(t)?On===null&&(On=t.getFormat(),kn=t.getStyle()):B(t)&&o<r&&!t.isInline()&&(k+=jt)}i.element.__lexicalTextContent=k,k=a+k}function Vn(e,t){if(e){let n=e.__last;if(n){let e=t.get(n);if(e)return j(e)?`line-break`:V(e)&&e.isInline()?`decorator`:null}return`empty`}return null}function Hn(e,t,n){let r=Vn(e,wn),i=Vn(t,Tn);r!==i&&t.getDOMSlot(n).setManagedLineBreak(i)}function Un(e,t,n){var r;On=null,kn=null,function(e,t,n){let r=k,i=e.__size,a=t.__size;k=``;let o=n.element;if(i===1&&a===1){let n=e.__first,r=t.__first;if(n===r)Gn(n,o);else{let e=Xn(n),t=zn(r,null);try{o.replaceChild(t,e)}catch(i){if(typeof i==`object`&&i){let a=`${i.toString()} Parent: ${o.tagName}, new child: {tag: ${t.tagName} key: ${r}}, old child: {tag: ${e.tagName}, key: ${n}}.`;throw Error(a)}throw i}Mn(n,null)}let i=Tn.get(r);N(i)&&On===null&&(On=i.getFormat(),kn=i.getStyle())}else{let r=Wn(e,wn),s=Wn(t,Tn);if(r.length!==i&&O(227),s.length!==a&&O(228),i===0)a!==0&&Bn(s,0,0,a-1,n);else if(a===0){if(i!==0){let e=n.after==null&&n.before==null&&n.element.__lexicalLineBreak==null;Nn(r,0,i-1,e?null:o),e&&(o.textContent=``)}}else(function(e,t,n,r,i,a){let o=r-1,s=i-1,c,l,u=a.getFirstChild(),d=0,f=0;for(;d<=o&&f<=s;){let e=t[d],r=n[f];if(e===r)u=qn(Gn(r,a.element)),d++,f++;else{if(l===void 0&&(l=Jn(n,f)),c===void 0)c=Jn(t,d);else if(!c.has(e)){d++;continue}if(!l.has(e)){u=qn(Xn(e)),Mn(e,a.element),d++,c.delete(e);continue}if(c.has(r)){let e=bs(yn,r);e!==u&&a.withBefore(u).insertChild(e),u=qn(Gn(r,a.element)),d++,f++}else zn(r,a.withBefore(u)),f++}let i=Tn.get(r);i!==null&&N(i)?On===null&&(On=i.getFormat(),kn=i.getStyle()):B(i)&&f<=s&&!i.isInline()&&(k+=jt)}let p=d>o,m=f>s;if(p&&!m){let e=n[s+1],t=e===void 0?null:yn.getElementByKey(e);Bn(n,0,f,s,a.withBefore(t))}else m&&!p&&Nn(t,d,o,a.element)})(0,r,s,i,a,n)}o.__lexicalTextContent=k,k=r+k}(e,t,t.getDOMSlot(n)),r=t,On==null||On===r.__textFormat||jn||r.setTextFormat(On),function(e){kn==null||kn===e.__textStyle||jn||e.setTextStyle(kn)}(t)}function Wn(e,t){let n=[],r=e.__first;for(;r!==null;){let e=t.get(r);e===void 0&&O(101),n.push(r),r=e.__next}return n}function Gn(e,t){let n=wn.get(e),r=Tn.get(e);n!==void 0&&r!==void 0||O(61);let i=An||Cn.has(e)||Sn.has(e),a=bs(yn,e);if(n===r&&!i){let e;if(B(n)){let t=a.__lexicalTextContent;typeof t==`string`?e=t:(e=n.getTextContent(),a.__lexicalTextContent=e)}else e=n.getTextContent();return k+=e,a}if(n!==r&&i&&gs(Dn,bn,xn,r,`updated`),r.updateDOM(n,a,vn)){let n=zn(e,null);return t===null&&O(62),t.replaceChild(n,a),Mn(e,null),n}if(B(n)){B(r)||O(334,e);let t=r.__indent;(An||t!==n.__indent)&&In(a,t);let o=r.__format;if((An||o!==n.__format)&&Ln(a,o),i)Un(n,r,a),H(r)||r.isInline()||Hn(n,r,a);else{let e=a.__lexicalTextContent,t;typeof e==`string`?t=e:(t=n.getTextContent(),a.__lexicalTextContent=t),k+=t}if((An||r.__dir!==n.__dir)&&(Rn(a,r),H(r)&&!An))for(let e of r.getChildren())B(e)&&Rn(bs(yn,e.getKey()),e)}else{let t=r.getTextContent();if(V(r)){let t=r.decorate(yn,vn);t!==null&&Kn(e,t)}k+=t}if(!jn&&H(r)&&r.__cachedText!==k){let e=r.getWritable();e.__cachedText=k,r=e}return a}function Kn(e,t){let n=yn._pendingDecorators,r=yn._decorators;if(n===null){if(r[e]===t)return;n=Xo(yn)}n[e]=t}function qn(e){let t=e.nextSibling;return t!==null&&t===yn._blockCursorElement&&(t=t.nextSibling),t}function Jn(e,t){let n=new Set;for(let r=t;r<e.length;r++)n.add(e[r]);return n}function Yn(e,t,n,r,i,a){k=``,An=r===2,yn=n,vn=n._config,bn=n._nodes,xn=yn._listeners.mutation,Sn=i,Cn=a,wn=e._nodeMap,Tn=t._nodeMap,jn=t._readOnly,En=new Map(n._keyToDOMMap);let o=new Map;return Dn=o,Gn(`root`,null),yn=void 0,bn=void 0,Sn=void 0,Cn=void 0,wn=void 0,Tn=void 0,vn=void 0,En=void 0,Dn=void 0,o}function Xn(e){let t=En.get(e);return t===void 0&&O(75,e),t}function A(e){return{type:e}}var Zn=A(`SELECTION_CHANGE_COMMAND`),Qn=A(`SELECTION_INSERT_CLIPBOARD_NODES_COMMAND`),$n=A(`CLICK_COMMAND`),er=A(`BEFORE_INPUT_COMMAND`),tr=A(`INPUT_COMMAND`),nr=A(`COMPOSITION_START_COMMAND`),rr=A(`COMPOSITION_END_COMMAND`),ir=A(`DELETE_CHARACTER_COMMAND`),ar=A(`INSERT_LINE_BREAK_COMMAND`),or=A(`INSERT_PARAGRAPH_COMMAND`),sr=A(`CONTROLLED_TEXT_INSERTION_COMMAND`),cr=A(`PASTE_COMMAND`),lr=A(`REMOVE_TEXT_COMMAND`),ur=A(`DELETE_WORD_COMMAND`),dr=A(`DELETE_LINE_COMMAND`),fr=A(`FORMAT_TEXT_COMMAND`),pr=A(`UNDO_COMMAND`),mr=A(`REDO_COMMAND`),hr=A(`KEYDOWN_COMMAND`),gr=A(`KEY_ARROW_RIGHT_COMMAND`),_r=A(`MOVE_TO_END`),vr=A(`KEY_ARROW_LEFT_COMMAND`),yr=A(`MOVE_TO_START`),br=A(`KEY_ARROW_UP_COMMAND`),xr=A(`KEY_ARROW_DOWN_COMMAND`),Sr=A(`KEY_ENTER_COMMAND`),Cr=A(`KEY_SPACE_COMMAND`),wr=A(`KEY_BACKSPACE_COMMAND`),Tr=A(`KEY_ESCAPE_COMMAND`),Er=A(`KEY_DELETE_COMMAND`),Dr=A(`KEY_TAB_COMMAND`),Or=A(`INSERT_TAB_COMMAND`),kr=A(`INDENT_CONTENT_COMMAND`),Ar=A(`OUTDENT_CONTENT_COMMAND`),jr=A(`DROP_COMMAND`),Mr=A(`FORMAT_ELEMENT_COMMAND`),Nr=A(`DRAGSTART_COMMAND`),Pr=A(`DRAGOVER_COMMAND`),Fr=A(`DRAGEND_COMMAND`),Ir=A(`COPY_COMMAND`),Lr=A(`CUT_COMMAND`),Rr=A(`SELECT_ALL_COMMAND`),zr=A(`CLEAR_EDITOR_COMMAND`),Br=A(`CLEAR_HISTORY_COMMAND`),Vr=A(`CAN_REDO_COMMAND`),Hr=A(`CAN_UNDO_COMMAND`),Ur=A(`FOCUS_COMMAND`),Wr=A(`BLUR_COMMAND`),Gr=A(`KEY_MODIFIER_COMMAND`),Kr=Object.freeze({}),qr=[[`keydown`,function(e,t){Jr=e.timeStamp,Yr=e.key,!t.isComposing()&&q(t,hr,e)}],[`pointerdown`,function(e,t){let n=e.target,r=e.pointerType;Rs(n)&&r!==`touch`&&r!==`pen`&&e.button===0&&no(t,()=>{Oo(n)||(ti=!0)})}],[`compositionstart`,function(e,t){q(t,nr,e)}],[`compositionend`,function(e,t){pt?ri=!0:gt||!ht&&!bt?q(t,rr,e):(ii=!0,ai=e.data)}],[`input`,function(e,t){e.stopPropagation(),no(t,()=>{t.dispatchCommand(tr,e)},{event:e}),Zr=null}],[`click`,function(e,t){no(t,()=>{let n=F(),r=Fs(Ds(t)),i=Ta();if(r){if(P(n)){let t=n.anchor,a=t.getNode();if(t.type===`element`&&t.offset===0&&n.isCollapsed()&&!H(a)&&G().getChildrenSize()===1&&a.getTopLevelElementOrThrow().isEmpty()&&i!==null&&n.is(i))r.removeAllRanges(),n.dirty=!0;else if(e.detail===3&&!n.isCollapsed()&&a!==n.focus.getNode()){let e=ec(a,e=>B(e)&&!e.isInline());B(e)&&e.select(0)}}else if(e.pointerType===`touch`||e.pointerType===`pen`){let n=r.anchorNode;(J(n)||Lo(n))&&$o(wa(i,r,t,e))}}q(t,$n,e)})}],[`cut`,Kr],[`copy`,Kr],[`dragstart`,Kr],[`dragover`,Kr],[`dragend`,Kr],[`paste`,Kr],[`focus`,Kr],[`blur`,Kr],[`drop`,Kr]];mt&&qr.push([`beforeinput`,(e,t)=>function(e,t){let n=e.inputType;n===`deleteCompositionText`||pt&&ys(t)||n!==`insertCompositionText`&&q(t,er,e)}(e,t)]);var Jr=0,Yr=null,Xr=0,Zr=null,Qr=new WeakMap,$r=new WeakMap,ei=!1,ti=!1,ni=!1,ri=!1,ii=!1,ai=``,oi=null,si=[0,``,0,`root`,0];function ci(e,t,n,r,i){let a=e.anchor,o=e.focus,s=a.getNode(),c=z(),l=Fs(Ds(c)),u=l===null?null:l.anchorNode,d=a.key,f=c.getElementByKey(d),p=n.length;return d!==o.key||!N(s)||(!i&&(!mt||Xr<r+50)||s.isDirty()&&p<2||ts(n))&&a.offset!==o.offset&&!s.isComposing()||Io(s)||s.isDirty()&&p>1||(i||!mt)&&f!==null&&!s.isComposing()&&u!==zo(f)||l!==null&&t!==null&&(!t.collapsed||t.startContainer!==l.anchorNode||t.startOffset!==l.anchorOffset)||!s.isComposing()&&(s.getFormat()!==e.format||s.getStyle()!==e.style)||function(e,t){if(t.isSegmented())return!0;if(!e.isCollapsed())return!1;let n=e.anchor.offset,r=t.getParentOrThrow(),i=Fo(t);return n===0?!t.canInsertTextBefore()||!r.canInsertTextBefore()&&!t.isComposing()||i||function(e){let t=e.getPreviousSibling();return(N(t)||B(t)&&t.isInline())&&!t.canInsertTextAfter()}(t):n===t.getTextContentSize()&&(!t.canInsertTextAfter()||!r.canInsertTextAfter()&&!t.isComposing()||i)}(e,s)}function li(e,t){return Lo(e)&&e.nodeValue!==null&&t!==0&&t!==e.nodeValue.length}function ui(e,t,n){let{anchorNode:r,anchorOffset:i,focusNode:a,focusOffset:o}=e;ei&&(ei=!1,li(r,i)&&li(a,o)&&!oi)||no(t,()=>{if(!n)return void $o(null);if(!Ao(t,r,a))return;let s=F();if(oi&&P(s)&&s.isCollapsed()){let e=s.anchor,t=oi.anchor;(e.key===t.key&&e.offset===t.offset+1||e.offset===1&&t.getNode().is(e.getNode().getPreviousSibling()))&&(s=oi.clone(),$o(s))}if(oi=null,P(s)){let n=s.anchor,r=n.getNode();if(s.isCollapsed()){e.type===`Range`&&e.anchorNode===e.focusNode&&(s.dirty=!0);let i=Ds(t).event,a=i?i.timeStamp:performance.now(),[o,c,l,u,d]=si,f=G(),p=!1===t.isComposing()&&f.getTextContent()===``;if(a<d+200&&n.offset===l&&n.key===u)di(s,o,c);else if(n.type===`text`)N(r)||O(141),fi(s,r);else if(n.type===`element`&&!p){B(r)||O(259);let e=n.getNode();e.isEmpty()?function(e,t){di(e,t.getTextFormat(),t.getTextStyle())}(s,e):di(s,0,``)}}else{let e=n.key,t=s.focus.key,r=s.getNodes(),a=r.length,c=s.isBackward(),l=c?o:i,u=c?i:o,d=c?t:e,f=c?e:t,p=2047,m=!1;for(let e=0;e<a;e++){let t=r[e],n=t.getTextContentSize();if(N(t)&&n!==0&&!(e===0&&t.__key===d&&l===n||e===a-1&&t.__key===f&&u===0)&&(m=!0,p&=t.getFormat(),p===0))break}s.format=m?p:0}}q(t,Zn,void 0)})}function di(e,t,n){e.format===t&&e.style===n||(e.format=t,e.style=n,e.dirty=!0)}function fi(e,t){di(e,t.getFormat(),t.getStyle())}function pi(e){if(!e.getTargetRanges)return null;let t=e.getTargetRanges();return t.length===0?null:t[0]}function mi(e){let t=e.inputType,n=pi(e),r=z(),i=F();if(t===`deleteContentBackward`){if(i===null){let e=Ta();if(!P(e))return!0;$o(e.clone())}if(P(i)){let t=i.anchor.key===i.focus.key;if(a=e.timeStamp,Yr===`MediaLast`&&a<Jr+30&&r.isComposing()&&t){if(Go(null),Jr=0,setTimeout(()=>{no(r,()=>{Go(null)})},30),P(i)){let e=i.anchor.getNode();e.markDirty(),N(e)||O(142),fi(i,e)}}else{Go(null),e.preventDefault();let n=i.anchor.getNode(),a=n.getTextContent(),o=n.canInsertTextAfter(),s=i.anchor.offset===0&&i.focus.offset===a.length,c=yt&&t&&!s&&o;if(c&&i.isCollapsed()&&(c=!V(vs(i.anchor,!0))),!c){q(r,ir,!0);let e=F();yt&&P(e)&&e.isCollapsed()&&(oi=e,setTimeout(()=>oi=null))}}return!0}}var a;if(!P(i))return!0;let o=e.data;Zr!==null&&as(!1,r,Zr),i.dirty&&Zr===null||!i.isCollapsed()||H(i.anchor.getNode())||n===null||i.applyDOMRange(n),Zr=null;let s=i.anchor,c=i.focus,l=s.getNode(),u=c.getNode();if(t===`insertText`||t===`insertTranspose`){if(o===`
4
4
  `)e.preventDefault(),q(r,ar,!1);else if(o===jt)e.preventDefault(),q(r,or,void 0);else if(o==null&&e.dataTransfer){let t=e.dataTransfer.getData(`text/plain`);e.preventDefault(),i.insertRawText(t)}else o!=null&&ci(i,n,o,e.timeStamp,!0)?(e.preventDefault(),q(r,sr,o)):Zr=o;return Xr=e.timeStamp,!0}switch(e.preventDefault(),t){case`insertFromYank`:case`insertFromDrop`:case`insertReplacementText`:q(r,sr,e);break;case`insertFromComposition`:Go(null),q(r,sr,e);break;case`insertLineBreak`:Go(null),q(r,ar,!1);break;case`insertParagraph`:Go(null),ni&&!gt?(ni=!1,q(r,ar,!1)):q(r,or,void 0);break;case`insertFromPaste`:case`insertFromPasteAsQuotation`:q(r,cr,e);break;case`deleteByComposition`:(function(e,t){return e!==t||B(e)||B(t)||!Fo(e)||!Fo(t)})(l,u)&&q(r,lr,e);break;case`deleteByDrag`:case`deleteByCut`:q(r,lr,e);break;case`deleteContent`:q(r,ir,!1);break;case`deleteWordBackward`:q(r,ur,!0);break;case`deleteWordForward`:q(r,ur,!1);break;case`deleteHardLineBackward`:case`deleteSoftLineBackward`:q(r,dr,!0);break;case`deleteContentForward`:case`deleteHardLineForward`:case`deleteSoftLineForward`:q(r,dr,!1);break;case`formatStrikeThrough`:q(r,fr,`strikethrough`);break;case`formatBold`:q(r,fr,`bold`);break;case`formatItalic`:q(r,fr,`italic`);break;case`formatUnderline`:q(r,fr,`underline`);break;case`historyUndo`:q(r,pr,void 0);break;case`historyRedo`:q(r,mr,void 0)}return!0}function hi(e){if(J(e.target)&&Oo(e.target))return!0;let t=z(),n=F(),r=e.data,i=pi(e);if(r!=null&&P(n)&&ci(n,i,r,e.timeStamp,!1)){ri&&=(vi(t,r),!1);let i=n.anchor.getNode(),a=Fs(Ds(t));if(a===null)return!0;let o=n.isBackward(),s=o?n.anchor.offset:n.focus.offset,c=o?n.focus.offset:n.anchor.offset;mt&&!n.isCollapsed()&&N(i)&&a.anchorNode!==null&&i.getTextContent().slice(0,s)+r+i.getTextContent().slice(s+c)===is(a.anchorNode)||q(t,sr,r);let l=r.length;pt&&l>1&&e.inputType===`insertCompositionText`&&!t.isComposing()&&(n.anchor.offset-=l),yt&&t.isComposing()&&(Jr=0,Go(null))}else as(!1,t,r===null?void 0:r),ri&&=(vi(t,r||void 0),!1);return function(){R(),Zt(z())}(),!0}function gi(e){let t=z(),n=F();if(P(n)&&!t.isComposing()){let r=n.anchor,i=n.anchor.getNode();Go(r.key),Cs(Ni),(e.timeStamp<Jr+30||r.type===`element`||!n.isCollapsed()||i.getFormat()!==n.format||N(i)&&i.getStyle()!==n.style)&&q(t,sr,Mt)}return!0}function _i(e){return vi(z(),e.data),Cs(Pi),!0}function vi(e,t){let n=e._compositionKey;if(Go(null),n!==null&&t!=null){if(t===``){let t=W(n),r=zo(e.getElementByKey(n));if(r!==null&&r.nodeValue!==null&&N(t)){let n=Fs(Ds(e)),i=null,a=null;n!==null&&n.anchorNode===r&&(i=n.anchorOffset,a=n.focusOffset),os(t,r.nodeValue,i,a,!0)}return}if(t[t.length-1]===`
@@ -1,2 +1,2 @@
1
- import{$ as e,E as t,F as n,G as r,H as i,M as a,O as o,P as s,T as c,U as l,Z as u,b as d,g as f,j as p,k as m,q as h,t as g,x as _}from"./index-D7m61Ahx.js";var v={key:0},y={class:`error-header`},b={class:`error-message`},x={class:`error-location`},S={class:`error-line-badge`},C={key:0,class:`error-code-block`},w={class:`line-number`},T={key:1},E=g({__name:`ErrorPage`,setup(g){let E=d(),D=_(),O=o(()=>{try{return E.query.data?JSON.parse(E.query.data):null}catch{return null}});async function k(){let e=await f();e.error?D.replace({name:`error`,query:{data:JSON.stringify(e.error)}}):(D.push(`/`),window.location.reload())}return(o,d)=>{let f=r(`router-link`);return O.value?(i(),a(`div`,v,[m(`header`,null,[m(`article`,y,[d[1]||=m(`h3`,null,[m(`i`,{class:`iconoir-warning-triangle`}),s(` Error `)],-1),m(`p`,b,e(O.value.error),1),m(`p`,x,[d[0]||=m(`i`,{class:`iconoir-page`},null,-1),s(` `+e(O.value.path)+` `,1),m(`span`,S,`Line `+e(O.value.line_no),1)])]),m(`a`,{href:`#`,class:`reload-btn`,onClick:c(k,[`prevent`])},[...d[2]||=[m(`i`,{class:`iconoir-refresh`},null,-1),s(` Reload `,-1)]])]),O.value.context?(i(),a(`div`,C,[m(`pre`,null,[m(`code`,null,[(i(!0),a(t,null,l(O.value.context,t=>(i(),a(`span`,{key:t.line_no,class:u(t.selected?`error-line`:`code-line`)},[m(`span`,w,e(String(t.line_no).padStart(4,` `)),1),s(e(t.content)+`
1
+ import{$ as e,E as t,F as n,G as r,H as i,M as a,O as o,P as s,T as c,U as l,Z as u,b as d,g as f,j as p,k as m,q as h,t as g,x as _}from"./index-BXXkUK1V.js";var v={key:0},y={class:`error-header`},b={class:`error-message`},x={class:`error-location`},S={class:`error-line-badge`},C={key:0,class:`error-code-block`},w={class:`line-number`},T={key:1},E=g({__name:`ErrorPage`,setup(g){let E=d(),D=_(),O=o(()=>{try{return E.query.data?JSON.parse(E.query.data):null}catch{return null}});async function k(){let e=await f();e.error?D.replace({name:`error`,query:{data:JSON.stringify(e.error)}}):(D.push(`/`),window.location.reload())}return(o,d)=>{let f=r(`router-link`);return O.value?(i(),a(`div`,v,[m(`header`,null,[m(`article`,y,[d[1]||=m(`h3`,null,[m(`i`,{class:`iconoir-warning-triangle`}),s(` Error `)],-1),m(`p`,b,e(O.value.error),1),m(`p`,x,[d[0]||=m(`i`,{class:`iconoir-page`},null,-1),s(` `+e(O.value.path)+` `,1),m(`span`,S,`Line `+e(O.value.line_no),1)])]),m(`a`,{href:`#`,class:`reload-btn`,onClick:c(k,[`prevent`])},[...d[2]||=[m(`i`,{class:`iconoir-refresh`},null,-1),s(` Reload `,-1)]])]),O.value.context?(i(),a(`div`,C,[m(`pre`,null,[m(`code`,null,[(i(!0),a(t,null,l(O.value.context,t=>(i(),a(`span`,{key:t.line_no,class:u(t.selected?`error-line`:`code-line`)},[m(`span`,w,e(String(t.line_no).padStart(4,` `)),1),s(e(t.content)+`
2
2
  `,1)],2))),128))])])])):p(``,!0)])):(i(),a(`div`,T,[d[4]||=m(`p`,null,`No error data available.`,-1),n(f,{to:`/`},{default:h(()=>[...d[3]||=[s(`Back to home`,-1)]]),_:1})]))}}},[[`__scopeId`,`data-v-cb96d9d5`]]);export{E as default};
@@ -1 +1 @@
1
- import{B as e,H as t,M as n,R as r,V as i,Y as a,k as o,t as s,u as c}from"./index-D7m61Ahx.js";import{t as l}from"./useGraphviz-DweKV7Kg.js";import{d as u}from"./WikiPage-CeCQBTDS.js";var d={key:0},f={key:1,class:`graph-container graph-expand`},p=[`innerHTML`],m=s({__name:`GraphView`,setup(s){let m=a(``),h=a(!0),g=a(null),_=null;e(async()=>{let e=await c();m.value=e?await l(e):``,h.value=!1,await r(),v()}),i(()=>{_?.destroy()});function v(){if(!g.value)return;let e=g.value.querySelector(`svg`);e&&(_=u(e,g.value))}return(e,r)=>(t(),n(`article`,null,[r[1]||=o(`header`,null,[o(`h2`,null,`Architecture Overview`)],-1),h.value?(t(),n(`div`,d,[...r[0]||=[o(`p`,null,`Loading graph...`,-1)]])):(t(),n(`div`,f,[o(`div`,{id:`graphviz`,ref_key:`graphEl`,ref:g,class:`fullcanvas`,innerHTML:m.value},null,8,p)]))]))}},[[`__scopeId`,`data-v-dbc5bc1f`]]);export{m as default};
1
+ import{B as e,H as t,M as n,R as r,V as i,Y as a,k as o,t as s,u as c}from"./index-BXXkUK1V.js";import{t as l}from"./useGraphviz-DlSnFeCL.js";import{d as u}from"./WikiPage-D2svpk6B.js";var d={key:0},f={key:1,class:`graph-container graph-expand`},p=[`innerHTML`],m=s({__name:`GraphView`,setup(s){let m=a(``),h=a(!0),g=a(null),_=null;e(async()=>{let e=await c();m.value=e?await l(e):``,h.value=!1,await r(),v()}),i(()=>{_?.destroy()});function v(){if(!g.value)return;let e=g.value.querySelector(`svg`);e&&(_=u(e,g.value))}return(e,r)=>(t(),n(`article`,null,[r[1]||=o(`header`,null,[o(`h2`,null,`Architecture Overview`)],-1),h.value?(t(),n(`div`,d,[...r[0]||=[o(`p`,null,`Loading graph...`,-1)]])):(t(),n(`div`,f,[o(`div`,{id:`graphviz`,ref_key:`graphEl`,ref:g,class:`fullcanvas`,innerHTML:m.value},null,8,p)]))]))}},[[`__scopeId`,`data-v-dbc5bc1f`]]);export{m as default};