archsight 0.3.2 → 0.4.0

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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -1
  3. data/docs/archimate.md +21 -1
  4. data/docs/configuration.md +1 -0
  5. data/docs/diagram.md +15 -3
  6. data/docs/docker.md +4 -1
  7. data/docs/icons.md +32 -0
  8. data/docs/import.md +178 -55
  9. data/docs/index.md.erb +31 -8
  10. data/docs/modeling.md +772 -24
  11. data/docs/pages.md +44 -13
  12. data/docs/search.md +21 -1
  13. data/docs/togaf.md +5 -1
  14. data/lib/archsight/analysis/result.rb +8 -2
  15. data/lib/archsight/analysis/sandbox.rb +8 -0
  16. data/lib/archsight/analysis/typst_renderer.rb +246 -0
  17. data/lib/archsight/analysis.rb +1 -0
  18. data/lib/archsight/annotations/annotation.rb +30 -3
  19. data/lib/archsight/annotations/architecture_annotations.rb +47 -0
  20. data/lib/archsight/annotations/asset_annotations.rb +34 -0
  21. data/lib/archsight/annotations/link_annotations.rb +15 -0
  22. data/lib/archsight/annotations/resource_reference.rb +12 -0
  23. data/lib/archsight/annotations/risk_annotations.rb +21 -0
  24. data/lib/archsight/cli.rb +124 -23
  25. data/lib/archsight/database.rb +40 -0
  26. data/lib/archsight/diagram/cli.rb +50 -2
  27. data/lib/archsight/diagram/formatter.rb +112 -0
  28. data/lib/archsight/diagram/routing/edge_router/orthogonal_path.rb +38 -10
  29. data/lib/archsight/diagram/routing/edge_router.rb +29 -4
  30. data/lib/archsight/diagram/routing/edge_routing.rb +61 -5
  31. data/lib/archsight/diagram/style/theme.rb +7 -2
  32. data/lib/archsight/documentation.rb +3 -2
  33. data/lib/archsight/editor/page_source.rb +13 -1
  34. data/lib/archsight/export/confluence/analysis_output.rb +101 -0
  35. data/lib/archsight/export/confluence/client.rb +13 -0
  36. data/lib/archsight/export/confluence/diagram_links.rb +1 -1
  37. data/lib/archsight/export/confluence/exporter.rb +40 -13
  38. data/lib/archsight/export/confluence/labels.rb +25 -0
  39. data/lib/archsight/export/confluence/page_properties.rb +4 -6
  40. data/lib/archsight/export/confluence/storage.rb +38 -2
  41. data/lib/archsight/helpers/embeds.rb +18 -7
  42. data/lib/archsight/helpers/resource_resolver.rb +25 -0
  43. data/lib/archsight/import/executor.rb +139 -16
  44. data/lib/archsight/import/handler.rb +55 -6
  45. data/lib/archsight/import/handler_loader.rb +64 -0
  46. data/lib/archsight/import/handlers/cache_pruner.rb +30 -7
  47. data/lib/archsight/import/handlers/command.rb +120 -0
  48. data/lib/archsight/import/handlers/github.rb +4 -1
  49. data/lib/archsight/import/handlers/gitlab.rb +4 -1
  50. data/lib/archsight/import/handlers/go_dep_resolver.rb +10 -2
  51. data/lib/archsight/import/handlers/go_grapher.rb +102 -5
  52. data/lib/archsight/import/handlers/go_module_parser.rb +88 -0
  53. data/lib/archsight/import/handlers/grapher.rb +40 -1
  54. data/lib/archsight/import/handlers/repository.rb +3 -0
  55. data/lib/archsight/import/handlers/rest_api_index.rb +3 -0
  56. data/lib/archsight/import/registry.rb +22 -1
  57. data/lib/archsight/import.rb +64 -1
  58. data/lib/archsight/linter/structure.rb +239 -0
  59. data/lib/archsight/linter.rb +217 -6
  60. data/lib/archsight/page_loader.rb +12 -1
  61. data/lib/archsight/query/evaluator.rb +13 -6
  62. data/lib/archsight/query/parser.rb +73 -6
  63. data/lib/archsight/query.rb +1 -1
  64. data/lib/archsight/references.rb +3 -3
  65. data/lib/archsight/renderer.rb +80 -23
  66. data/lib/archsight/resources/analysis.rb +3 -2
  67. data/lib/archsight/resources/application_component.rb +83 -8
  68. data/lib/archsight/resources/application_event.rb +79 -0
  69. data/lib/archsight/resources/application_service.rb +18 -2
  70. data/lib/archsight/resources/base.rb +58 -5
  71. data/lib/archsight/resources/business_actor.rb +14 -1
  72. data/lib/archsight/resources/business_contract.rb +72 -0
  73. data/lib/archsight/resources/business_control.rb +10 -2
  74. data/lib/archsight/resources/business_event.rb +79 -0
  75. data/lib/archsight/resources/business_process.rb +8 -1
  76. data/lib/archsight/resources/business_product.rb +12 -0
  77. data/lib/archsight/resources/business_role.rb +70 -0
  78. data/lib/archsight/resources/compliance_evidence.rb +8 -2
  79. data/lib/archsight/resources/data_object.rb +6 -1
  80. data/lib/archsight/resources/implementation_deliverable.rb +63 -0
  81. data/lib/archsight/resources/implementation_event.rb +52 -0
  82. data/lib/archsight/resources/implementation_gap.rb +49 -0
  83. data/lib/archsight/resources/implementation_plateau.rb +67 -0
  84. data/lib/archsight/resources/implementation_work_package.rb +84 -0
  85. data/lib/archsight/resources/import.rb +37 -11
  86. data/lib/archsight/resources/location.rb +56 -0
  87. data/lib/archsight/resources/motivation_assessment.rb +121 -0
  88. data/lib/archsight/resources/motivation_constraint.rb +7 -1
  89. data/lib/archsight/resources/motivation_driver.rb +50 -0
  90. data/lib/archsight/resources/motivation_goal.rb +13 -1
  91. data/lib/archsight/resources/motivation_principle.rb +75 -0
  92. data/lib/archsight/resources/motivation_requirement.rb +18 -2
  93. data/lib/archsight/resources/motivation_stakeholder.rb +21 -0
  94. data/lib/archsight/resources/page.rb +9 -7
  95. data/lib/archsight/resources/strategy_capability.rb +9 -0
  96. data/lib/archsight/resources/technology_artifact.rb +11 -4
  97. data/lib/archsight/resources/technology_communication_network.rb +89 -0
  98. data/lib/archsight/resources/technology_device.rb +88 -0
  99. data/lib/archsight/resources/technology_equipment.rb +75 -0
  100. data/lib/archsight/resources/technology_event.rb +80 -0
  101. data/lib/archsight/resources/technology_facility.rb +70 -0
  102. data/lib/archsight/resources/technology_node.rb +57 -1
  103. data/lib/archsight/resources/technology_service.rb +33 -0
  104. data/lib/archsight/resources/technology_system_software.rb +28 -0
  105. data/lib/archsight/resources.rb +12 -0
  106. data/lib/archsight/version.rb +1 -1
  107. data/lib/archsight/web/api/analysis_helpers.rb +55 -0
  108. data/lib/archsight/web/api/json_helpers.rb +3 -37
  109. data/lib/archsight/web/api/openapi/spec.yaml +10 -8
  110. data/lib/archsight/web/api/page_helpers.rb +1 -8
  111. data/lib/archsight/web/api/routes.rb +7 -2
  112. data/lib/archsight/web/application.rb +38 -2
  113. data/lib/archsight/web/editor/routes.rb +2 -1
  114. data/lib/archsight/web/public/vue/ApiDocsPage-COp4onwn.js +1 -0
  115. data/lib/archsight/web/public/vue/DocPage-D52OwaKc.js +1 -0
  116. data/lib/archsight/web/public/vue/EditorPage-3aqL7yVf.js +35 -0
  117. data/lib/archsight/web/public/vue/ErrorPage--b9XeSYa.js +2 -0
  118. data/lib/archsight/web/public/vue/GraphView-qh_EtRrQ.js +1 -0
  119. data/lib/archsight/web/public/vue/HomePage-C2TNh2U-.js +2 -0
  120. data/lib/archsight/web/public/vue/InstanceRouter-ZaCcjlIX.css +1 -0
  121. data/lib/archsight/web/public/vue/InstanceRouter-uzb_OMG0.js +1 -0
  122. data/lib/archsight/web/public/vue/KindList-CyJuP_uq.js +1 -0
  123. data/lib/archsight/web/public/vue/KindList-yYcRT2BV.css +1 -0
  124. data/lib/archsight/web/public/vue/PageView-B93woeN3.css +1 -0
  125. data/lib/archsight/web/public/vue/PageView-FyygrS-b.js +1 -0
  126. data/lib/archsight/web/public/vue/QueryError-B4Ex_csZ.js +1 -0
  127. data/lib/archsight/web/public/vue/ResourceList-BY6Z1Kcb.js +2 -0
  128. data/lib/archsight/web/public/vue/ResourceList-D75O87zG.css +1 -0
  129. data/lib/archsight/web/public/vue/{SearchResults-CyPUZZSC.css → SearchResults-BV6UHriJ.css} +1 -1
  130. data/lib/archsight/web/public/vue/SearchResults-CkFpHF8m.js +1 -0
  131. data/lib/archsight/web/public/vue/WikiPage-BoHNewCX.js +3 -0
  132. data/lib/archsight/web/public/vue/WikiPage-TpmM1VAF.css +1 -0
  133. data/lib/archsight/web/public/vue/architecture-7GRP2DOG-BvzKZE4e.js +1 -0
  134. data/lib/archsight/web/public/vue/cynefin-OW5HDTMX-D-xs_Hxh.js +1 -0
  135. data/lib/archsight/web/public/vue/eventmodeling-NTZA5JFV-nbjxG01S.js +1 -0
  136. data/lib/archsight/web/public/vue/gitGraph-4MIJSDKK-CW6mw2ab.js +1 -0
  137. data/lib/archsight/web/public/vue/index-BGlYCbi7.js +3 -0
  138. data/lib/archsight/web/public/vue/index-eUHmJ7K2.css +1 -0
  139. data/lib/archsight/web/public/vue/info-A6RAGUB7-C12sjlHe.js +1 -0
  140. data/lib/archsight/web/public/vue/{mermaid-BjEi5URd.js → mermaid-DjsXQ_XN.js} +35 -35
  141. data/lib/archsight/web/public/vue/packet-AYTQ26CC-wMwKwHmA.js +1 -0
  142. data/lib/archsight/web/public/vue/pie-WAS4IAKB-w1-sAU_K.js +1 -0
  143. data/lib/archsight/web/public/vue/radar-RG4KPBEZ-DpwqIFoy.js +1 -0
  144. data/lib/archsight/web/public/vue/railroad-74A4TZTK-Ce5XC24d.js +1 -0
  145. data/lib/archsight/web/public/vue/railroad-abnf-HS5TGJTU-BSQO2pds.js +1 -0
  146. data/lib/archsight/web/public/vue/railroad-ebnf-LZEXJU2U-Dq1c2YtD.js +1 -0
  147. data/lib/archsight/web/public/vue/railroad-peg-WCYAUIDC-DKj6dli0.js +1 -0
  148. data/lib/archsight/web/public/vue/rolldown-runtime-hePW80VL.js +1 -0
  149. data/lib/archsight/web/public/vue/treeView-Q6P3EWNA-BmHNTWxU.js +1 -0
  150. data/lib/archsight/web/public/vue/treemap-WGGIJYW6-DsEI7sSD.js +1 -0
  151. data/lib/archsight/web/public/vue/{useGraphviz-DweKV7Kg.js → useGraphviz-4evusK9i.js} +13 -1
  152. data/lib/archsight/web/public/vue/{useHighlight-D5Gf8DLl.js → useHighlight-DPguaxfm.js} +8 -8
  153. data/lib/archsight/web/public/vue/usePanZoom-seQE1TPk.js +12 -0
  154. data/lib/archsight/web/public/vue/wardley-WFR3VGLG-CSCW83-M.js +1 -0
  155. data/lib/archsight/web/public/vue.html +5 -5
  156. metadata +72 -38
  157. data/lib/archsight/web/public/vue/ApiDocsPage-DoOxKjG0.js +0 -1
  158. data/lib/archsight/web/public/vue/DocPage-CfsC3CeQ.js +0 -1
  159. data/lib/archsight/web/public/vue/EditorPage-CsJA0q8n.js +0 -35
  160. data/lib/archsight/web/public/vue/ErrorPage-OJpJz9df.js +0 -2
  161. data/lib/archsight/web/public/vue/GraphView-CBq6oFRV.js +0 -1
  162. data/lib/archsight/web/public/vue/HomePage-BwgMLgVC.js +0 -2
  163. data/lib/archsight/web/public/vue/InstanceRouter-DQz-SsQq.js +0 -1
  164. data/lib/archsight/web/public/vue/InstanceRouter-jeavM6PW.css +0 -1
  165. data/lib/archsight/web/public/vue/KindList-4q0K9Cll.js +0 -1
  166. data/lib/archsight/web/public/vue/PageView-DzeGnvoS.js +0 -1
  167. data/lib/archsight/web/public/vue/QueryError-kg6Yf-pW.js +0 -1
  168. data/lib/archsight/web/public/vue/ResourceList-B0FLaFR3.css +0 -1
  169. data/lib/archsight/web/public/vue/ResourceList-Df_0e0qt.js +0 -2
  170. data/lib/archsight/web/public/vue/SearchResults-CKgY6_wH.js +0 -1
  171. data/lib/archsight/web/public/vue/WikiPage-DoFJ0dbW.css +0 -1
  172. data/lib/archsight/web/public/vue/WikiPage-DrvCHwJ7.js +0 -13
  173. data/lib/archsight/web/public/vue/architecture-7GRP2DOG-BfA1TPxQ.js +0 -1
  174. data/lib/archsight/web/public/vue/cynefin-OW5HDTMX-BmgdUKVD.js +0 -1
  175. data/lib/archsight/web/public/vue/eventmodeling-NTZA5JFV-DbXDvAWF.js +0 -1
  176. data/lib/archsight/web/public/vue/gitGraph-4MIJSDKK-BkVhrKS1.js +0 -1
  177. data/lib/archsight/web/public/vue/index-D0Q5GZRs.js +0 -3
  178. data/lib/archsight/web/public/vue/index-oF-iyZvk.css +0 -1
  179. data/lib/archsight/web/public/vue/info-A6RAGUB7-BIlCVuUY.js +0 -1
  180. data/lib/archsight/web/public/vue/packet-AYTQ26CC-eoQTjY3j.js +0 -1
  181. data/lib/archsight/web/public/vue/pie-WAS4IAKB-DEOotGhh.js +0 -1
  182. data/lib/archsight/web/public/vue/radar-RG4KPBEZ-C2yucuUN.js +0 -1
  183. data/lib/archsight/web/public/vue/railroad-74A4TZTK-CzONK5VY.js +0 -1
  184. data/lib/archsight/web/public/vue/railroad-abnf-HS5TGJTU-9zRPsDsx.js +0 -1
  185. data/lib/archsight/web/public/vue/railroad-ebnf-LZEXJU2U-BJ4dkz9l.js +0 -1
  186. data/lib/archsight/web/public/vue/railroad-peg-WCYAUIDC-DFy_rqAj.js +0 -1
  187. data/lib/archsight/web/public/vue/treeView-Q6P3EWNA-2cq5CyD2.js +0 -1
  188. data/lib/archsight/web/public/vue/treemap-WGGIJYW6-DK-e9Ez4.js +0 -1
  189. data/lib/archsight/web/public/vue/wardley-WFR3VGLG-BQwqUqfB.js +0 -1
