{"id":26149742,"url":"https://github.com/ippclub/yarnflow","last_synced_at":"2025-04-14T03:52:16.423Z","repository":{"id":279585513,"uuid":"939260622","full_name":"IppClub/YarnFlow","owner":"IppClub","description":"A lightweight compiler that converts Yarn Spinner scripts into Lua code, enabling seamless integration of interactive storytelling into Lua-based projects.","archived":false,"fork":false,"pushed_at":"2025-03-09T03:13:04.000Z","size":47,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-27T17:51:50.985Z","etag":null,"topics":["cpp","lua","yarn-spinner","yuescript"],"latest_commit_sha":null,"homepage":"","language":"C++","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/IppClub.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":"2025-02-26T09:01:00.000Z","updated_at":"2025-03-09T03:13:08.000Z","dependencies_parsed_at":"2025-02-26T11:21:03.391Z","dependency_job_id":"a99227af-9757-4b01-b384-372e7c61c78c","html_url":"https://github.com/IppClub/YarnFlow","commit_stats":null,"previous_names":["ippclub/yarnflow"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IppClub%2FYarnFlow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IppClub%2FYarnFlow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IppClub%2FYarnFlow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IppClub%2FYarnFlow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IppClub","download_url":"https://codeload.github.com/IppClub/YarnFlow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248819355,"owners_count":21166474,"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":["cpp","lua","yarn-spinner","yuescript"],"created_at":"2025-03-11T05:36:26.245Z","updated_at":"2025-04-14T03:52:16.397Z","avatar_url":"https://github.com/IppClub.png","language":"C++","readme":"# YarnFlow: Yarn Spinner to Lua Compiler\n\n[![IppClub](https://img.shields.io/badge/IppClub-Certified-11A7E2?logo=data%3Aimage%2Fsvg%2Bxml%3Bcharset%3Dutf-8%3Bbase64%2CPHN2ZyB2aWV3Qm94PSIwIDAgMjg4IDI3NCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjIiPjxwYXRoIGQ9Im0xNDYgMzEgNzIgNTVWMzFoLTcyWiIgc3R5bGU9ImZpbGw6I2Y2YTgwNjtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Im0xNjkgODYtMjMtNTUgNzIgNTVoLTQ5WiIgc3R5bGU9ImZpbGw6I2VmN2EwMDtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Ik0yNiAzMXY1NWg4MEw4MSAzMUgyNloiIHN0eWxlPSJmaWxsOiMwN2ExN2M7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJNMTA4IDkydjExMmwzMS00OC0zMS02NFoiIHN0eWxlPSJmaWxsOiNkZTAwNWQ7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJNMCAyNzR2LTUyaDk3bC0zMyA1MkgwWiIgc3R5bGU9ImZpbGw6I2Y2YTgwNjtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Im03NyAyNzQgNjctMTA3djEwN0g3N1oiIHN0eWxlPSJmaWxsOiNkZjI0MzM7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJNMTUyIDI3NGgyOWwtMjktNTN2NTNaIiBzdHlsZT0iZmlsbDojMzM0ODVkO2ZpbGwtcnVsZTpub256ZXJvIi8%2BPHBhdGggZD0iTTE5MSAyNzRoNzl2LTUySDE2N2wyNCA1MloiIHN0eWxlPSJmaWxsOiM0ZTI3NWE7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJNMjg4IDEwMGgtMTdWODVoLTEzdjE1aC0xN3YxM2gxN3YxNmgxM3YtMTZoMTd2LTEzWiIgc3R5bGU9ImZpbGw6I2M1MTgxZjtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Im0yNiA4NiA1Ni01NUgyNnY1NVoiIHN0eWxlPSJmaWxsOiMzMzQ4NWQ7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJNOTMgMzFoNDJsLTMwIDI5LTEyLTI5WiIgc3R5bGU9ImZpbGw6IzExYTdlMjtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Ik0xNTggMTc2Vjg2bC0zNCAxNCAzNCA3NloiIHN0eWxlPSJmaWxsOiMwMDU5OGU7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJtMTA2IDU5IDQxLTEtMTItMjgtMjkgMjlaIiBzdHlsZT0iZmlsbDojMDU3Y2I3O2ZpbGwtcnVsZTpub256ZXJvIi8%2BPHBhdGggZD0ibTEyNCAxMDAgMjItNDEgMTIgMjctMzQgMTRaIiBzdHlsZT0iZmlsbDojNGUyNzVhO2ZpbGwtcnVsZTpub256ZXJvIi8%2BPHBhdGggZD0ibTEwNiA2MCA0MS0xLTIzIDQxLTE4LTQwWiIgc3R5bGU9ImZpbGw6IzdiMTI4NTtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Im0xMDggMjA0IDMxLTQ4aC0zMXY0OFoiIHN0eWxlPSJmaWxsOiNiYTAwNzc7ZmlsbC1ydWxlOm5vbnplcm8iLz48cGF0aCBkPSJtNjUgMjc0IDMzLTUySDBsNjUgNTJaIiBzdHlsZT0iZmlsbDojZWY3YTAwO2ZpbGwtcnVsZTpub256ZXJvIi8%2BPHBhdGggZD0iTTc3IDI3NGg2N2wtNDAtNDUtMjcgNDVaIiBzdHlsZT0iZmlsbDojYTgxZTI0O2ZpbGwtcnVsZTpub256ZXJvIi8%2BPHBhdGggZD0iTTE2NyAyMjJoNThsLTM0IDUyLTI0LTUyWiIgc3R5bGU9ImZpbGw6IzExYTdlMjtmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Im0yNzAgMjc0LTQ0LTUyLTM1IDUyaDc5WiIgc3R5bGU9ImZpbGw6IzA1N2NiNztmaWxsLXJ1bGU6bm9uemVybyIvPjxwYXRoIGQ9Ik0yNzUgNTVoLTU3VjBoMjV2MzFoMzJ2MjRaIiBzdHlsZT0iZmlsbDojZGUwMDVkO2ZpbGwtcnVsZTpub256ZXJvIi8%2BPHBhdGggZD0iTTE4NSAzMWg1N3Y1NWgtMjVWNTVoLTMyVjMxWiIgc3R5bGU9ImZpbGw6I2M1MTgxZjtmaWxsLXJ1bGU6bm9uemVybyIvPjwvc3ZnPg%3D%3D\u0026labelColor=fff)](https://ippclub.org)\n\n## Description\n\nYarnFlow is a compiler that translates Yarn Spinner scripts into Lua code and uses Lua as the script runtime, allowing you to seamlessly integrate interactive story elements from Yarn Spinner into Lua-based projects. Whether you're developing a game, an interactive app, or any Lua-powered project, YarnFlow simplifies the process of leveraging Yarn Spinner’s intuitive story-based scripting language with the power and flexibility of Lua.\n\n## About YarnFlow\n\nYarnFlow is a sub-project developed and maintained as part of the Dora SSR open-source game engine project. It provides a seamless way to integrate Yarn Spinner's narrative capabilities into Lua-based games and applications built with Dora SSR.\n\nFor more information about the Dora SSR game engine project, please visit [Dora SSR on GitHub](https://github.com/ippclub/dora-ssr).\n\nAnd there is a visual novel framework built on top of Dora SSR showing the power of YarnFlow, you can visit [Dora Story](https://github.com/ippclub/dora-story) for more information.\n\n## Key Features\n\n- **Simple Integration:** Easily integrate interactive narratives into your Lua projects.\n- **Easy Yarn Spinner to Lua Conversion:** Take your Yarn Spinner scripts and compiles them into clean, executable Lua code.\n- **Compact \u0026 Extensible:** Designed to be compact and easy to extend with Lua functions.\n- **Open-Source:** YarnFlow is an open-source project, welcoming contributions and improvements from the community.\n\n## Installation\n\nTo install YarnFlow via LuaRocks:\n\n```\nluarocks install yarnflow\n```\n\nOr you can build `yarnflow.so` file with\n\n```bash\nmake LUAI=/your-path/lua/include LUAL=/your-path/lua/lib\n```\n\nThen get the binary file from path `lib/yarnflow.so`.\n\n## Usage\n\n1. Write your story using Yarn Spinner syntax.\n2. Use YarnFlow to load your Yarn script in Lua.\n3. Execute the loaded script with the yarnflow runner.\n\nExample:\n\n```lua\nlocal yarnCode = [[\ntitle: Start\n---\n\u003c\u003cset $heart to 0\u003e\u003e\nNarrator: Hi, I'm the narrator for this beginner's guide!\nNarrator: I'm talking to you with Yarn Spinner!\nNarrator: What do you think of all this, then?\n-\u003e It's alright, I guess.\n  \u003c\u003cset $heart to $heart - 1\u003e\u003e\n  \u003c\u003cjump Alright\u003e\u003e\n-\u003e It's great. I love it.\n  \u003c\u003cset $heart to $heart + 1\u003e\u003e\n  \u003c\u003cjump Love\u003e\u003e\n===\n\ntitle: Alright\n---\n\u003c\u003cdot 4\u003e\u003e\nNarrator: Well, that's not very nice.\nNarrator: I'm trying my best here.\n-\u003e Are you really? I don't think so.\n  \u003c\u003cset $heart to $heart - 1\u003e\u003e\n  \u003c\u003cjump Alright\u003e\u003e\n-\u003e Oh, OK. I'm sorry.\n  \u003c\u003cset $heart to $heart + 1\u003e\u003e\n  \u003c\u003cjump Love\u003e\u003e\n===\n\ntitle: Love\n---\n\u003c\u003cdot 5\u003e\u003e\nNarrator: Oh, you're too kind.\nNarrator: I'm just doing my job.\n-\u003e You're doing a great job.\n  \u003c\u003cset $heart to $heart + 2\u003e\u003e\n  Narrator: Oh, stop it, you.\n  Narrator: You're making me blush.\n-\u003e You're a natural.\n  \u003c\u003cset $heart to $heart + 3\u003e\u003e\n  Narrator: Oh, you.\n  Narrator: I'm but a humble narrator.\n===\n]]\n\nlocal yarnflow = require(\"yarnflow\")\nlocal variables = {\n  heart = 0,\n}\nlocal commands = {\n  dot = function(count)\n    print((\".\"):rep(count))\n  end,\n}\nlocal runner = yarnflow(yarnCode, \"Start\", variables, commands)\n\nlocal function printHeart()\n  print(\"Heart: \" .. variables.heart)\nend\n\n-- The advance function takes an optional integer representing the player's choice index.\n-- For the first call or when no choice is needed, we pass nil.\nlocal function advance(option)\n  -- First, we call runner:advance(option) to get the next part of the Yarn script.\n  -- This returns two values: an action type and a result.\n  local action, result = runner:advance(option)\n  -- Handle the result based on the action type.\n  if action == \"Text\" then\n    -- If the action is \"Text\", the result will be a TextResult object,\n    -- containing the text and any associated markers (e.g., character names).\n    -- Check the markers, extract the character's name (if present), and print the text.\n    local characterName = \"\"\n    local marks = result.marks\n    if marks then\n      for i = 1, #marks do\n        local mark = marks[i]\n        if mark.name == \"char\" then\n          characterName = mark.attrs.name .. \": \"\n        end\n      end\n    end\n    print(characterName .. result.text)\n  elseif action == \"Option\" then\n    -- If the action is \"Option\", the result will be an OptionResult object,\n    -- containing one or more options. Iterate over the options and print them,\n    -- allowing the player to select them later.\n    for i, op in ipairs(result) do\n      if op then\n        print(\"[\" .. tostring(i) .. \"]: \" .. op.text)\n      end\n    end\n  else\n    -- For other actions (like errors), print the result directly.\n    print(result)\n    -- If the action is nil, it means the story is finished.\n    if action == nil then\n      printHeart()\n      os.exit(0)\n    end\n  end\nend\n\n-- Start the story\nadvance()\n\nrepeat\n  local input = io.read()\n  if input then\n    advance(tonumber(input))\n  end\nuntil input == \"exit\"\n```\n\n## License\n\nYarnFlow is released under the [MIT License](LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fippclub%2Fyarnflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fippclub%2Fyarnflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fippclub%2Fyarnflow/lists"}