gloo-md 1.1 → 1.2

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gloo-md.rb +6 -4
  3. data/lib/md_doc.rb +178 -0
  4. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4263fc76f70591ae470fa3bf72800df6bc2055fe6ea73610940d4bc398548b6
4
- data.tar.gz: f645e639d0759dab026b38d8b266a4e67004c977039402b6c4efac5a0ee12008
3
+ metadata.gz: 26d3d6ba34f0daaa4881b63fa84848e8ad01043d34357e67d93aad97d85bfe64
4
+ data.tar.gz: cd27b868d2846861b17031cbf2076c24b1f1d996238f208d5e2a1760533086d3
5
5
  SHA512:
6
- metadata.gz: c885359772e7b95bcf53baa9d2e62db12f9a03a86dce068a03c8c1eb9ea8aa9f10ea07252a929ebef0ad373b364f9b43fd6a6427aff134e6586468d9f2f7972c
7
- data.tar.gz: 5bce0c04c4cc2f76e54fa69b6aa2b86b1f5506953eb04de23274c1102e5afc7c40d74e81340443da7a706d59f603826ed1e5964567c61ef50e4f120d29abb672
6
+ metadata.gz: 670f1cc4ca37f23fcd67ae241c26bb8c334d9cef5a49de5b5d4b3ac587e629d5f02a3999fdf390c1642c94aeec829b63ccbc4bb6da49a338fb317d81ff0ca2ba
7
+ data.tar.gz: cc147be4c2af1f0a82e64e504e397d6f76f32cc11e34c38d85645e6ef69324339d67b34f416e5d1a3c948cf9abfa5c37fe48236745031712a487c4c29d77aefd
data/lib/gloo-md.rb CHANGED
@@ -4,18 +4,20 @@
4
4
  # This file is loaded when someone does `require 'gloo-md'`
5
5
  #
6
6
  require 'md'
7
+ require 'md_doc'
7
8
  require 'markdown_ext'
8
9
 
9
- #
10
+ #
10
11
  # Registers the extension.
11
- #
12
+ #
12
13
  class MdInit < Gloo::Plugin::Base
13
14
 
14
- #
15
+ #
15
16
  # Register verbs and objects.
16
- #
17
+ #
17
18
  def register( callback )
18
19
  callback.register_obj( Md )
20
+ callback.register_obj( MdDoc )
19
21
  end
20
22
 
21
23
  end