@@ -66,7 +66,8 @@ module Archsight::Web::API::JsonHelpers
66
66
  description: klass.description,
67
67
  layer: klass.layer,
68
68
  icon: klass.icon,
69
- instance_count: count
69
+ instance_count: count,
70
+ self_relations: Archsight::GraphvisRenderer.self_relations(klass).any?
70
71
  }
71
72
  end
72
73
  kinds.sort_by { |k| k[:kind] }
@@ -92,6 +93,7 @@ module Archsight::Web::API::JsonHelpers
92
93
  name: instance.name,
93
94
  metadata: { annotations: render_annotations(instance.annotations, base: Archsight::Assets.base_dir_for(instance, resources_dir: Archsight.resources_dir), kind: kind) },
94
95
  annotation_formats: Archsight::Resources[kind]&.annotation_formats(instance.annotations.keys) || {},
96
+ annotation_links: Archsight::Helpers::ResourceResolver.new(db).annotation_links(kind, instance.annotations),
95
97
  spec: serialize_spec(instance.spec),
96
98
  relations: extract_relations(instance),
97
99
  references: extract_references(instance),
@@ -193,42 +195,6 @@ module Archsight::Web::API::JsonHelpers
193
195
  end
194
196
  end
195
197
 
196
- def build_analysis_result(result)
197
- data = {
198
- name: result.name,
199
- success: result.success?,
200
- has_findings: result.has_findings?,
201
- duration: result.duration,
202
- sections: result.sections.map { |s| serialize_analysis_section(s) }
203
- }
204
-
205
- if result.failed?
206
- data[:error] = result.error
207
- data[:error_backtrace] = result.error_backtrace if result.error_backtrace&.any?
208
- end
209
-
210
- data
211
- end
212
-
213
- def serialize_analysis_section(section)
214
- case section[:type]
215
- when :heading
216
- { type: "heading", level: section[:level], text: section[:text] }
217
- when :text
218
- { type: "text", content: markdown(section[:content]) }
219
- when :message
220
- { type: "message", level: section[:level].to_s, message: section[:message] }
221
- when :table
222
- { type: "table", headers: section[:headers], rows: section[:rows] }
223
- when :list
224
- { type: "list", items: section[:items] }
225
- when :code
226
- { type: "code", lang: section[:lang], content: section[:content] }
227
- else
228
- { type: section[:type].to_s }
229
- end
230
- end
231
-
232
198
  def extract_references(instance)
