{"id":19450939,"url":"https://github.com/rixo/routix","last_synced_at":"2026-06-07T21:32:23.085Z","repository":{"id":42623996,"uuid":"254773957","full_name":"rixo/routix","owner":"rixo","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-12T10:56:49.000Z","size":361,"stargazers_count":2,"open_issues_count":7,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-09T15:03:59.362Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rixo.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}},"created_at":"2020-04-11T02:00:14.000Z","updated_at":"2022-03-30T15:30:01.000Z","dependencies_parsed_at":"2022-09-08T01:20:33.486Z","dependency_job_id":null,"html_url":"https://github.com/rixo/routix","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rixo%2Froutix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rixo%2Froutix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rixo%2Froutix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rixo%2Froutix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rixo","download_url":"https://codeload.github.com/rixo/routix/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240638417,"owners_count":19833283,"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":[],"created_at":"2024-11-10T16:39:39.425Z","updated_at":"2026-06-07T21:32:23.031Z","avatar_url":"https://github.com/rixo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Routix\n\n\u003e Low level routes generator with a focus on performance and customizability.\n\nRoutix watches some directory for files with some given extensions, and outputs a flat list of routes (files) and/or a nested tree.\n\n- FS is hit only once for listing and stats by the watcher\n- the tree is fully constructed from user provided `path`\n- all processing is done at compile time\n- the flat routes list and the tree references the same runtime objects\n\n## Principles\n\nThe file watcher already has to list and stats from the file system; Routix doesn't hit the file system beyond that. During watch, most things are kept in memory, and only the relevant bits are recomputed.\n\nThe output is very basic and can easily be customized by providing a `parse` function that receives a file and can change its `path` or augment it with custom properties, and a `format` function that converts the intermediary file objects to the format that will be written into the generated files.\n\nOnly files (not directories) are taken into account. The tree hierarchy is fully constructed from the file objects' `path` property that is returned by the `parse` function.\n\n## Installation\n\n```bash\nnpm install --dev routix\n```\n\n## Rollup plugin\n\n```js\nimport routix from 'routix/rollup'\n\nexport default {\n  // ...\n\n  plugins: [\n    routix({\n      dir: 'src/pages',\n      extensions: ['.svelte', '.svx'],\n      write: { routes: true, tree: true },\n      leadingSlash: true,\n      parse: file =\u003e {\n        // . =\u003e /\n        file.path = file.path.replace(/\\./g, '/')\n\n        const segments = file.path.split('/')\n\n        let segment = segments.pop()\n\n        // foo/index =\u003e foo\n        if (segment === 'index') {\n          file.path = segments.join('/') || '/'\n          segment = segments[segments.length - 1]\n        }\n\n        // foo_bar_baz =\u003e \"foo bar baz\"\n        file.title = segment ? segment.replace(/_+/g, ' ') : '/'\n      },\n      format: ({ title }) =\u003e ({ title }),\n    }),\n\n    // ...\n  ],\n}\n```\n\n## Node API\n\n```js\nimport Routix from 'routix'\n\n// init\nconst routix = Routix({ ...options })\n\n// start reading FS (and watching if watch option is true)\nawait routix.start()\n\n// wait for a build to finish\nawait routix.onIdle()\n\n// wait for a change event for at most x ms, then until the build completes\nawait routix.onIdle(100)\n\n// is the given file is one of our write target (i.e. routes.js or tree.js)?\nroutix.isWriteTarget(file)\n\n// is the given file watched by Routix (i.e. a \"page\" file)?\nroutix.isWatchedFile(file)\n\n// close file watchers\nroutix.close()\n```\n\n## Options\n\nFor now, see the [options.js](./src/options.js) file.\n\n## Customizing the output\n\n### `parse`\n\n```js\n// with actual files:\nparse = async ({ isFile: true, path, extension, absolute }, options) =\u003e void\n\n// with \"virtual\" dirs:\nparse = async ({ isFile: false, path }, options) =\u003e void\n```\n\nThe `parse` function is called once with each file (that is, files that are initially present, and then existing files that are updated, and new files that are created).\n\nIt is also called for each \"directory\", although in this case it may be called more than once for each. Note that those directories are not the one from the file system, but the ones that are derived from the returned file `path` when the tree is built -- when `write.tree` is false, then directories are not processed.\n\nThe parse function is free to mutate the passed object, however its return value is ignored.\n\n### `format`\n\n```js\nformat = ({ isFile, path, ... }) =\u003e ({ [prop]: any })\n```\n\nA `format` function can be passed to add extra props to items in the generated routes file. The function is passed the augmented (by `parse`) intermediary object and must return an object of prop / value pairs that will be added to the output.\n\nThe `format` function is called for each file and directory. It must use the `isFile` prop if it want to distinguish between them.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frixo%2Froutix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frixo%2Froutix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frixo%2Froutix/lists"}