data/lib/md_doc.rb ADDED
@@ -0,0 +1,178 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2026 Eric Crane. All rights reserved.
3
+ #
4
+ # A Markdown document with YAML frontmatter.
5
+ # Holds a file path and exposes the frontmatter fields as container
6
+ # children and the Markdown body as a text child.
7
+ #
8
+ require 'yaml'
9
+
10
+ class MdDoc < Gloo::Core::Obj
11
+
12
+ KEYWORD = 'md_doc'.freeze
13
+ KEYWORD_SHORT = 'md_doc'.freeze
14
+
15
+ PATH = 'path'.freeze
16
+ FRONTMATTER = 'frontmatter'.freeze
17
+ BODY = 'body'.freeze
18
+
19
+
20
+ # ---------------------------------------------------------------------
21
+ # Type identity
22
+ # ---------------------------------------------------------------------
23
+
24
+ #
25
+ # The name of the object type.
26
+ #
27
+ def self.typename
28
+ return KEYWORD
29
+ end
30
+
31
+ #
32
+ # The short name of the object type.
33
+ #
34
+ def self.short_typename
35
+ return KEYWORD_SHORT
36
+ end
37
+
38
+ #
39
+ # Set the value with any necessary type conversions.
40
+ #
41
+ def set_value( new_value )
42
+ self.value = new_value.to_s
43
+ end
44
+
45
+
46
+ # ---------------------------------------------------------------------
47
+ # Children
48
+ # ---------------------------------------------------------------------
49
+
50
+ #
51
+ # Does this object have children to add when an object
52
+ # is created in interactive mode?
53
+ #
54
+ def add_children_on_create?
55
+ return true
56
+ end
57
+
58
+ #
59
+ # Add the default children: path, frontmatter, body.
60
+ #
61
+ def add_default_children
62
+ fac = @engine.factory
63
+ fac.create_file PATH, nil, self
64
+ fac.create_can FRONTMATTER, self
65
+ fac.create_text BODY, nil, self
66
+ end
67
+
68
+
69
+ # ---------------------------------------------------------------------
70
+ # Messages
71
+ # ---------------------------------------------------------------------
72
+
73
+ #
74
+ # Get a list of message names that this object receives.
75
+ #
76
+ def self.messages
77
+ return super + %w[read write]
78
+ end
79
+
80
+ #
81
+ # Read the file at path, parse frontmatter and body, populate children.
82
+ # Frontmatter children are created dynamically from whatever keys are present.
83
+ #
84
+ def msg_read
85
+ path = resolve_path
86
+ return unless path
87
+
88
+ unless File.exist?( path )
89
+ @engine.log.error "md_doc file not found: #{path}"
90
+ return
91
+ end
92
+
93
+ content = File.read( path )
94
+ fm_hash, body_text = parse_frontmatter( content )
95
+
96
+ fm_can = find_child FRONTMATTER
97
+ if fm_can && fm_hash
98
+ fm_hash.each do |key, val|
99
+ child = fm_can.find_add_child( key.to_s, 'string' )
100
+ child.set_value val.to_s
101
+ end
102
+ end
103
+
104
+ body = find_child BODY
105
+ body.set_value( body_text ) if body
106
+ end
107
+
108
+ #
109
+ # Serialize frontmatter and body children back to the file at path.
110
+ # Creates the file if it does not exist.
111
+ #
112
+ def msg_write
113
+ path = resolve_path
114
+ return unless path
115
+
116
+ fm_can = find_child FRONTMATTER
117
+ fm_hash = {}
118
+ if fm_can
119
+ fm_can.children.each do |child|
120
+ fm_hash[ child.name ] = child.value
121
+ end
122
+ end
123
+
124
+ body = find_child BODY
125
+ body_text = body ? body.value.to_s : ''
126
+
127
+ content = build_content( fm_hash, body_text )
128
+ File.write( File.expand_path( path ), content )
129
+ end
130
+
131
+
132
+ # ---------------------------------------------------------------------
133
+ # Private helpers
134
+ # ---------------------------------------------------------------------
135
+
136
+ private
137
+
138
+ #
139
+ # Get the expanded path string from the path child.
140
+ #
141
+ def resolve_path
142
+ o = find_child PATH
143
+ return nil unless o
144
+ return nil if o.value.to_s.strip.empty?
145
+
146
+ File.expand_path( o.value.to_s )
147
+ end
148
+
149
+ #
150
+ # Parse YAML frontmatter from file content.
151
+ # Returns [fm_hash, body_text]. If there is no frontmatter block,
152
+ # fm_hash is empty and body_text is the full content.
153
+ #
154
+ def parse_frontmatter( content )
155
+ if content =~ /\A---\s*\n(.*?\n)---\s*\n?(.*)\z/m
156
+ fm_hash = YAML.safe_load( $1 ) || {}
157
+ body_text = $2
158
+ return fm_hash, body_text
159
+ end
160
+
161
+ return {}, content
162
+ end
163
+
164
+ #
165
+ # Build the file content string from a frontmatter hash and body text.
166
+ # Emits frontmatter as YAML between --- delimiters.
167
+ #
168
+ def build_content( fm_hash, body_text )
169
+ if fm_hash.empty?
170
+ return body_text
171
+ end
172
+
173
+ # to_yaml emits "---\nkey: val\n"; strip the leading "---\n" and rewrap.
174
+ fm_yaml = fm_hash.to_yaml.sub( /\A---\n/, '' )
175
+ "---\n#{fm_yaml}---\n#{body_text}"
176
+ end
177
+
178
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gloo-md
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.1'
4
+ version: '1.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Crane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-11 00:00:00.000000000 Z
11
+ date: 2026-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redcarpet
@@ -34,6 +34,7 @@ files:
34
34
  - lib/gloo-md.rb
35
35
  - lib/markdown_ext.rb
36
36
  - lib/md.rb
37
+ - lib/md_doc.rb
37
38
  homepage: https://gloo.ecrane.us/
38
39
  licenses:
39
40
  - MIT