233
199
  references = {}
234
200
 
@@ -254,7 +254,7 @@ paths:
254
254
  Returns one page with its metadata and its body rendered to HTML.
255
255
 
256
256
  **Metadata** comes from the frontmatter: `title` (falls back to the name), `status`, `author` and
257
- `owner` (`Name <email>`, split into `name` and `email`), `tags` and the `confluence` URL.
257
+ `owner` (`Name <email>`, split into `name` and `email`), `tags` and the `links` (name and URL, e.g. `confluence`).
258
258
 
259
259
  **`html`** is the markdown body rendered once per request:
260
260
  - GitHub-flavoured markdown (tables, fenced code, task lists).
@@ -309,7 +309,7 @@ paths:
309
309
  owner:
310
310
  name: Jane Doe
311
311
  email: jane.doe@example.com
312
- confluence: null
312
+ links: {}
313
313
  tags:
314
314
  - howto
315
315
  - wiki
@@ -1489,7 +1489,7 @@ components:
1489
1489
  description: Whether the analysis executed successfully
1490
1490
  has_findings:
1491
1491
  type: boolean
1492
- description: Whether the analysis produced findings
1492
+ description: Whether the script produced any output (tables, lists, text, ...). Output is not a problem; errors and warnings the script reports are message sections
1493
1493
  duration:
