{"id":13995098,"url":"https://github.com/MarkCodable/MarkCodable","last_synced_at":"2025-07-22T21:31:58.604Z","repository":{"id":58721480,"uuid":"531250579","full_name":"MarkCodable/MarkCodable","owner":"MarkCodable","description":"Swift Codable with human-friendly Markdown storage","archived":false,"fork":false,"pushed_at":"2023-10-03T16:30:09.000Z","size":73,"stargazers_count":330,"open_issues_count":12,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-16T08:03:57.289Z","etag":null,"topics":["codable","markdown","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MarkCodable.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-31T20:37:10.000Z","updated_at":"2024-11-02T17:59:59.000Z","dependencies_parsed_at":"2022-09-07T06:00:54.920Z","dependency_job_id":null,"html_url":"https://github.com/MarkCodable/MarkCodable","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkCodable%2FMarkCodable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkCodable%2FMarkCodable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkCodable%2FMarkCodable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkCodable%2FMarkCodable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MarkCodable","download_url":"https://codeload.github.com/MarkCodable/MarkCodable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227177766,"owners_count":17743163,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["codable","markdown","swift"],"created_at":"2024-08-09T14:03:14.976Z","updated_at":"2024-11-29T17:30:58.484Z","avatar_url":"https://github.com/MarkCodable.png","language":"Swift","readme":"# MarkCodable\n\nMarkdown Swift coding with an eye on human interaction.\n\n\u003e This library is still in flux until we find together what's the best way to use markdown encoding, check the issues and/or leave some feedback.\n\n## Overview\n\n**MarkCodable** encodes `Codable` values as Markdown text and decodes Markdown strings as Swift values. Markdown-representation allows humans to easily edit values by hand using their favorite text editor on any operating system or in a web interface.\n\nJSON is flexible but either too compact or too verbose to edit meaningfully by hand:\n\n```javascript\n[{\"number\":134,\"street\":\"main st.\",\"isSocial\":false,\"price\":{\"price\":1234.3199999999999,\"currency\":\"USD\"}},{\"number\":24,\"street\":\"Secondary st.\",\"isSocial\":true,\"price\":{\"price\":9234.3199999999997,\"currency\":\"JPY\"}}]\n```\n\nIn comparison, Markdown isn't as expressive but it's far simpler to view and edit by a human:\n\n```text\n|isSocial|number|price.currency|price.price|street       |\n|--------|------|--------------|-----------|-------------|\n|false   |134   |USD           |1234.32    |main st.     |\n|true    |24    |JPY           |9234.32    |Secondary st.|\n```\n\nThus, for the smaller scope of encoding data in an edit-friendly format, Markdown is a great choice.\n\n## Use cases\n\nYou encode or decode `Codable` values as with any other decoder, bar some limitations on nested data types:\n\n```swift\n// Encode into a Markdown string\nlet markdown = try MarkEncoder().encode([house1, house2])\n\n// Decode from a Markdown string\nlet houses = try MarkDecoder()\n    .decode([House].self, from: markdown)\n```\n\n### Configuration\n\nMarkdown is a viable alternative to json or yml files, especially for multiple configuration entries like per-environment or per-domain configurations, for example:\n\n```text\n| environment | host      | port | user | schema |\n|-------------|-----------|------|------|--------|\n| qa          | 127.0.0.1 | 8080 | test | http   |\n| production  | 2.317.1.2 | 9999 | app  | https  |\n```\n\n### Test and mock objects\n\nIn unit tests you often times need a number of test objects to create the test setup. Those are sometimes a bit clunky to always create in code so you can either include the Markdown in your tests or have it as an `.md` file in your test bundle:\n\n```text\n| userID | name | age | permissions |\n|--------|------|-----|-------------|\n|1       |peter | 32  |read         |\n|2       |admin | 100 |read,write   |\n```\n\n### Database\n\nFor simple relational data, using `MarkCodable` will allow you or your users to simply edit the data in any plain text editor. This is how a small podcast database might look like:\n\n```text\nUsers.md:\n| userID | name |\n|--------|------|\n|1       | John |\n|2       | Gui  |\n\nPodcasts.md:\n| podcastID | name            | hosts |\n|-----------|-----------------|-------|\n|1          |Swift by Sundell | 1     |\n|2          |Stacktrace       | 1,2   |\n```\n\nLoad the items by reading the files, decoding the values, and optionally store them as indexed dictionaries:\n\n```swift\nlet users = try MarkDecoder()\n    .decode([User].self, from: String(contentsOfFile: \"Users.md\"))\n    .reduce(into: [Int: User](), { $0[$1.id] = $1 })\n\nprint(users[2]) // [userID: 2, name: Gui]\n```\n\n## Installation\n\nUse the package directly in Xcode or via SwiftPM.\n\n```swift\ndependencies: [\n  .package(url: \"https://github.com/MarkCodable/MarkCodable\", from: \"0.6.0\"),\n]\n```\n\n## Demo App\n\nThis package contains a target called `marktest` that showcases some demo code. Run that demo from the package folder via:\n\n```text\nswift run marktest\n```\n\nTo see a demo of a full SwiftUI app (~70 lines of Swift) using a GitHub-hosted Markdown file as backend, check out [this repo](https://github.com/icanzilb/MarkCodingDemoApp).\n\n\u003cimg src=\"https://raw.githubusercontent.com/icanzilb/MarkCodingDemoApp/main/etc/app-screen.png\" width=320\u003e\n\n## Credits\n\nMIT License, Marin Todorov (2022)\n\n[@icanzilb on Twitter](https://twitter.com/icanzilb)\n\n## Help, feedback or suggestions?\n\n- There is a list of current [bugs](https://github.com/icanzilb/MarkCodable/issues?q=is%3Aissue+is%3Aopen+label%3Abug) if you'd like to pick one.\n- There is also a list of currently planned [enhancements](https://github.com/icanzilb/MarkCodable/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement).\n\n\n- [Open an issue](https://github.com/icanzilb/MarkCodable/issues) if you need help, if you found a bug, or if you want to discuss a feature request.\n- [Open a PR](https://github.com/icanzilb/MarkCodable/pulls) if you want to make a change to the code.\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMarkCodable%2FMarkCodable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMarkCodable%2FMarkCodable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMarkCodable%2FMarkCodable/lists"}