{"id":29199209,"url":"https://github.com/drewstinnett/labdoc","last_synced_at":"2026-04-27T00:31:46.509Z","repository":{"id":45578336,"uuid":"427149714","full_name":"drewstinnett/labdoc","owner":"drewstinnett","description":"Generate a GitLab Personal README.md from a template","archived":false,"fork":false,"pushed_at":"2023-03-07T03:26:35.000Z","size":201,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-02T10:05:00.599Z","etag":null,"topics":["gitlab","golang","plugin","readme"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drewstinnett.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-11T21:35:14.000Z","updated_at":"2022-03-27T03:07:34.000Z","dependencies_parsed_at":"2024-06-21T02:08:36.226Z","dependency_job_id":"12f9d5e6-c7e6-4e3d-9fd5-c543ed0ae2f1","html_url":"https://github.com/drewstinnett/labdoc","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/drewstinnett/labdoc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewstinnett%2Flabdoc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewstinnett%2Flabdoc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewstinnett%2Flabdoc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewstinnett%2Flabdoc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drewstinnett","download_url":"https://codeload.github.com/drewstinnett/labdoc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewstinnett%2Flabdoc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32318417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"ssl_error","status_checked_at":"2026-04-26T23:26:25.802Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gitlab","golang","plugin","readme"],"created_at":"2025-07-02T10:01:08.432Z","updated_at":"2026-04-27T00:31:46.493Z","avatar_url":"https://github.com/drewstinnett.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LabDoc\n\nGenerate a README.md for GitLab similar to the way\n[markscribe](https://github.com/muesli/markscribe) does in GitHub.\n\n## Usage\n\n### Generate README.md\n\nCurrently the rendered version of your template will be printed to stdout. Just\ndirect it in to the target file like so:\n\n```bash\nlabdoc generate example_templates/rss.tpl \u003e README.md\n```\n\n### Show Examples\n\nPrint out example usage, based on plugin data:\n\n```bash\nlabdoc examples\n```\n\n### Run in Gitlab CI\n\nCreate a new personal access token from your profile page on Gitlab.com (or your\nlocally hosted URL). It will need the following permissions: `read_user`,\n`read_api`, and `write_repository`. Save this token as `GITLAB_TOKEN` in your\nrunner variable section, along with any other plugin variables that you might\nneed.\n\nSet up your `.gitlab-ci.yml` file with something like the following:\n\n```yaml\n---\nstages:\n  - release\n\nrelease:\n  stage: release\n  image:\n    name: brewerdrewer/labdoc:latest\n    entrypoint: ['']\n  variables:\n    GIT_DEPTH: 0\n  script:\n    - /labdoc generate templates/README.md.tpl \u003e README.md\n    - git config --global user.email \"${GITLAB_USER_EMAIL}\"\n    - git config --global user.name \"${GITLAB_USER_NAME}\"\n    - CHANGED=$(git diff)\n    - |\n      if [ -n \"${CHANGED}\" ]; then\n        git commit -a -m 'Updating readme'\n        git push https://${GITLAB_USER_LOGIN}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_ROOT_NAMESPACE}/${CI_PROJECT_NAME}.git HEAD:main\n      fi\n```\n\n## Plugins\n\n### Builtin Template\n\nThis is for generic template functions across multiple plugins\n\n#### builtinDebug\n\nOh dude, would love do document this better. For now, you can use the\n`builtinDebug` filter though. Would love some help on making this more clear\n\n```go\n{{ . | builtinDebug }}\n```\n\nThis will show a json representation of the object\n\n#### builtinAgo\n\nConvert a time.Time or string to 'time ago'. If it can't convert the string to a\ntime.Time, it'll just return the original string\n\n```go\n{{ .Title }} - {{ .PublishedParsed | builtinAgo }}\n```\n\n### RSS Plugin\n\nSimple plugin for just loading an rss file and returning the entries\n\n#### rssListFeed\n\nNo additional configuration needed, just pass in a feed URL and a limit\n\n```go\n{{ range rssListFeed \"https://www.rogerebert.com/feed\" 10}}\n```\n\n### Letterboxd Plugin\n\nUses the letterboxd rss feeds to query your recent events. Requires\n`LETTERBOXD_USER` environment variable to be set\n\n#### letterboxdRecentlyWatched\n\n```go\n{{ range letterboxdRecentlyWatched 5 }}\n```\n\n### Goodreads Plugin\n\nUses the goodreads rss feed, since the API has been deprecated. You'll need to\nset both of these variables in order for this to work:\n\n`GOODREADS_RSSUSERID` - You can find this in your profile link. For example, if\nyou see `https://www.goodreads.com/user/show/111216449-drew-stinnett`, then\n`111216449` is what `GOODREADS_RSSUSERID` should be set to\n\n`GOODREADS_RSSKEY` - Unsure how private this should be, but if it's in an RSS\nurl, assuming it's not too private. Pull this by clicking on the rss icon in the\ngoodreads web interface, and selecting the long string after `key=` and before\n`\u0026`in the url\n\n#### goodreadsRecentlyRead\n\n```go\n{{ range goodreadsRecentlyRead 10 }}\n```\n\n## Extending with more Plugins\n\nWe would love to have more plugins!\n\nPlugins should have their own directory under\n[internal/plugins](internal/plugins), and have the following interface:\n\n```go\ntype plug struct{}\n\nfunc (p *plug) TemplateFunctions() (template.FuncMap, error) {\n  templ := template.FuncMap{\n    \"templateFunctionFoo\":       templateFunctionFoo,\n  }\n  return templ, nil\n}\n\nfunc (p *plug) Examples() string {\n    return `## Example Entries\n{{ range rssListFeed \"https://www.example.com/feed\" 10}}\n[{{ .Title }}]({{ .Link }}) on {{ .Published }}\n{{- end }}\n`\n}\n\nfunc templateFunctionFoo(limit int) ([]someOject, error){\n  ...\n  return objects, nil\n}\n\nfunc init() {\n  labdoc.Add(\"myplugin\", func() labdoc.Plugin {\n    return \u0026plug{}\n  })\n}\n```\n\nOnce your plugin is ready, register it in\n[plugins/all/all.go](plugins/all/all.go)\n\nNote that in the above example, the template function will be namespaced by the\nplugin name, and can be called using `mypluginTemplateFunctionFoo`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrewstinnett%2Flabdoc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrewstinnett%2Flabdoc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrewstinnett%2Flabdoc/lists"}