1494
1494
  type: number
1495
1495
  format: float
@@ -1869,7 +1869,7 @@ components:
1869
1869
 
1870
1870
  PageResponse:
1871
1871
  type: object
1872
- required: [name, title, status, author, owner, created, updated, properties, confluence, tags, toc, breadcrumb, html, backlinks]
1872
+ required: [name, title, status, author, owner, created, updated, properties, links, tags, toc, breadcrumb, html, backlinks]
1873
1873
  properties:
1874
1874
  name:
1875
1875
  type: string
@@ -1909,10 +1909,12 @@ components:
1909
1909
  html:
1910
1910
  type: string
1911
1911
  description: The value rendered as inline markdown (links, emphasis, `{macros}`, `[[wiki links]]`), without a paragraph around it
1912
- confluence:
1913
- type: [string, 'null']
1914
- format: uri
1915
- description: URL of the corresponding Confluence page
1912
+ links:
1913
+ type: object
1914
+ description: Links of the page to other systems, by name (`confluence`, `jira`, ...)
1915
+ additionalProperties:
1916
+ type: string
1917
+ format: uri
1916
1918
  tags:
1917
1919
  type: array
1918
1920
  items:
@@ -41,7 +41,7 @@ module Archsight::Web::API::PageHelpers
41
41
  created: annotations["page/created"],
