I was wondering if anyone has an idea of how to basically create a parametrized, reusable content adapter using modules, so that target sites can reuse it with different input data.
Below is some code to get data and create pages from data. What I wanted to do was to add this to my theme module (or maybe a separate module if that is better - I have no idea ) and somehow be able to pull this into my sites while allowing a user/dev to change what data is used when they import/mount it.
{{ $dataFile := .dataFile }}
{{ $useHugoData := .useHugoData | default "false" }}
{{ $hugoData := "" }}
{{ if eq $useHugoData "true" }}
{{ if or (hasPrefix $dataFile "http://") (hasPrefix $dataFile "https://") }}
{{ with resources.GetRemote $dataFile }}
{{ $hugoData = . | transform.Unmarshal }}
{{ end }}
{{ else }}
{{ with resources.Get $dataFile }}
{{ $hugoData = . | transform.Unmarshal }}
{{ else with fileExists $dataFile }}
{{ $hugoData = readFile $dataFile }}
{{ else }}
{{ errorf "File not found: %s" $dataFile }}
{{ end }}
{{ end }}
{{ end }}
{{ return $hugoData }}
I would call this partial in my go template like so:
{{ $dataFile := "path/to/your/data.json or remote location" }}
{{ $hugoData := partial "get-hugo-data.html" (dict "dataFile" $dataFile "useHugoData" "true") }}
{{ with $hugoData }}
{{ template "walk" (dict "data" .roots "path" "" "ctx" $) }}
{{ end }}
{{ define "walk" }}
{{ range .data }}
<!-- Build the path for the current node -->
{{ $path := path.Join $.path .title }}
<!-- Render the page content -->
{{ template "add-page" (dict "data" . "path" $path "ctx" $.ctx) }}
<!-- Recursively walk through children -->
{{ with .children }}
{{ template "walk" (dict "data" . "path" $path "ctx" $.ctx) }}
{{ end }}
{{ end }}
{{ end }}
{{ define "add-page" }}
{{ with .data }}
<!-- Match and create taxonomies from config -->
{{ $taxonomies := readFile "config/_default/taxonomies.yaml" | transform.Unmarshal }}
{{ $params := dict }}
{{ range $key, $value := . }}
{{ if isset $taxonomies $key }}
{{ $taxonomy := index $taxonomies $key }}
{{ $params = merge $params (dict $taxonomy $value) }}
{{ else }}
{{ $params = merge $params (dict $key $value) }}
{{ end }}
{{ end }}
{{ $content := dict "mediaType" "text/markdown" "value" .content }}
{{$kind := ""}}
{{$type := ""}}
{{ if .children}}
{{ $kind = "section" }}
{{ $type = "customTypeForSection"}}
{{ end }}
{{ else }}
{{ $kind = "page" }}
{{ $type = "docs"}}
{{ end }}
{{ $page := dict
"content" $content
"kind" $kind
"params" $params
"path" $.path
"title" .title
"type" $type
}}
{{ $.ctx.AddPage $page }}
{{ end }}
{{ end }}
I am not confident with any approach right now so would love some Hugo wisdom, I know I can add this content adapter to the myThemeModule/site/content folder and bring it in but ideally we would somehow be able to call the content adapter like we would a partial and pass in an argument (from page context or wherever) which basically tells the content adapter what dataset to use when making the pages.
If someone could help me with some ideas that would be much appreciated, and if I need to clarify I can try my best!
Ah this is brilliant! I love the idea of the target site config being the central source of determining where my adapter goes (through module mount pathing) in addition to being the source of dataset options.
I will move the data collection into something more segmented for maintenance, looking forward to giving this a try tomorrow!
I appreciate you taking the time, this is quite fun for me so thanks for the help
I have followed your approach as discussed, and it works as expected! I define a list of data options in params.contentAdapter & pull from these in my _content.gotmpl
[params.ContentAdapter]
enable = true
data = ["datasetFileName"]
I can then pass this ādatasetFileNameā into my partial & build pages with some logic to determine if I want to use a remote file or one in the site/data folder.
My follow-up question is this:
My idea is to reuse this same go template multiple times by mounting it in different spots on the site but for each instance to use different datasets. I need some sort of method to map a data file to the instance of the adapter I am mounting.
My initial thinking is to just put the name of the dataset or remote URL in the _index.md fileās frontmatter where the content.gotmpl is being mounted- and as you probably expected, I would not have access to this pageās params in the go template (they wouldnāt exist yet), ha!
I am sure I could try some stuff to create this sort of mapping in the config or just make multiple content adapter wrappers which call the addPages partial with different data, but wondering what is the most viable option.
I expected that question and tried that before.
Unfortunately the new templates.Current function reports the filesystem path ā which is the one from the theme ā always when mounted. Namemethod. and Filename returns nil . Found no other method for solving that problem
If a content adapter could provide a method to return the path relative to the contentDir this would help you out. To support generic adapters - But I think thatās was the intended use when it starts.
dunno if this maybe worth a feature request - @bep what do you think.
additional info:
when a content adapter is mounted to two different target folders in the contentDir.
and you modify it. Hugo server reports two changes on for each content folder