{"id":13476167,"url":"https://github.com/yaronn/wopr","last_synced_at":"2025-05-14T19:07:46.513Z","repository":{"id":41337423,"uuid":"39265689","full_name":"yaronn/wopr","owner":"yaronn","description":"A simple markup language for creating rich terminal reports, presentations and infographics","archived":false,"fork":false,"pushed_at":"2024-04-01T20:35:13.000Z","size":324,"stargazers_count":3066,"open_issues_count":7,"forks_count":78,"subscribers_count":55,"default_branch":"master","last_synced_at":"2025-05-13T16:56:56.561Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/yaronn.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}},"created_at":"2015-07-17T17:09:51.000Z","updated_at":"2025-05-08T21:55:46.000Z","dependencies_parsed_at":"2024-04-12T21:59:46.983Z","dependency_job_id":null,"html_url":"https://github.com/yaronn/wopr","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaronn%2Fwopr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaronn%2Fwopr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaronn%2Fwopr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaronn%2Fwopr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yaronn","download_url":"https://codeload.github.com/yaronn/wopr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"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-07-31T16:01:27.257Z","updated_at":"2025-05-14T19:07:45.507Z","avatar_url":"https://github.com/yaronn.png","language":"JavaScript","funding_links":[],"categories":["Productivity","JavaScript","Miscellaneous","\u003ca name=\"data-management\"\u003e\u003c/a\u003eData management","\\*nix/\\*nux","Libraries"],"sub_categories":["Presentations","Fancy stuff","Presentation"],"readme":"# WOPR\r\n\r\nWOPR is a simple markup language for creating [rich terminal reports](https://github.com/yaronn/blessed-contrib), presentations and infographics.\r\n\r\nPut [a report](https://raw.githubusercontent.com/yaronn/wopr/master/examples/sample.xml) on the web (e.g. gist) and view it via curl:\r\n\r\n`````bash\r\n$\u003e curl -N tty.zone/\\[0-2\\]\\?auto\\\u0026cols=$((COLUMNS))\r\n`````\r\n(If you experience firewall issues replace tty.zone with ec2-23-21-64-152.compute-1.amazonaws.com or use a [local viewer](https://github.com/yaronn/wopr#viewing-reports))\r\n\r\nCreated by Yaron Naveh ([@YaronNaveh](https://twitter.com/YaronNaveh))\r\n\r\n![](./examples/images/charts.png \"term\")\r\n![](./examples/images/map.png \"term\")\r\n\r\n##Writing your first terminal report##\r\n\r\nHere is a simple report with a bar chart:\r\n\r\n`````xml\r\n\u003cdocument\u003e\r\n  \u003cpage\u003e\r\n    \u003citem col=\"0\" row=\"0\" colSpan=\"5\" rowSpan=\"4\"\u003e\r\n      \u003cbar maxHeight=\"5\" data-titles=\"A,B,C\" data-data=\"2,5,3\" /\u003e\r\n    \u003c/item\u003e\r\n  \u003c/page\u003e\r\n\u003c/document\u003e\r\n`````\r\n\r\nYou have 3 options to view this report:\r\n\r\n**Option 1: POST it to the wopr online viewer**\r\n\r\n`````bash\r\n$\u003e curl --data '\u003cdocument\u003e\u003cpage\u003e\u003citem col=\"0\" row=\"0\" colSpan=\"5\" rowSpan=\"4\"\u003e\u003cbar maxHeight=\"5\" data-titles=\"A,B,C\" data-data=\"2,5,3\" /\u003e\u003c/item\u003e\u003c/page\u003e\u003c/document\u003e' tty.zone\\?cols=$((COLUMNS))\r\n`````\r\n\r\nIf you experience firewall issues replace tty.zone with ec2-23-21-64-152.compute-1.amazonaws.com.\r\n\r\n**Note:** The online viewer is a reference implementation. Do not send it secret data but rather create [your own](https://github.com/yaronn/wopr/tree/master/server).\r\n\r\n**Option 2: POST it from external url**\r\n\r\nSave the report content in some url (e.g. gist) and then:\r\n\r\n`````bash\r\n$\u003e a=$(curl -s https://gist.githubusercontent.com/yaronn/e6eec6d0e7adac63c83f/raw/50aca544d26a32aa189e790635c8679067017948/gistfile1.xml); curl --data \"$a\" tty.zone\\?cols=$((COLUMNS))\r\n`````\r\n\r\n(note you need the gist raw url)\r\n\r\nIf you experience firewall issues replace tty.zone with ec2-23-21-64-152.compute-1.amazonaws.com.\r\n\r\n**Note:** The online viewer is a reference implementation. Do not send it secret data but rather create [your own](https://github.com/yaronn/wopr/tree/master/server).\r\n\r\n\r\n**Option 3: Via the local viewer**\r\n\r\nSave the report xml to report.xml and then:\r\n\r\n`````bash\r\n$\u003e npm install -g wopr\r\n$\u003e wopr report.xml\r\n`````\r\n\r\nNote the local viewer does not send anything online and does not require network.\r\n\r\n![](./examples/images/charts.png \"term\")\r\n\r\n##Markup Basics#\r\n\r\n**Pages**\r\n\r\nA document is a set of pages:\r\n\r\n`````xml\r\n\u003cdocument\u003e\r\n  \u003cpage\u003e\r\n    ...\r\n  \u003c/page\u003e\r\n  \u003cpage\u003e\r\n    ...\r\n  \u003c/page\u003e\r\n\u003c/document\u003e\r\n`````\r\n\r\n**Layout**\r\n\r\nA page is a 12x12 grid in which you can position different widgets:\r\n\r\n`````xml\r\n\u003cdocument\u003e\r\n  \u003cpage\u003e\r\n    \u003citem col=\"0\" row=\"0\" colSpan=\"3\" rowSpan=\"3\"\u003e\r\n      \u003cbar maxHeight=\"5\" data-titles=\"A,B,C\" data-data=\"2,5,3\" /\u003e\r\n    \u003c/item\u003e\r\n    \u003citem col=\"5\" row=\"9\" colSpan=\"1\" rowSpan=\"1\"\u003e\r\n      \u003cbox content=\"some text\" /\u003e\r\n    \u003c/item\u003e\r\n  \u003c/page\u003e\r\n\u003c/document\u003e\r\n`````\r\n\r\nHere, the bar widget is in the first column and row (0-based indexing) and spans three columns and rows.\r\nThe box element is in the same page but in a different position.\r\n\r\n\r\n**Widgets**\r\n\r\nThe available widgets are the ones that exist in the [blessed](https://github.com/chjj/blessed) and [blessed-contrib](https://github.com/yaronn/blessed-contrib) projects.\r\nYou can infer the xml representation of a javascript widget using a simple convention. Assume that you would instantiate some blessed widget with this javascript:\r\n\r\n`````javascript\r\nblessed.widget({ string: \"5\"\r\n               , int: 1\r\n               , intArray: [1,2,3]\r\n               , stringArray: [\"a\", \"b\", \"c\"]\r\n               , multiArray: [ [1,2,3], [4,5,6] ]\r\n               , complexArray: [ {a: 1, b: [1,2] }, {a: 3, b: [3,4]} ]\r\n               , object: { innerProp: 1, multiArray: [ [1,2], [3,4] ] }\r\n})\r\n`````\r\n\r\nThen here is how you would represent it in xml:\r\n    \r\n`````xml\r\n\u003cwidget string=\"5\" int=\"1\" intArray=\"1,2,3\" stringArray=\"a,b,c\" object-innerProp=\"1\"\u003e\r\n  \u003cmultiArray\u003e\r\n    1,2,3\r\n    4,5,6\r\n  \u003c/multiArray\u003e\r\n  \u003cobject-multiArray\u003e\r\n    1,2\r\n    3,4\r\n  \u003c/object-multiArray\u003e\r\n  \u003ccomplexArray\u003e\r\n    \u003cm a=\"1\" b=\"1,2\" /\u003e\r\n    \u003cm a=\"3\" b=\"3,4\" /\u003e\r\n  \u003c/complexArray\u003e\r\n\u003c/widget\u003e\r\n`````\r\n\r\nYou can also look at the [demo xml](https://raw.githubusercontent.com/yaronn/wopr/master/examples/sample.xml) to get more samples.\r\n\r\n![](./examples/images/map.png \"term\")\r\n\r\n##Viewing Reports##\r\n\r\n\r\nDepending on how you use a report, you have a few ways to view it. On Windows you will probably only be able to use the third option and need to [install the fonts](http://webservices20.blogspot.com/2015/04/running-terminal-dashboards-on-windows.html) for best view.\r\n\r\n**Option 1: POST it to the wopr online viewer**\r\n\r\n`````bash\r\n$\u003e curl --data '\u003cdocument\u003e\u003cpage\u003e\u003citem col=\"0\" row=\"0\" colSpan=\"5\" rowSpan=\"4\"\u003e\u003cbar maxHeight=\"5\" data-titles=\"A,B,C\" data-data=\"2,5,3\" /\u003e\u003c/item\u003e\u003c/page\u003e\u003c/document\u003e' tty.zone\\?cols=$((COLUMNS))\r\n`````\r\n\r\nIf you experience firewall issues replace tty.zone with ec2-23-21-64-152.compute-1.amazonaws.com.\r\n\r\n**Option 2: POST it from external url**\r\n\r\nSave the report content in some url (e.g. gist) and then:\r\n\r\n`````bash\r\n$\u003e a=$(curl -s https://gist.githubusercontent.com/yaronn/e6eec6d0e7adac63c83f/raw/50aca544d26a32aa189e790635c8679067017948/gistfile1.xml); curl --data \"$a\" tty.zone\\?cols=$((COLUMNS))\r\n`````\r\n\r\n(note you need the gist raw url)\r\n\r\nIf you experience firewall issues replace tty.zone with ec2-23-21-64-152.compute-1.amazonaws.com.\r\n\r\nTip: If you use a url shortener (e.g. bit.ly) add the -L flag to curl to follow redirects.\r\n\r\n**Option 3: via the local viewer**\r\n\r\nSave the report xml to report.xml and then:\r\n\r\n`````bash\r\n$\u003e npm install -g wopr\r\n$\u003e wopr report.xml\r\n`````\r\n\r\nNote the local viewer does not send anything online and does not require network.\r\n\r\n**Tip:** Maximize the terminal before viewing the report for best viewing experience  \r\n**Tip:** If you \u003ckbd\u003eCTRL+C\u003c/kbd\u003e in the middle or rendering your cursoe might disappear. Restore it by running again and letting the render complete or with `$\u003e echo '\\033[?25h'`\r\n\r\n**View customization**\r\nWhen using the online reports, you might need to adjust the slides size based on your font / resolution or use non-xterm terminal. tty.zone supports the following query params:\r\n\r\n`````bash\r\ncurl -N tty.zone\\?\\\u0026cols=200\\\u0026rows=50\\\u0026terminal=xterm\r\n`````\r\n\r\nYou can infer them automatically from your environment:\r\n\r\n`````bash\r\ncurl -N tty.zone\\?\\\u0026cols=$((COLUMNS))\\\u0026rows=$((LINES-5))\\\u0026terminal=${TERM}\r\n`````\r\n\r\nIt is best to escape all special characters (e.g. ? \u0026) as seen in the above samples, since some shells will require this (zsh).\r\n\r\n\r\n**Pages**\r\n\r\nWhen viewing a report with the local viewer you can advance slides with the Return or Space keys.\r\nWhen using the online viewer you have 2 options:\r\n\r\n**Option 1:** Manually advance slides with Return or Space:\r\n\r\n`````bash\r\np=0; while true; do curl tty.zone/$((p++))\\?cols=$((COLUMNS)); read; done\r\n`````\r\n\r\n**Option 2:** Slides advance automatically every 5 seconds:\r\n\r\n`````bash\r\ncurl -N tty.zone/\\[0-2\\]\\?auto\\\u0026cols=$((COLUMNS))\r\n`````\r\n\r\nWhere 0 is the index of the first slide and 2 of the last slide. Keep the brackets in the url (they are not to express optional argument) and escape them as in the above sample.\r\n\r\nTip: disable curl buffering with the -N flag\r\n\r\nYou can also view a specific slide (#4 in this case):\r\n\r\n`````bash\r\ncurl --data '\u003cdocument\u003e...\u003c/document\u003e' tty.zone/4\\?cols=$((COLUMNS))\r\n`````\r\n\r\n##License##\r\nMIT\r\n\r\n\r\n## More Information\r\nCreated by Yaron Naveh ([twitter](http://twitter.com/YaronNaveh), [blog](http://webservices20.blogspot.com/))\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaronn%2Fwopr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyaronn%2Fwopr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaronn%2Fwopr/lists"}