42
42
  updated: annotations["page/updated"],
43
43
  properties: page.properties.map { |key, value| { key: key, value: value, html: inline_markdown(value, page) } },
44
- confluence: annotations["page/confluence"],
44
+ links: annotations.select { |key, _| key.start_with?("link/") }.transform_keys { |key| key.delete_prefix("link/") },
45
45
  tags: Archsight::Resources::Page.annotation_matching("page/tags")&.value_for(page) || [],
46
46
  toc: annotations["page/toc"] == "yes" ? Archsight::PageTree.toc(body) : [],
47
47
  breadcrumb: tree.breadcrumb(page),
@@ -50,13 +50,6 @@ module Archsight::Web::API::PageHelpers
50
50
  }
51
51
  end
52
52
 
53
- # A short text (a page property) rendered as inline markdown: links, emphasis, `{macros}`, [[wiki links]], without the
54
- # paragraph around it
55
- def inline_markdown(text, page)
56
- html = markdown(text.to_s, base: Archsight::Assets.base_dir_for(page, resources_dir: Archsight.resources_dir), page: page)
57
- html.strip.sub(%r{\A<p>(.*)</p>\z}m, '\1')
58
- end
59
-
60
53
  # The header already shows the title, so a leading "# Title" that repeats it is dropped
61
54
  # (Confluence exports and hand-written pages usually start with one).
