Packages
phoenix_kit
1.4.7
1.7.209
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit_web/live/modules/publishing/context/metadata.ex
defmodule PhoenixKitWeb.Live.Modules.Publishing.Metadata do
@moduledoc """
Metadata helpers for .phk (PhoenixKit) publishing entries.
Metadata is stored as a simple key-value format at the top of the file:
```
---
slug: home
title: Welcome
status: published
published_at: 2025-10-29T18:48:00Z
---
Content goes here...
```
"""
@type metadata :: %{
status: String.t(),
title: String.t(),
description: String.t() | nil,
slug: String.t(),
published_at: String.t()
}
@doc """
Parses .phk content, extracting metadata from frontmatter and returning the content.
"""
@spec parse_with_content(String.t()) :: {:ok, metadata(), String.t()} | {:error, atom()}
def parse_with_content(content) do
case extract_frontmatter(content) do
{:ok, metadata, body_content} ->
{:ok, metadata, body_content}
{:error, _} ->
# Fallback: try old XML format for backwards compatibility
metadata = extract_metadata_from_xml(content)
{:ok, metadata, content}
end
end
@doc """
Serializes metadata as YAML-style frontmatter.
"""
@spec serialize(metadata()) :: String.t()
def serialize(metadata) do
"""
---
slug: #{metadata.slug}
title: #{metadata.title || ""}
status: #{metadata.status}
published_at: #{metadata.published_at}
---
"""
end
@doc """
Returns default metadata for a new entry.
"""
@spec default_metadata() :: metadata()
def default_metadata do
now = DateTime.utc_now() |> DateTime.truncate(:second)
%{
status: "draft",
title: "",
description: nil,
slug: "",
published_at: DateTime.to_iso8601(now)
}
end
# Extract metadata from YAML-style frontmatter
defp extract_frontmatter(content) do
case Regex.run(~r/^---\n(.*?)\n---\n(.*)$/s, content) do
[_, frontmatter, body] ->
metadata = parse_frontmatter_lines(frontmatter)
{:ok, metadata, String.trim(body)}
_ ->
{:error, :no_frontmatter}
end
end
defp parse_frontmatter_lines(frontmatter) do
default = default_metadata()
lines =
frontmatter
|> String.split("\n")
|> Enum.map(&String.trim/1)
|> Enum.reject(&(&1 == ""))
metadata =
Enum.reduce(lines, %{}, fn line, acc ->
case String.split(line, ":", parts: 2) do
[key, value] ->
Map.put(acc, String.trim(key), String.trim(value))
_ ->
acc
end
end)
%{
title: Map.get(metadata, "title", default.title),
status: Map.get(metadata, "status", default.status),
slug: Map.get(metadata, "slug", default.slug),
published_at: Map.get(metadata, "published_at", default.published_at),
description: Map.get(metadata, "description")
}
end
# Extract metadata from <Page> element attributes (legacy XML format)
defp extract_metadata_from_xml(content) do
default = default_metadata()
# Simple regex-based extraction (for now)
title = extract_attribute(content, "title") || default.title
status = extract_attribute(content, "status") || default.status
slug = extract_attribute(content, "slug") || default.slug
published_at = extract_attribute(content, "published_at") || default.published_at
description = extract_attribute(content, "description")
%{
title: title,
status: status,
slug: slug,
published_at: published_at,
description: description
}
end
defp extract_attribute(content, attr_name) do
regex = ~r/<Page[^>]*\s#{attr_name}="([^"]*)"/
case Regex.run(regex, content) do
[_, value] -> value
_ -> nil
end
end
end