{"id":21637821,"url":"https://github.com/hi-folks/fusionable","last_synced_at":"2025-08-21T11:33:06.562Z","repository":{"id":261506326,"uuid":"882667338","full_name":"Hi-Folks/fusionable","owner":"Hi-Folks","description":"JavaScript package that aims to facilitate the management of structured, database-free content through Markdown files with Frontmatter.","archived":false,"fork":false,"pushed_at":"2024-11-23T22:03:46.000Z","size":267,"stargazers_count":24,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-08T23:22:41.112Z","etag":null,"topics":["cms","frontmatter","javascript","markdown","typescript-library"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/fusionable","language":"TypeScript","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/Hi-Folks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-11-03T12:51:11.000Z","updated_at":"2024-11-23T22:03:49.000Z","dependencies_parsed_at":"2024-11-06T23:18:32.700Z","dependency_job_id":null,"html_url":"https://github.com/Hi-Folks/fusionable","commit_stats":null,"previous_names":["hi-folks/fusionable"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hi-Folks%2Ffusionable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hi-Folks%2Ffusionable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hi-Folks%2Ffusionable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hi-Folks%2Ffusionable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hi-Folks","download_url":"https://codeload.github.com/Hi-Folks/fusionable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230511478,"owners_count":18237657,"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":["cms","frontmatter","javascript","markdown","typescript-library"],"created_at":"2024-11-25T04:07:02.604Z","updated_at":"2025-08-21T11:33:06.547Z","avatar_url":"https://github.com/Hi-Folks.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fusionable JS\n\n\u003cp align=center\u003e\n    \u003ci\u003e\n    \u003cstrong\u003eFusionable JS\u003c/strong\u003e is a JavaScript/TypeScript library designed for developers who work with Markdown as a content storage format\n    \u003c/i\u003e\n\u003c/p\u003e\n\n\u003cp align=center\u003e\n    \u003ca href=\"https://www.npmjs.com/package/fusionable\"\u003e\n        \u003cimg src=\"https://img.shields.io/npm/v/fusionable?style=for-the-badge\u0026label=Version\" alt=\"Latest Version on NPM\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/fusionable\"\n    \u003e\u003cimg src=\"https://img.shields.io/npm/d18m/fusionable?style=for-the-badge\" alt=\"Total Downloads\"\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cimg src=\"https://img.shields.io/npm/l/fusionable?style=for-the-badge\" alt=\"Packagist License\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/last-commit/hi-folks/fusionable?style=for-the-badge\" alt=\"GitHub last commit\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/Hi-Folks/fusionable/refs/heads/main/fusionable-cover.png\" alt=\"Fusionable is a JavaScript/TypeScript library designed for developers who work with Markdown as a content storage format\"\u003e\n\u003c/p\u003e\n\n**Fusionable** is a JavaScript/TypeScript library designed for developers who work with Markdown as a content storage format. It provides a powerful and flexible API to parse, filter, and manage collections of Markdown files based on their metadata (frontmatter). With Fusionable, you can easily treat Markdown files as structured content collections, enabling efficient filtering, sorting, and retrieval for various applications, from documentation systems to content-driven websites.\n\n\u003e Fusionable is still under development. We have the version 0.0.*. Feel free to use it in your experiment but not for production. Based on your feedback, we are working hard to make it stable and production-ready.\n\n\n\nAn example of using Fusionable for handling Markdown content:\n\n```javascript\n\nlet contents = new FusionCollection()\n      .loadFromDir(`./src/content`) //load markdown files from a directory\n      .filter(\"highlight\") // filtering\n      .orderBy(\"date\") // sorting markdown by `date` field\n      .limit(3) // limiting the result\n      .getItemsArray();\n\n```\n\nOnce you read this README, you can explore more how to use Fusionable with SvelteKit, Nextjs, and Nuxt:\n\n- **SvelteKit**: [How to Build a Content-Driven Static Site with Markdown, SvelteKit and Fusionable](https://dev.to/robertobutti/how-to-build-a-content-driven-static-site-with-markdown-sveltekit-and-fusionable-347f)\n- **Next.js**: [Building a website using Markdown content with Next.js App Router and Fusionable](https://dev.to/robertobutti/building-a-website-using-markdown-content-with-nextjs-app-router-and-fusionable-4kj7)\n- **Nuxt**: [Build a static website with Markdown content, using Nuxt and Fusionable (server API approach)](https://dev.to/robertobutti/build-a-static-website-with-markdown-content-using-nuxt-and-fusionable-server-api-approach-2o65)\n\n## What is Fusionable?\nFusionable is a library that allows you to organize, filter, and query **collections of Markdown files**. It leverages frontmatter metadata in each file, enabling you to:\n\n- Parse and extract content from Markdown files.\n- Retrieve files or collections based on metadata fields.\n- Sort and filter content collections dynamically with a fluent API.\n- Use Markdown files as a structured content source for building dynamic content applications.\n\nWith Fusionable, Markdown files have become more than simple documents; they have become manageable, queryable data sources.\n\nExample use cases for Fusionable\n\n- Content-driven Websites: Manage and retrieve blog posts, news articles, or other structured content stored in Markdown format.\n- Static Site Generation: Integrate Fusionable in static site generators to dynamically filter and sort Markdown content.\n- Documentation Systems: Organize documentation sections by metadata like tags, dates, or custom categories.\n\n## How to use Fusionable\n\nTo install the Fusionable JS package:\n\n```bash\nbun add fusionable\n```\n\nOr, if you are using NPM and Node, you can install it via the `npm` command:\n\n```bash\nnpm i fusionable\n```\n\nThen, you can create your Markdown files, for example, in the `./src/content` directory:\n\n```markdown\n---\ntitle: \"Post One\"\ndescription: This is the first post\ndate: \"2020-01-01\"\nhighlight: true\ntags: [\"typescript\", \"markdown\"]\ncover: https://picsum.photos/seed/post-1/400/200\n---\n## Hello\nContent of the *first post*.\n\n```\n\nYou can parse, load, filter, and sort the content via:\n\n```javascript\nimport FusionCollection from \"fusionable/FusionCollection\"\nlet contents = new FusionCollection()\n      .loadFromDir(`./src/content`)\n      .filter('highlight')\n      .orderBy(\"date\")\n      .limit(3)\n      .getItemsArray();\n```\n\nOr, you can simply get one content via the slug field in the Frontmatter:\n\n```javascript\nconst item = new FusionCollection()\n  .loadFromDir('./tests/data/')\n  .getOneBySlug('post-1');\n```\n\n\n\n## FusionCollection API\n\nThe `FusionCollection` class provides a flexible, chainable API for loading, filtering, sorting, limiting, and retrieving data. Below is a breakdown of the main methods available.\n\n### Method for loading a set of Markdown files from a directory: `loadFromDir()`\n\nLoads content from a specified directory and initializes the collection with items found in that directory.\n\nParameter:\n- `directoryPath` (`string`): The path to the directory from which to load content.\nIt returns: The `FusionCollection` instance allows for method chaining.\n\nExample:\n\n```javascript\n// loadFromDir(directoryPath: string): FusionCollection\nlet collection = new FusionCollection().loadFromDir(`./src/content`);\n```\n\n### Method for filtering markdown content:  `filter()`\n\nAdds a filter condition to refine the collection based on a specific field, comparison operator, and value.\n\nParameters:\n- `field`: (`string`) — The field to apply the filter on.\n- `operator`: (`OperatorEnum`, optional) — The comparison operator. Defaults to strict equality (`===`). Options include:\n  - OperatorEnum.EQUALS (===)\n  - OperatorEnum.NOT_EQUALS (!==)\n  - OperatorEnum.GREATER_THAN (\u003e)\n  - OperatorEnum.LESS_THAN (\u003c)\n  - OperatorEnum.GREATER_THAN_OR_EQUAL (\u003e=)\n  - OperatorEnum.LESS_THAN_OR_EQUAL (\u003c=)\n- `value`: (`any`, optional) — The value to compare the field against. Defaults to `true`.\n\nIt returns the `FusionCollection` instance allows for method chaining.\n\nExample:\n\n```javascript\n// Filter items where \"status\" is \"active\"\ncollection.filter(\"status\", OperatorEnum.EQUALS, \"active\");\n\n// Filter items where \"age\" is greater than 18\ncollection.filter(\"age\", OperatorEnum.GREATER_THAN, 18);\n\n// Filter items where \"highlight\" is true (using default operator and value)\ncollection.filter(\"highlight\");\n\n```\n\n### Method for sorting Markdown content: `orderBy()`\n\nSpecifies the field and direction for sorting the collection.\n\nParameters:\n- `field` (`string`): The name of the field to sort by.\n- `direction` (`'asc' | 'desc'`, default `'asc'`): The sort direction, either `'asc'` for ascending or `'desc'` for descending.\nIt returns: The `FusionCollection` instance, allowing for method chaining.\n\nExample:\n\n```javascript\n// orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): FusionCollection\ncollection.orderBy(\"date\", \"desc\");\n```\n\n### Method for limiting the number of Markdown content `limit()`\n\nLimits the number of items in the collection to the specified count.\n\nParameter:\n- `count` (`number`): The maximum number of items to include in the collection.\nIt returns: The `FusionCollection` instance, allowing for method chaining.\n\nExample:\n\n```javascript\n// limit(count: number): FusionCollection\ncollection.limit(3);\n```\n\n### Method for getting an array of content `getItemsArray()`\n\nRetrieves an array of raw item data from the collection after applying any specified filters, sorting, and limits.\n\nIt returns: An array containing the raw data of each item in the collection (`any[]`).\n\nExample:\n\n```javascript\n// getItemsArray(): any[]\nlet itemsArray = collection.getItemsArray();\n```\n\n### Method for getting array of metadata  `getMetadataArray()`\n\nAfter applying any specified filters, sorting, and limits, retrieve an array of raw item data from the collection. The difference to `getItemsArray()` is that the `getMetadataArray()` method excludes the markdown content and includes only the metadata. This method is useful if you need only metadata.\n\nIt returns: An array containing the raw data of each item in the collection (`any[]`).\n\nExample:\n\n```javascript\n// getMetadataArray(): any[]\nlet metadataArray = collection.getMetadataArray();\n```\n\n### Method for getting one element by its filename `getOneByFilename()`\n\nThe `getOneFilename()` allows you to retrieve one item (`FusionItem` and not `FusionCollection`) by filename.\n\nParameter:\n- `filename` (`string`) - the filename with the extension and no path (`post-1.md`)\n\nIt returns: the item (`FusionItem`) matching the filename, or `null` if no match is found.\n\nExample:\n\n```js\nlet filename = 'post-1.md';\nlet dir = './tests/data/no-frontmatter';\nlet post = new FusionCollection()\n            .loadFromDir(dir)\n            .getOneByFilename(filename);\nconsole.log(post.getContent());\nconsole.log(post.getSource()); // 'tests/data/no-frontmatter/post-1.md'\nconsole.log(post.getFilename()); // 'post-1.md'\nconsole.log(post.getName()); // 'post-1'\n\n```\n\n### Method for getting one element by slug  `getOneBySlug()`\n\nRetrieves a single item from the collection by its slug.\n\nParameter:\n- `slug` (`string`) - The unique slug identifier for the item to retrieve.\n\nIt returns: the item matching the slug, or `null` if no match is found. (`FusionItem`).\n\nExample:\n\n```javascript\nconst item = new FusionCollection()\n  .loadFromDir('./tests/data/')\n  .getOneBySlug('post-1');\n// So, you can access to some information/content:\nitem.getContent(); // the markdown content\nitem.getFields(); // the frontmatter fields\nitem.getField(\"title\"); // the title frontmatter field\n```\n\nThe strong assumption here is that you have the `slug` field in your frontmatter sections, for example:\n\n```markdown\n---\ntitle: \"Post One\"\nslug: \"post-1\"\ndate: \"2023-01-01\"\ntags: [\"typescript\", \"markdown\"]\n---\n## Hello\nContent of the *first post*.\n```\n\n## Why Fusionable?\n\nMarkdown is widely used for creating structured, lightweight, and readable content. However, Markdown alone lacks the tools for organizing, filtering, and retrieving files based on specific criteria—features that are essential for scaling projects or building complex content management workflows. Fusionable bridges this gap by adding structure and manageability to Markdown collections, so developers can take advantage of the following:\n\n- Metadata-driven Organization: Fusionable reads the **frontmatter** (YAML metadata) in each Markdown file, making it easy to filter, sort, and group content collections based on properties like tags, categories, publish dates, or any custom fields.\n- Content Management as Code: By treating Markdown files as structured data, Fusionable allows developers to use them (their Markdown files) as a content database, with programmatic access for creating dynamic websites, static site generators, or custom documentation tools.\n- Enhanced Content Retrieval: Fusionable simplifies accessing Markdown content collections with a fluent API, so you can filter, sort, and retrieve content effortlessly, all in one place.\n- Flexibility and Extensibility: Fusionable’s API is built with flexibility in mind. It supports various filtering and sorting operations on Markdown collections, making it ideal for use with JavaScript frameworks or other content pipelines.\n\n## Contributing\n\nIf you are interested in contributing to Fusionable, you are welcome! You could evaluate the following:\n\n- Improve the documentation in the readme\n- Write a post about Fusionable\n- Contributing to the source code, fixing an issue, or implementing a new feature. For that, my suggestion is to read [the contributing file](https://github.com/Hi-Folks/fusionable/blob/main/CONTRIBUTING.md)\n\n## References\n\n\u003e This project was created using `bun init` in bun v1.1.33. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhi-folks%2Ffusionable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhi-folks%2Ffusionable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhi-folks%2Ffusionable/lists"}