62
55
  def strip_duplicate_title(body, page)
@@ -5,6 +5,7 @@ require "sinatra/extension"
5
5
  require_relative "json_helpers"
6
6
  require_relative "page_helpers"
7
7
  require_relative "requirements_helpers"
8
+ require_relative "analysis_helpers"
8
9
  require_relative "../../assets"
9
10
 
10
11
  module Archsight; end
@@ -18,6 +19,7 @@ module Archsight::Web::API::Routes
18
19
  helpers Archsight::Web::API::JsonHelpers
19
20
  helpers Archsight::Web::API::PageHelpers
20
21
  helpers Archsight::Web::API::RequirementsHelpers
22
+ helpers Archsight::Web::API::AnalysisHelpers
21
23
 
22
24
  # Rendering is CPU work, previews are typed, not pasted
23
25
  MAX_DIAGRAM_SOURCE = 100_000
@@ -67,10 +69,13 @@ module Archsight::Web::API::Routes
67
69
  klass = Archsight::Resources[kind]
68
70
  json_error("Kind '#{kind}' not found", status: 404, error_type: "NotFound") unless klass
69
71
 
70
- instance = db.instance_by_kind(kind, name)
72
+ # an alias finds the one resource that has it; the response carries the real name
73
+ instance = db.instance_by_kind(kind, name) || db.instance_by_alias(kind, name)
71
74
  json_error("Instance '#{name}' not found", status: 404, error_type: "NotFound") unless instance
