Module: PlanMyStuff::MetadataParser

Defined in:
lib/plan_my_stuff/metadata_parser.rb

Constant Summary collapse

LEGACY_DEPRECATION_MESSAGE =
'PlanMyStuff: legacy <!-- pms-metadata: ... --> body format detected. It will continue to parse ' \
'until 1.0.0, at which point legacy detection will be removed. New writes already use the visible ' \
'<details> block format introduced in 0.17.0; existing bodies migrate on their next write.'
METADATA_PATTERN =

New format: collapsible <details> block containing a JSON code fence. Renders visibly on GitHub (issue #58) instead of being hidden in an HTML comment.

%r{
  \A<details><summary>pms-metadata</summary>\n\n
  ```json\n(.*?)\n```\n\n
  </details>\n*
}mx
LEGACY_METADATA_PATTERN =

Legacy format kept for parsing only - existing issues serialized before 0.17.0 used a hidden HTML comment. They migrate to the new format on the next write.

/\A<!-- pms-metadata:(.*?) -->\n*/m

Class Method Summary collapse

Class Method Details

.matching_pattern(raw_body) ⇒ Regexp?

Returns the pattern that matches at the start of raw_body, or nil when neither matches.

Parameters:

  • raw_body (String)

Returns:

  • (Regexp, nil)

    the pattern that matches at the start of raw_body, or nil when neither matches



78
79
80
81
# File 'lib/plan_my_stuff/metadata_parser.rb', line 78

def matching_pattern(raw_body)
  return METADATA_PATTERN if raw_body.match?(METADATA_PATTERN)
  return LEGACY_METADATA_PATTERN if raw_body.match?(LEGACY_METADATA_PATTERN)
end

.parse(raw_body) ⇒ Hash{Symbol => Hash, String}

Extracts metadata JSON from the raw body

Parameters:

  • raw_body (String, nil)

Returns:

  • (Hash{Symbol => Hash, String})

    :metadata (Hash, empty when absent) and :body (String)



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/plan_my_stuff/metadata_parser.rb', line 33

def parse(raw_body)
  return { metadata: {}, body: '' } if raw_body.blank?

  pattern = matching_pattern(raw_body)
  return { metadata: {}, body: raw_body } if pattern.nil?

  PlanMyStuff.deprecator.warn(LEGACY_DEPRECATION_MESSAGE) if pattern == LEGACY_METADATA_PATTERN

  match = raw_body.match(pattern)
   = JSON.parse(match[1], symbolize_names: true)
  body = raw_body.sub(pattern, '')

  { metadata: , body: body }
rescue JSON::ParserError
  { metadata: {}, body: raw_body }
end

.serialize!(metadata, body) ⇒ String

Serializes a metadata hash and body into the stored format

Parameters:

Returns:

  • (String)

Raises:

  • (ArgumentError)

    if metadata is not a Hash or PlanMyStuff::CustomFields



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/plan_my_stuff/metadata_parser.rb', line 59

def serialize!(, body)
  if !.is_a?(Hash) && !.is_a?(PlanMyStuff::CustomFields)
    raise(ArgumentError, "metadata must be a Hash or PlanMyStuff::CustomFields, got #{.class}")
  end

  json =
    if .is_a?(PlanMyStuff::CustomFields)
      JSON.pretty_generate(.to_h)
    else
      JSON.pretty_generate()
    end

  "<details><summary>pms-metadata</summary>\n\n```json\n#{json}\n```\n\n</details>\n\n#{body}"
end