{"id":15384663,"url":"https://github.com/amphiluke/lindsvg","last_synced_at":"2025-06-11T22:36:20.582Z","repository":{"id":48695129,"uuid":"231341297","full_name":"Amphiluke/lindsvg","owner":"Amphiluke","description":"Lindenmayer System [Scalable] Vector Graphics","archived":false,"fork":false,"pushed_at":"2024-09-27T07:31:26.000Z","size":1955,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-05T11:29:52.774Z","etag":null,"topics":["l-system","svg"],"latest_commit_sha":null,"homepage":"https://amphiluke.github.io/lindsvg/","language":"JavaScript","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/Amphiluke.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":"2020-01-02T08:42:47.000Z","updated_at":"2024-09-27T07:31:30.000Z","dependencies_parsed_at":"2024-03-04T16:15:25.660Z","dependency_job_id":"01c758d6-c9ea-4433-9afd-ba0ad2ac0fb8","html_url":"https://github.com/Amphiluke/lindsvg","commit_stats":{"total_commits":32,"total_committers":2,"mean_commits":16.0,"dds":0.03125,"last_synced_commit":"a4c8c2fddd3005f9f35982f42031c48f3d6177c4"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Amphiluke%2Flindsvg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Amphiluke%2Flindsvg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Amphiluke%2Flindsvg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Amphiluke%2Flindsvg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Amphiluke","download_url":"https://codeload.github.com/Amphiluke/lindsvg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219888244,"owners_count":16564130,"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":["l-system","svg"],"created_at":"2024-10-01T14:43:01.179Z","updated_at":"2024-10-16T21:01:41.668Z","avatar_url":"https://github.com/Amphiluke.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lindsvg\n\n**lindsvg** (pronounced /ˈlɪnds ˈviː ˈdʒiː/), Lindenmayer System \\[Scalable\\] Vector Graphics\n\nSimple dependency-free module used to generate SVG images of deterministic L-systems.\n\n![Generated SVG tree](https://amphiluke.github.io/l-systems/img/autumn-tree.svg)\n\n## Installation\n\n### In an npm project\n\nInstalling the module is as simple as:\n\n```\nnpm install lindsvg\n```\n\nNow you may get it in your scripts as usual: `require(\"lindsvg\")`, or `import * as lindsvg from \"lindsvg\"`.\n\n### In a browser\n\nlindsvg is available in UMD format which allows you using it either with AMD/CJS compatible module loaders or in global namespace (`window.lindsvg`). You may get the module sources from such CDNs as jsDelivr or unpkg:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/lindsvg/dist/lindsvg.min.js\"\u003e\u003c/script\u003e\n```\n\nIf you rather prefer using ES modules in a browser, just choose the “esm” bundle:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import * as lindsvg from \"https://cdn.jsdelivr.net/npm/lindsvg/dist/lindsvg.esm.min.js\";\n  // ...\n\u003c/script\u003e\n```\n\n## Supported commands\n\nThe following turtle commands are currently supported by lindsvg:\n\n| Command             | Description                                           |\n| ------------------- | ----------------------------------------------------- |\n| `F`                 | Move forward one step with drawing a line             |\n| `B`                 | Move forward one step without drawing a line          |\n| `+`                 | Turn left by turning angle (theta)                    |\n| `-`                 | Turn right by turning angle (theta)                   |\n| `\\|`                | Reverse direction (turn by 180 degrees)               |\n| `!`                 | Reverse the meaning of `+` and `-`                    |\n| `[`                 | Push current state of the turtle onto the stack       |\n| `]`                 | Pop a state from the stack and apply it to the turtle |\n| `A`,`C`–`E`,`G`–`Z` | Auxiliary user-defined rules                          |\n\n## API \u0026amp; examples\n\nThe module exports two pairs of methods.\n\n1. The methods returning ready-to-render L-system’s SVG code as a string:\n    * `getSVGCode(lsParams[, svgParams])`;\n    * `getMultiPathSVGCode(lsParams[, svgParams])`;\n2. The methods returning raw data that you may use to construct the SVG code yourself:\n    * `getSVGData(lsParams)`;\n    * `getMultiPathSVGData(lsParams)`.\n\nThe “multi-path” methods (`getMultiPathSVGCode` and `getMultiPathSVGData`) differ from the “normal” methods (`getSVGCode` and `getSVGData`) in that they provide the ability for advanced stylisation of _branched_ L-systems. SVG images created using these “multi-path” methods contain several `\u003cpath\u003e` elements, each one for a specific branching level, so they can be stylised differently (color, line width, etc.)\n\nAll methods expect L-system parameters object as their first argument. These parameters are explained through the comments in the snippet below. Additionally, the methods `getSVGCode` and `getMultiPathSVGCode` may be passed an _optional_ parameter to alter the output SVG settings (refer the comments in the snippet below).\n\n### Using “single-path” methods\n\n```javascript\nimport {getSVGCode, getSVGData} from \"lindsvg\";\n\n// L-system parameters\nlet lsParams = {\n  axiom: \"A---A\",    // The initial codeword (axiom)\n  rules: {           // L-system production rules\n    F: \"F\",          // Move forward a step with drawing a line\n    B: \"B\",          // Move forward a step without drawing a line\n    A: \"B-F+Z+F-BA\", // Auxiliary rules...\n    Z: \"F-FF-F--[--Z]F-FF-F--F-FF-F--\",\n  },\n  alpha: 0,           // Initial angle in radians\n  theta: Math.PI / 3, // Angle increment in radians\n  step: 15,           // The length of a “turtle” step\n  iterations: 7,      // Total number of iterations\n};\n\n// Output SVG parameters (all of them are optional)\nlet svgParams = {\n  width: 600,       // Desired SVG element width\n  height: 600,      // Desired SVG element height\n  padding: 5,       // Additional space to extend the viewBox\n  pathAttributes: { // Name to value map for the \u003cpath\u003e element attributes\n    stroke: \"green\",\n    \"stroke-width\": \"2\",\n  },\n};\n\n// Get ready-to-render L-system’s SVG code as a string...\nlet svgCode = getSVGCode(lsParams, svgParams);\n\n// ...or get raw data required for manual SVG assemblage\nlet {pathData, minX, minY, width, height} = getSVGData(lsParams);\n```\n\nAn object returned by `getSVGData` contains [path data](https://www.w3.org/TR/SVG11/paths.html#PathData) needed to draw the L-system, as well as the drawing boundaries that are essential for the `viewBox` attribute.\n\n### Using “multi-path” methods\n\nUsing “multi-path” methods (`getMultiPathSVGCode` and `getMultiPathSVGData`) allows you to specify different path attributes for every `\u003cpath\u003e` element separately, which may make branched L-systems (like plants) look “more naturally”.\n\nFor example, to generate the tree [demonstrated above](#lindsvg) (all but foliage) the following options were used:\n\n```javascript\nimport {getMultiPathSVGCode, getMultiPathSVGData} from \"lindsvg\";\n\n// L-system parameters\nlet lsParams = {\n  axiom: \"F-FFF-F+F+X\",\n  rules: {\n    F: \"F\",\n    X: \"FFF-[-F+F[Y]-[X]]+[+F+F[X]-[X]]\",\n    Y: \"FF-[-F+F]+[+F+FY]\",\n  },\n  alpha: 90 * Math.PI / 180,\n  theta: 14 * Math.PI / 180,\n  iterations: 6,\n  step: 12,\n};\n\n// Output SVG parameters\nlet svgParams = {\n  width: 565,\n  height: 445,\n  padding: 10,\n  pathAttributes: {\n    stroke: \"#514d3a\",\n    \"stroke-width\": [\"16\", \"11\", \"9\", \"7\", \"6\", \"5\", \"3\", \"2\", \"1\"],\n    \"stroke-linecap\": [\"square\", \"round\" /* the rest items are equal to the last one */],\n  },\n};\n\n// Get ready-to-render L-system’s SVG code as a string...\nlet svgCode = getMultiPathSVGCode(lsParams, svgParams);\n\n// ...or get raw data required for manual SVG assemblage\nlet {multiPathData, minX, minY, width, height} = getMultiPathSVGData(lsParams);\n```\n\nIf an attribute array contains fewer elements than the maximum branching depth (e.g. see `stroke-linecap` in the example above), the missing items are implicitly made equal to the last one. So you don’t need to repeat the same value in the end of the list.\n\nYou may also use the special value `\"n/a\"` which prevents an attribute from being added on the corresponding `\u003cpath\u003e` element (e.g. when you need to add an attribute only to one or to a few `\u003cpath\u003e`s: `{pathAttributes: {transform: [\"skewY(-35)\", \"n/a\"]}}`).\n\nThe property `multiPathData` in the object returned by `getMultiPathSVGData` is a _list_ of path data for every `\u003cpath\u003e` element. The list is sorted in the order of increasing branch level (the deeper the branch the higher the index in the array).\n\n### Error handling\n\nIn case of invalid input L-system parameters, the methods throw a custom exception. You may use it to get a detailed explanation of which parameter(s) failed to pass validation, and format the message as you wish.\n\n```javascript\nimport {getSVGCode} from \"lindsvg\";\nimport {dump} from \"js-yaml\";\n\ntry {\n  console.log(getSVGCode(lsParams, svgParams));\n} catch (error) {\n  // Log the original message\n  console.error(error);\n  if (error.name === \"LSError\") {\n    // Get a JSON representation of the error list and format it as YAML\n    let errorJSON = error.toJSON();\n    console.log(dump(errorJSON, {indent: 4}));\n  }\n}\n```\n\n## Demos\n\nPlease, visit the project’s [demo web app](https://amphiluke.github.io/lindsvg/) (installable as a PWA and works offline too). You will find a few built-in L-system collections there, and will also be able to experiment with lindsvg while building your own L-systems.\n\nAlso, check out [this collection](https://codepen.io/collection/DVzqWb) on CodePen to get a few advanced examples of using lindsvg.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famphiluke%2Flindsvg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famphiluke%2Flindsvg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famphiluke%2Flindsvg/lists"}