{"id":21891425,"url":"https://github.com/sueddeutsche/drawio2ink","last_synced_at":"2025-09-22T03:18:53.120Z","repository":{"id":84338892,"uuid":"203165171","full_name":"sueddeutsche/drawio2ink","owner":"sueddeutsche","description":"Parse a narrative XML from draw.io through R to ink","archived":false,"fork":false,"pushed_at":"2024-02-02T17:55:26.000Z","size":1351,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-08-28T19:02:43.842Z","etag":null,"topics":["ddj","inky","tool","visual-storytelling","xml-parser"],"latest_commit_sha":null,"homepage":"","language":"R","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/sueddeutsche.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":"2019-08-19T12:08:21.000Z","updated_at":"2019-08-21T11:14:59.000Z","dependencies_parsed_at":"2024-11-28T14:00:14.320Z","dependency_job_id":null,"html_url":"https://github.com/sueddeutsche/drawio2ink","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sueddeutsche/drawio2ink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sueddeutsche%2Fdrawio2ink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sueddeutsche%2Fdrawio2ink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sueddeutsche%2Fdrawio2ink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sueddeutsche%2Fdrawio2ink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sueddeutsche","download_url":"https://codeload.github.com/sueddeutsche/drawio2ink/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sueddeutsche%2Fdrawio2ink/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276339190,"owners_count":25624996,"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","status":"online","status_checked_at":"2025-09-22T02:00:08.972Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["ddj","inky","tool","visual-storytelling","xml-parser"],"created_at":"2024-11-28T12:36:01.129Z","updated_at":"2025-09-22T03:18:53.089Z","avatar_url":"https://github.com/sueddeutsche.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# drawio2ink – Parse a narrative XML from draw.io through R to ink\n\n## Table of Contents\n\n [Getting Started](#getting-started)\n\n- [Prerequisites](#prerequisites)\n- [Installing](#installing)\n\n[Build a story](#build-a-story)\n\n- [Building a valid narrative flow chart](#building-a-valid-narrative-flow-chart)\n\n[Using the app](#using-the-app)\n\n- [Configure the output of the app](#configure-the-output-of-the-app)\n- [CSS classes](#css-classes)\n\n[Built With](#built-with)\n\n[Contributing](#contributing)\n\n[Authors](#authors)\n\n[License](#license)\n\n[Acknowledgments](#acknowledgments)\n\nThis ShinyApp works as a simple XML-Parser-Web-Interface. The app and parser are written in **R**. The parser converts an XML file exported from the [free online diagram tool draw.io](https://www.draw.io/) to the [narrative scripting language ink](https://www.inklestudios.com/ink/). The generated output is therefore a **.ink** file. This file can then be further processed and edited in the [ink-editor Inky](https://github.com/inkle/inky). We at the Süddeutsche Zeitung used this app to quickly and easily parse a story in draw.io-flow chart XMl-structure because we edited the story often. The resulting longread [can be found here](https://projekte.sueddeutsche.de/artikel/politik/urlaub-und-klimakrise-fliegen-sie-noch-e282839/) (behind our paywall, though).\n\n## Getting Started\n\n### Prerequisites\n\nYou need a recent **R** version installed on your system. You can [download and install it from here](https://cran.r-project.org/). This app was built with R version **3.5.3** (2019-03-11), but it should run with earlier versions as well.\n\nYou don't have to have the IDE [**RStudio**](https://www.rstudio.com/products/rstudio/download/#download) installed, but it helps tremendously in coding with R. For example, in this case it automatically provides a \"Run App\" button if you work on a ShinyApp.\n\nAll the **R packages** you need to have installed are installed and/or loaded in the app.R file and should be installed automatically when running the app. In case you run into problems, here's the list as well:\n\n- *shiny* – for the web app\n- *shinythemes* – for an eye-pleasing theme\n- *here* – manage the shiny-directories\n- *xml2* – parse XML files\n- *dplyr* – data manipulation\n- *purrr* – looping and manipulating the lists from the XML\n- *stringr* – manipulate strings/characters\n- *readr* – read/write functions\n- *glue* – glue strings and variables together\n\n### Installing\n\nYou can run this app with RStudio or via the command line:\n\n#### Using RStudio\n\n1. Clone/download the repo.\n2. Open `app.R` in RStudio\n3. Click \"Run App\"\n\nA new browser window/tab should open with the ShinyApp interface like this:\n\n![web interface to the app](img/web-interface.png)\n\n#### Using the command line\n\n1. Same as above\n2. Open the app directory (where app.R lies) in a terminal\n3. Open the R shell by typing `R`\n4. Run the app and open the browser window via these two commands:\n    ```R\n    \u003e library(shiny)\n    \u003e shinyAppFile(\"app.R\")\n    ```\n\n## Build a story\n\n### Building a valid narrative flow chart\n\nThere are some pre-defined assumptions you have to consider building a flow chart for your story in draw.io if you want this parser to work.\n\nThe script identifies the types of story elements (option text box, arrow etc.) by looking at their `style` attribute in the XML file. These are not perfectly consistent, i.e. styles get appended in the XML attribute if you change it in draw.io. These are the settings in the script:\n\n```r\ntype = case_when(\n        str_detect(style, \"orthogonalLoop\") ~ \"arrow\",\n        str_detect(style, \"endArrow\")       ~ \"arrow\",\n        str_detect(style, \"rounded=1\")      ~ \"textbox\",\n        str_detect(style, \"rounded=0\")      ~ \"textbox\",\n        str_detect(style, \"ellipse\")        ~ \"textbox\",\n        str_detect(style, \"shape=hexagon\")  ~ \"textbox\",\n        str_detect(style, \"text\")           ~ \"textbox\",\n        TRUE                                ~ \"other\"\n        )\n```\n\nIn the next step the script differentiates different types of **text boxes**:\n\n```r\ntextbox_type = case_when(\n        type == \"textbox\" \u0026 str_detect(style, \"rounded=1\")     ~ \"option\",\n        type == \"textbox\" \u0026 str_detect(style, \"rounded=0\")     ~ \"reaction\",\n        type == \"textbox\" \u0026 str_detect(style, \"ellipse\")       ~ \"expert\",\n        type == \"textbox\" \u0026 str_detect(style, \"shape=hexagon\") ~ \"reaction\",\n        type == \"textbox\" \u0026 str_detect(style, \"text\")          ~ \"other_text\",\n        TRUE                                                   ~ \"none\"\n        )\n```\n\nThis translates into the following rules for draw.io\n\n#### Styles/Shapes\n\nThe **first reaction** has the shape \"hexagon\":\n\n![screenshot of shape hexagon](img/shape-hexagon.png)\n\nAll **other reaction text** boxes have the style \"rounded=0\", sharp corners:\n\n![screenshot of style sharp corners](img/style-rounded-0.png)\n\n**Option text boxes** – which the reader clicks – have the style \"rounded=1\", rounded corners:\n\n![screenshot of style rounded corners](img/style-rounded-1.png)\n\n**Expert quote** text boxes have the style \"ellipse\":\n\n![screenshot of style ellipsis](img/style-ellipse.png)\n\nText that's not in a bubble has the style \"text\" and will be discarded.\n\n**Arrows** can have the styles \"orthogonalLoop\" or \"endArrow\".\n\n#### Connections\n\nIt is **very important** that all arrows are properly connected at the start and the end. Otherwise the script will return an error:\n\n```error\nError: There are disconnected arrows. Please visit your draw.io and fix them.\n```\n\nor, if you deployed it on a server it might be:\n\n```error\nError: An error has occurred. Check your logs or contact the app author for clarification.\n```\n\nHow do you spot a disconnected arrow?\n\nDisconnected:\n\n![screenshot of disconnected arrow](img/arrow-disconnected.png)\n\nConnected:\n\n![screenshot of connected arrow 1](img/arrow-connected.png)\n\nAlso connected:\n\n![screenshot of connected arrow 2](img/arrow-circle.png)\n\nAnother important point are the expert comments and conclusions. The script interprets a text box with only a target but no source as an expert text box. So they have to look like this:\n\n![screenshot of expert arrow example](img/expert-arrow-example.png)\n\nIf such an expert text box is connected to a final reaction text box – which have only a source but no target – it will be interpreted as an expert conclusion at the end of a narrative string.\n\nIf you're finished with your narrative flow chart you can **export it as an XML file**. It's important to export it **uncompressed**, otherwise it will contain gibberish.\n\n## Using the app\n\n### Configure the output of the app\n\nYou can configure some aspects of the output `.ink` file. The first two options have small previews with example text so you can spot errors like a missing colon without sifting through the ink file.\n\n#### Expert Comment\n\nThe expert comment is a short sentence before the quote of the expert. We show this quote below your answer after you've chosen one (in this case, the yellow text box):\n\n**The option in the app**\n![the expert comment quote option in the app](img/expert-comment-option.png)\n\n**Example from our article**\n![example of an expert comment quote](img/expert-comment.png)\n\n#### Expert Conclusion\n\nYou can also configure the expert conclusion text. This is very similar to the in-between comment quote, it just shows at the end of a narrative string (again, in yellow):\n\n**The option in the app**\n![the expert conclusion option in the app](img/expert-conclusion-option.png)\n\n**Example from our article**\n![example of an expert conclusion quote](img/expert-conclusion.png)\n\nin case you're wondering if you can configure the small portrait image of the expert: This comes through CSS. All the style comes through CSS as well. The output of this parser enables you to open it in Inky and export a JSON with the story content, which will be rendered on your website (via ink-js, for example).\n\n#### Restart Button\n\nCustomize the text on the restart button:\n\n**The option in the app**\n![the restart button option in the app](img/restart-button-option.png)\n\n**Example from our article**\n![example of restart button](img/restart-button.png)\n\nThe \"Andere Position\" – other position – button is coded in Javascript. It won't appear in your downloaded ink file.\n\n#### Optional: Introductory Annotation\n\nIn our case, we wanted to help the reader get into the discussion. So after the first reaction of the opponent, we explicitly asked the reader in a separate box to click on one of the three dialogue choices. You can turn this off or customize it. This output can be styled separately through the CSS class `annotation`.\n\n**The option in the app**\n![the introductory annotation option in the app](img/intro-annotation-option.png)\n\n**Example from our article**\n![example of the introductory annotation](img/intro-annotation.png)\n\nIf you're done configuring the output, you can upload the XMl file you've exported from draw.io (uncompressed!), check the big preview and download the ink file!\n\n### CSS classes\n\nThe parser is currently hard-coded to append specific tags to specific text elements. The pattern `# CLASS: classname` will be translated by ink.js to a CSS class for the corresponding answer/reaction/expert statement. More info on [tags in ink](https://github.com/inkle/ink/blob/master/Documentation/RunningYourInk.md#marking-up-your-ink-content-with-tags). The classes in this parser work currently as follows:\n\ntext element | ink output | translated CSS class\n-------------|------------|---------------------\nreaction of the counterpart | # CLASS: opposite | #opposite \nanswer option for the user | # CLASS: self | #self\nexpert comment and conclusion | # CLASS: expert | #expert\nintroductory annotation | # CLASS: annotation | #annotation\n\n## Built With\n\n- [R](https://cran.r-project.org/) - The programming language used\n- [Shiny](https://shiny.rstudio.com/) - Web-App framework for use with R\n\n## Contributing\n\nWe have no guidelines for contributing to this repository yet. Feel free to contact the team, if you encounter problems or have suggestions.\n\n## Authors\n\n- **Moritz Zajonz** - *Initial work* - [enigmoe](https://github.com/enigmoe)\n\nSee also the list of [contributors](https://github.com/sueddeutsche/drawio2ink/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n\n## Acknowledgments\n\n- Hat tip to [@munichrocker](https://github.com/munichrocker), who helped with the concept of the parser\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsueddeutsche%2Fdrawio2ink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsueddeutsche%2Fdrawio2ink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsueddeutsche%2Fdrawio2ink/lists"}