72
75
 
73
- json_response(build_instance_response(kind, instance))
76
+ # graph_layers: the layers its dependency graph follows when the page opens
77
+ json_response(build_instance_response(kind, instance)
78
+ .merge(graph_layers: Archsight::GraphvisRenderer.default_graph_layers(instance.class.layer)))
74
79
  end
75
80
 
76
81
  # GET /api/v1/pages - Page tree built from PageMenu resources, page tags and filters and the home page
@@ -25,17 +25,25 @@ class Archsight::Web::Application < Sinatra::Base
25
25
  attr_accessor :db
26
26
 
27
27
  def database
28
- @database ||= Archsight::Database.new(Archsight.resources_dir).tap(&:reload!)
28
+ @database ||= Archsight::Database.new(Archsight.resources_dir).tap(&:reload!).tap { |db| load_import_handlers(db) }
29
29
  end
30
30
 
31
31
  def reload!
32
32
  start = Time.new
33
33
  puts "== Reloading ..." if database.verbose
34
34
  database.reload!
35
+ load_import_handlers(database)
35
36
  dur = (Time.new - start) * 1000
36
37
  puts format("== done %0.2f ms", dur) if database.verbose
37
38
  end
38
39
 
40
+ # The import handlers, built-in and of the resources repository (import/handlerPath), so the editor knows the
41
+ # same handler names as `archsight lint`. A file that does not load is reported, the server keeps running.
42
+ def load_import_handlers(db)
43
+ require "archsight/import"
44
+ Archsight::Import::HandlerLoader.load(db).each { |problem| warn "Import handler: #{problem}" }
45
+ end
46
+
39
47
  # Configure application for the given environment
40
48
  # @param env [Symbol] :development or :production
41
49
  # @param logging [Boolean, nil] Override default logging setting
@@ -135,6 +143,15 @@ class Archsight::Web::Application < Sinatra::Base
135
143
  settings.environment == :development
136
144
  end
137
145
 
146
+ # A short text (a page property, an analysis table cell) rendered as inline markdown: links, emphasis,
147
+ # `{macros}`, [[wiki links]], without the paragraph around it
148
+ # @param page [Archsight::Resources::Page, nil] the page the text belongs to, for its relative images and macros
149
+ def inline_markdown(text, page = nil)
150
+ base = page && Archsight::Assets.base_dir_for(page, resources_dir: Archsight.resources_dir)
151
+ html = markdown(text.to_s, base: base, page: page)
152
+ html.strip.sub(%r{\A<p>(.*)</p>\z}m, '\1')
153
+ end
154
+
138
155
  # Render markdown to HTML with optional URL resolution for repository content
139
156
  # @param data [String] Markdown content
140
157
  # @param git_url [String, nil] Git URL for resolving relative paths (e.g., for README images)
@@ -282,14 +299,33 @@ class Archsight::Web::Application < Sinatra::Base
282
299
  serve_vue
283
300
  end
284
301
 
302
+ # The resources of a kind and the relations between them (see GraphvisRenderer#create_graph_kind)
303
+ get "/kinds/:kind/dot" do
304
+ halt 404, "kind #{params["kind"]} unknown" unless Archsight::Resources[params["kind"]]
305
+
306
+ content_type "text/plain"
307
+ create_graph_kind(db, params["kind"])
308
+ end
309
+
310
+ # An alias in the URL redirects to the resource's real name (`:` stays readable, the rest is escaped)
285
311
  get "/kinds/:kind/instances/:instance" do
