Class: OKF::Render::Graph
- Inherits:
-
Object
- Object
- OKF::Render::Graph
- Defined in:
- lib/okf/render/graph.rb
Overview
Renders an OKF::Bundle::Graph as the interactive graph page. The markup lives in graph/template.html.erb; #render returns the HTML string.
The page boots from a minimal payload — nodes carry only id + title, plus compact TYPES/TAGS inverted indexes for colouring and filtering. It has two data modes, both driven by one template:
server mode (embed: nil) — the default. Each concept's markdown body,
metadata, catalog, index and log are pulled from OKF::Server::App on
demand via fetch, so the initial payload stays small and bodies read
live from disk (edits show without a restart). Nothing extra embedded.
render mode (embed: payload) — `okf render` bakes the whole bundle in via
.static below: the same fetch getters resolve from the injected payload
instead, so the single file needs no server (e.g. GitHub Pages).
NOTE (trust boundary): the page loads Cytoscape + marked from a CDN, so it needs network for those libraries even in render mode. Fetched/embedded markdown is sanitized client-side (DOMPurify.sanitize(marked.parse(...))) and all inline--escaped by #json_for_script (stdlib ERB does not auto-escape). Still, only serve bundles you trust.
Constant Summary collapse
- TEMPLATE =
File.("graph/template.html.erb", __dir__)
- LAYOUTS =
%w[cose concentric breadthfirst circle grid].freeze
- MIN_SIZE =
Node-diameter range in px; the template scales within it by node degree.
14- MAX_SIZE =
44- LT_ESCAPE =
The 6-character JSON unicode escape for
<(backslash, u, 0, 0, 3, c), built from the backslash code point so no literal escape appears here. (92.chr(Encoding::UTF_8) + "u003c").freeze
Class Method Summary collapse
-
.payload(folder) ⇒ Object
What the baked page carries in place of the endpoints a live server would answer.
-
.static(folder, title: nil, link: nil, layout: "cose") ⇒ Object
okf render: the whole page as one self-contained file, the bundle baked in, so it hosts where no server answers a fetch.
Instance Method Summary collapse
-
#initialize(graph, title: nil, link: nil, layout: "cose", node_endpoint: "node", meta_endpoint: "node/meta", embed: nil, siblings: nil, self_slug: nil, hub_path: nil) ⇒ Graph
constructor
+node_endpoint+/+meta_endpoint+ are the (mount-relative) URLs the page fetches a concept's raw markdown and metadata fragment from — relative so the page works whether served at "/" or mounted under a Rails prefix.
- #render ⇒ Object
Constructor Details
#initialize(graph, title: nil, link: nil, layout: "cose", node_endpoint: "node", meta_endpoint: "node/meta", embed: nil, siblings: nil, self_slug: nil, hub_path: nil) ⇒ Graph
+node_endpoint+/+meta_endpoint+ are the (mount-relative) URLs the page
fetches a concept's raw markdown and metadata fragment from — relative so
the page works whether served at "/" or mounted under a Rails prefix.
embed is the render-mode payload (nil = server mode); see the class doc.
+siblings+/+self_slug+/+hub_path+ carry the hub's bundle switcher into the
page (server mode only). nil — the standalone-server and okf render
default — injects an empty SIBLINGS, so the switcher never appears in a
single bundle or a static file.
75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/okf/render/graph.rb', line 75 def initialize(graph, title: nil, link: nil, layout: "cose", node_endpoint: "node", meta_endpoint: "node/meta", embed: nil, siblings: nil, self_slug: nil, hub_path: nil) @graph = graph @title = title @link = link @layout = layout @node_endpoint = node_endpoint @meta_endpoint = @embed = @siblings = siblings @self_slug = self_slug @hub_path = hub_path end |
Class Method Details
.payload(folder) ⇒ Object
What the baked page carries in place of the endpoints a live server would answer. Every key here is data a client getter reads from EMBED instead of fetching — and each derives from the same folder method the matching OKF::Server::App endpoint uses, so the bake and the live server cannot drift (/node/meta is the exception: the fragment is derived on the client from the catalog's raw description, so no map is baked for it).
58 59 60 61 62 63 64 65 |
# File 'lib/okf/render/graph.rb', line 58 def self.payload(folder) { catalog: folder.catalog, index: folder.directory_index, logs: folder.log_entries, bodies: folder.concepts.each_with_object({}) { |concept, map| map[concept.id] = concept.body.to_s } } end |
.static(folder, title: nil, link: nil, layout: "cose") ⇒ Object
okf render: the whole page as one self-contained file, the bundle baked
in, so it hosts where no server answers a fetch. Takes any bundle handle
(an OKF::Bundle::Folder) and returns the HTML string.
48 49 50 |
# File 'lib/okf/render/graph.rb', line 48 def self.static(folder, title: nil, link: nil, layout: "cose") new(folder.graph(minimal: true), title: title || folder.name, link: link, layout: layout, embed: payload(folder)).render end |
Instance Method Details
#render ⇒ Object
89 90 91 |
# File 'lib/okf/render/graph.rb', line 89 def render ERB.new(File.read(TEMPLATE, encoding: "UTF-8")).result(binding) end |