Breaking change (breadcrumbs): Add JSONLD support#22
Conversation
|
@Flo0807 would you mind trying out this branch and see if it works for you and your needs? |
61a4baf to
92dbf3c
Compare
92dbf3c to
70ce7ed
Compare
sure |
I switched to this branch in my app. In general it works for my needs, but Claude still located some issues we might want to fix before merging this. @dbernheisel Likely bugConfig defaults shallow-merge into every item when defp merge_config_defaults(items, config) when is_list(items) do
Enum.map(items, &merge_config_defaults(&1, config))
endIf I set Smaller issuesRedundant
Docs
Doc inconsistency on input key casing. README and the Smaller notes
|
|
Good feedback. Let me see what we can optimize here re: module count, I was concerned about that too. |
|
@Flo0807 I've pushed a change. It should be largely the same, but to optimize compilation, I've opted for a mix compiler with a config, so you'll want to do something like this: # in mix.exs
compilers: [:seo_jsonld] ++ Mix.compilers()
# in config.exs
config :phoenix_seo, json_ld_types: :all
# Pick which Schema.org types to materialize via application config.
# Accepts a single entry or a list of entries:
#
# config :phoenix_seo, json_ld_types: :all
# config :phoenix_seo, json_ld_types: [:google, SEO.JSONLD.SearchAction]
#
# ### Available config entries
#
# - `:google` — the types Google has rich-result guides for plus their
# supporting types (~200 modules with their closure). **This is the
# default.**
# - `:all` — every regular Schema.org class (~820 modules).
# - Category atoms like `:medical`, `:place`, `:travel`, `:shopping`,
# `:creative_work`, `:action`, etc. See
# `Mix.Tasks.Compile.SeoJsonld.Generator.groups/0` for the full list.
# - Module names like `SEO.JSONLD.Article` (or strings like
# `"Article"` / `"schema:Article"`). |
Following on @Flo0807 great work, I decided to implement the full json-ld schema.org schema file and generate code from it to cover any remaining gaps for users. This is likely overkill for 90% of users, but niche apps will benefit.
I validated some generated output in both schema.org's validator and Google Rich Results validator
The already-implemented Breadcrumb json-ld module will go away since it was the only one implemented before, and moved into the generated module. There are some helper modules that can make it easier to use, so it's still there, but re-namespaced into
SEO.JSONLDGenerate typed JSON-LD modules from Schema.org
Adds a code generator (
priv/gen_json_ld.exs) that reads the full Schema.org vocabulary (priv/schemaorg.jsonld) and produces ~820 typed Elixir builder modules underSEO.JSONLD.*. Each module has abuild/1function that accepts snake_case Elixir maps/keyword lists and emits a JSON-LD-ready map with camelCase string keys,@context, and@type.@type attrs(input shape withrequired()/optional()per field) and@type t(output shape). Dialyzer catches missing required fields and wrong value types at compile time.:event_cancelled,:in_stock) that get converted to theirhttps://schema.org/...URLs. Unknown atoms raiseKeyError; non-atoms raiseArgumentError.Date,DateTime,Time,Duration, andURIstructs anywhere in the attrs map are automatically converted to their string forms (ISO 8601 /URI.to_string).@doclists only its own fields, with links to ancestor modules for inherited properties. Matches how schema.org organizes its own type pages.required()fields, curated examples with nested builder calls, and rich-result screenshots in their moduledocs.:inputsand:outputspseudo-fields that expand into Schema.org's hyphenated<property>-inputshorthand, with a composableSEO.JSONLD.Actionshelper.Hand-crafted convenience wrappers
Three modules are preserved across regeneration:
SEO.JSONLD.Breadcrumbs— compact[%{name: ..., item: ...}]list toBreadcrumbList+ListItemwith auto-positioned entries.SEO.JSONLD.FAQ—[%{question: ..., answer: ...}]list toFAQPage+Question+Answer.SEO.JSONLD.Actions—input_spec/1andinputs/1for building Schema.org Action input constraint strings.Config defaults
SEO.JSONLD.metanow merges site-wide config defaults (fromuse SEO, json_ld: %{...}) into each rendered payload. Item-supplied keys win.