312
+ kind = params["kind"]
313
+ name = params["instance"]
314
+ if Archsight::Resources[kind] && !db.instance_by_kind(kind, name) && (instance = db.instance_by_alias(kind, name))
315
+ redirect "/kinds/#{kind}/instances/#{ERB::Util.url_encode(instance.name).gsub("%3A", ":")}"
316
+ end
317
+
286
318
  serve_vue
287
319
  end
288
320
 
321
+ # `depth`: steps from the instance (a positive number; missing or `all`: every step), `layers`: the layers it
322
+ # follows, comma separated (missing or none known: every layer)
289
323
  get "/kinds/:kind/instances/:instance/dot" do
290
324
  @kind = params["kind"]
291
325
  @instance = params["instance"]
326
+ depth = params["depth"].to_s.match?(/\A[1-9]\d*\z/) ? params["depth"].to_i : nil
327
+ layers = params["layers"].to_s.split(",").map(&:strip) & Archsight::Resources::LAYERS
292
328
  content_type "text/plain"
293
- create_graph_one(db, @kind, @instance)
329
+ create_graph_one(db, @kind, @instance, max_depth: depth, layers: layers.empty? ? nil : layers)
294
330
  end
295
331
  end
@@ -57,7 +57,8 @@ module Archsight
57
57
  data = build_form_metadata(kind, klass)
58
58
  data[:mode] = "edit"
59
59
  data[:name] = instance.name
60
- data[:annotations] = instance.annotations.dup
60
+ # defaults are not in the file, a save leaves them out
61
+ data[:annotations] = instance.annotations.reject { |key, _| instance.defaulted?(key) }
61
62
  data[:relations] = extract_instance_relations(instance)
62
63
  data[:path_ref] = source_ref(instance)
63
64
  data[:content_hash] = source_content_hash(instance)
@@ -0,0 +1 @@
1
+ import{F as e,I as t,K as n,N as r,T as i,W as a,et as o,i as s,it as c,k as l,tt as u}from"./index-BGlYCbi7.js";var d={class:`api-docs-page`},f={key:0,class:`pico-color-red-500`},p=s({__name:`ApiDocsPage`,setup(s){let p=i(),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 a(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}}),(i,a)=>(n(),t(`div`,d,[r(`a`,{href:`#`,class:`back-link`,onClick:a[0]||=l(e=>u(p).back(),[`prevent`])},`← Back`),h.value?(n(),t(`div`,f,c(h.value),1)):e(``,!0),r(`div`,{ref_key:`container`,ref:m},null,512)]))}},[[`__scopeId`,`data-v-4823b89b`]]);export{p as default};
@@ -0,0 +1 @@
1
+ import{I as e,K as t,N as n,P as r,Z as i,et as a,t as o,u as s}from"./index-BGlYCbi7.js";import{t as c}from"./WikiPage-BoHNewCX.js";var l={key:1},u={__name:`DocPage`,props:{filename:String},setup(u){let d=u,f=a(null);function p(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 m(){let e=await s(d.filename);f.value=e?p(e,d.filename):{title:`Not found`,html:`<p>Documentation not found.</p>`,toc:[],breadcrumb:[{title:`Documentation`}]},o(f.value.title)}return i(()=>d.filename,m,{immediate:!0}),(i,a)=>f.value?(t(),r(c,{key:0,title:f.value.title,html:f.value.html,breadcrumb:f.value.breadcrumb,toc:f.value.toc},null,8,[`title`,`html`,`breadcrumb`,`toc`])):(t(),e(`article`,l,[...a[0]||=[n(`p`,null,`Loading...`,-1)]]))}};export{u as default};