{"id":13594480,"url":"https://github.com/tatatap-com/sowhat","last_synced_at":"2025-04-09T07:32:38.825Z","repository":{"id":43728988,"uuid":"429588549","full_name":"tatatap-com/sowhat","owner":"tatatap-com","description":null,"archived":false,"fork":false,"pushed_at":"2022-08-09T19:13:34.000Z","size":103,"stargazers_count":53,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-02T16:52:22.811Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tatatap-com.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}},"created_at":"2021-11-18T21:44:54.000Z","updated_at":"2024-03-02T00:02:38.000Z","dependencies_parsed_at":"2022-07-19T03:32:12.408Z","dependency_job_id":null,"html_url":"https://github.com/tatatap-com/sowhat","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tatatap-com%2Fsowhat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tatatap-com%2Fsowhat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tatatap-com%2Fsowhat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tatatap-com%2Fsowhat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tatatap-com","download_url":"https://codeload.github.com/tatatap-com/sowhat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223375349,"owners_count":17135355,"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-08-01T16:01:34.272Z","updated_at":"2024-11-06T16:31:27.962Z","avatar_url":"https://github.com/tatatap-com.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# sowhat\n\nSowhat is a markup language for organizing a collection of short note records. Records can include: organization and categorization elements, accounting elements, URLs, productivity elements, and formulas. \n\nThe following record contains a few of the elements listed above:\n\n```\n2021-01-30 00:55 /lunch \u003c-- Folder\n\nTodo Purchase \u003c-- Todo\n\n* bacon\n* lettuce\n* tomatoes\n* bread\n* mayo\n\n-\"Groceries Budget\":20.50 \u003c-- Bean\n\n$$(\"Cash After Shopping\")\n  (- (BEAN \"All My Money\")\n     (BEAN \"Groceries Budget\")) \u003c-- Formula\n```\n\n[The parsed result of the above record](#intro-example)\n\n## Table of Contents\n\n* [Origin](#origin)\n* [Integration](#integration)\n* [Usage](#usage)\n* [Elements](#elements)\n  * **[Pins](#pins)**\n  * **[Dates](#dates)**\n  * **[Folders](#folders)**\n  * **[Todo/Done](#tododone)**\n  * **[URLs](#urls)**\n  * **[Links](#links)**\n  * **[Tags](#tags)**\n  * **[Mentions](#mentions)**\n  * **[Events](#events)**\n  * **[Beans](#beans)**\n  * **[Cells](#cells)**\n  * **[Formulas](#formulas)**\n* [Examples](#examples)\n\n## Origin\n\nSowhat was originally designed for the note-taking service [/tap](https://www.tatatap.com?ref=SOWHAT). One of the primary input methods for /tap is SMS, hence the extremely terse syntax of sowhat.\n\n/tap is also a useful reference implementation for the sowhat language. The [/tap How-to guide](https://www.tatatap.com/how-to) has a lot of in-depth information about how the sowhat elements are interpreted.\n\n\n## Integration\n\nSowhat is meant to be used in conjunction with a storage engine to keep track of a collection of records. The collection will accumulate records in folders, values (referred to as Beans) that can be referenced by Formulas, Events that span multiple records, and any other application that can make use of the elements listed below.\n\nOf course, not all sowhat elements are necessary to produce a useful system. In-fact it started with only a single element, Folders.\n\n\n## Usage\n\n### Installation\n\n```\nnpm install @tatatap-com/sowhat\n```\n\n\n### Parsing\n\n```\nsowhat.parse(`\n2021-01-30 10:00 /a/b \n\nTodo Find out http://whattimeisit.com #time !task \n\n-budget:150.00 \n\n$$(\"Estimated Cost\")\n  (* \n    (BEAN budget) \n    1.1)\n`);\n```\n\n### Tokenizing\n\n```\nsowhat.tokenize('!hello #world');\n```\n\n### Compiling\n\nAny changes to grammar.ne will require recompiling the parser.\n\n```\nnpm run compile\n```\n\n## Elements\n\nAny text will parse as a valid sowhat record. The elements listed below add meaning and values to the record:\n\n* **[Pins](#pins)**: Pins provide an additional sequence to sort Records\n* **[Dates](#dates)**: The date the record pertains to (see below for more information about why this is not implied via file create time or some other meta-data source)\n* **[Folders](#folders)**: Describes where to file the record\n* **[Todo/Done](#tododone)**: Indicates whether the record is something todo or something done\n* **[URLs](#urls)**: See the [urlPattern](https://github.com/tatatap-com/sowhat/blob/master/src/urlPattern.js) for the exact Regex\n* **[Links](#links)**: Format to capture a link or image or both\n* **[Tags](#tags)**: Standard tagging organizational structure\n* **[Mentions](#mentions)**: Mentions allow tagging of a handle\n* **[Events](#events)**: Just like a tag, but utilizes the date element to indicate that _something_ happened at that time. In addition to marking a moment in time, events can include a continuation notation indicating the event spans a time range ending when a record dated in the future includes an _event close token_\n* **[Beans](#beans)**: Beans are meant to be counted, and so they must be, or they are not much use. They are like tags combined with a number used to increase or decrease the value of a symbol. \n* **[Cells](#cells)**: Cells are very similar to beans, but have slightly better syntactic ergonomics and semantically they work better with data other than cashflow-like things\n* **[Formulas](#formulas)**: Lisp-style equations that are able to reference the value of *Beans* and other *Formulas*\n* Words: words wonderful words, whatever words you like.\n\n\n```\n\u003cDate\u003e? \u003cFolder\u003e? \u003cTodo|Done\u003e? \u003c Word | URL | Tag | Event | Bean | Formula | Whitespace \u003e*\n```\n\nReplace the `\u003cElement\u003e` with the element specifications below. `?` after an element indicates the element is optional. `*` after an element indicates 0 or more of the preceding element(s).\n\n\n[See examples below](#examples)\n\n\nThe placement of Dates, Folders, Todos and Dones is fixed. These four elements must conform to the following order: \n\n```\n\u003cDate\u003e:? \u003cFolder\u003e:? \u003cTodo|Done\u003e:?\n```\nDates, Folders and Todo/Done are all optional\n\n\n### Element Label\n\n\nFolders, Tags, Events and Beans all include a Label portion. The regex for this portion is: \n\n```\n'(\"([^\"\\\\\\n]|\\\\.)*\")|(([\\u1000-\\uffff]|[a-zA-Z]|[\\$\\xA2-\\xA5\\u058F\\u060B\\u09F2\\u09F3\\u09FB\\u0AF1\\u0BF9\\u0E3F])([\\u1000-\\uffff]|[a-zA-Z0-9\\-_]|[\\$\\xA2-\\xA5\\u058F\\u060B\\u09F2\\u09F3\\u09FB\\u0AF1\\u0BF9\\u0E3F]){0,18})'\n```\n\nIt matches quoted text or non-whitespace text limited to the character sequence: `(([\\u1000-\\uffff]|[a-zA-Z]|[\\$\\xA2-\\xA5\\u058F\\u060B\\u09F2\\u09F3\\u09FB\\u0AF1\\u0BF9\\u0E3F])([\\u1000-\\uffff]|[a-zA-Z0-9\\-_]|[\\$\\xA2-\\xA5\\u058F\\u060B\\u09F2\\u09F3\\u09FB\\u0AF1\\u0BF9\\u0E3F]){0,18})` \n\n### Pins\n\nAn optional flag to add to the very beginning of a record, `*1`. The purpose of a Pin is to give the system a means to sort records with a sequence value other than Date.\n\nThe syntax of a Pin is an asterisk followed by 0-3 integers, giving 1000 possible pin positions. Must be pecified as the first element in a record.\n\n```\n*\n```\n\n```\n*0\n```\n\n```\n*999\n```\n\n```\n*420\n```\n\n\n### Dates\n\nAn optional date of the record can be specified as the first element. It must conform to the following format YYYY-MM-DD HH:MM:SS\n\nThe exact regex is:\n\n```\n(\\d{4})-?(1[0-2]|0[1-9])-?(3[01]|0[1-9]|[12][0-9])(([\\sT])?(2[0-3]|[01][0-9]):?([0-5][0-9]):?([0-5][0-9])?(\\.[0-9]+)?Z?)\n```\n\nAs you can see, sowhat does not validate whether the date is a real date. This task is left to the system using the sowhat language. It's possible, for example, to send 2021-02-31 and sowhat understands this to be a date. \n\nDepending on your application you may wish to ignore the date portion of the record in favor of the timestamp associated with an entity in your own system. \n\nIt can also be used to override a default date assignment provided by entities in your own system.\n\n\n### Folders\n\nA record can include one folder. It must follow the date element or be the first element of a record. Folders must be a `/` followed by the *[element label pattern](#element-label)*\n\nFolders may contain any number of nested folder segments.\n\nIf a folder is not specified no assumption is made as to what folder the record belongs. In other words no default folder is set. If folders are implemented it might make sense to implement a default value such as `/`.\n\n### Todo/Done\n\nTodo and Done keywords occur at the beginning of a record or follow a folder or date. The two elements are two aspects of the same concept -- they are meant to indicate whether the record is something to do or something that has been done! \n\nThe keywords can be capital or lowercase or a mix, it does not matter: `todo`, `DONE`, `ToDo`, `dONe` are all OK.\n\n\n### URLs\n\nURLs identified in the record are parsed into a list for further processing. They can be included anywhere in the record except within another element.\n\nThe URL regex can be found [here](https://github.com/tatatap-com/sowhat/blob/master/src/urlPattern.js) \n\n### Links and Images\n\nLinks and images are grouped together because of their often complementary behavior. The sowhat link element allows one to define a plain link/name combo, a link whose content is an image, or just an image.\n\nPossible scenarios:\n\n```\n://(\"url\")\n://(\"url\" \"name\")\n://(\"url\")() \u003c-- unnecessary extra parens\n://()(\"image-url\")\n://()(\"image-url\" \"name\")\n://(\"url\")(\"image-url\")\n://(\"url\")(\"image-url\" \"name\")\n://(\"url\" \"name\")() \u003c-- invalid unnecessary extra parens\n://(\"url\" \"name\")(\"image-url\")\n://(\"url\" \"name\")(\"image-url\" \"name\")\n\n```\n\n\n### Tags\n\nA `#` character followed by the *label pattern* regex. Full tag regex:\n\n### Mentions\n\nA `@` character followed by the a limited ASCII label regex. Full mention regex:\n\n```\n@[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*\n```\n\nThe idea here is pretty simple -- provide a way to highlight and refer to handles mentioned in the record.\n\n### Events\n\nEvents indicate that _something_ happened at a certain time. There are two forms of events: single point in time and ranges. The time associated with an event is the date specified along with the record.\n\nThe name of the event must match the *[element label pattern](#element-label)* of the element referenced above.\n\n#### Point-in-time Events\n\nSyntactically the same as a tag, but instead of a \"#\" they begin with a \"!\"\n\n#### Range Events\n\nRange events have two parts: an opening and a closing. To open a Range Event include \"...\" after the event like so: `!foo...`. To close this Range Event use the following format `...foo` \n\nA couple notes on Range Events:\n\n* In order for a range to be defined the open and close need to be defined in two separate records with the Close Range element record's date later than the Start Range element record's date.\n* Sowhat only handles the identification of these elements, the specific implementation will require a methodology for disambiguation when multiple open/close pairs are found with the same *label*\n\n### Beans\n\nBeans are used to increase or decrease a value associated with a symbol (the label pattern of the Bean). \n\nThe syntax is:\n\n```\n\u003c+|-\u003e\u003cLabel\u003e\u003c:\u003cNumber\u003e\u003e?\n```\n\nThe number portion is optional, and if ommitted will result in an increase or decrease of `1`.\n\nTo increase a Bean value use a `+` sign\n\n```\n+cash:42\n```\n\nTo decrease a Bean value use a `-` sign\n\n```\n-cash:42\n```\n\nThe value is any number that matches the following regex (NOTE: it must be a positive number):\n\n```\n/([0-9]*\\\\.?[0-9]+|[0-9]+\\\\.?[0-9]*)([eE][+-]?[0-9]+)?/\n```\n\n### Cells\n\nCells will probably replace Beans at some point. They are very similar, but the syntax is a bit more user-friendly.\n\nSyntax is:\n\n```\n\u0026\u003cLabel\u003e\u003c:\u003cNumber\u003e\u003e?\n```\n\nThe number can be positive or negative, unlike Beans.\n\n\n### Formulas\n\nFormulas are used to calculate number values. \n\nThey use the following syntax\n\n```\n$$(\u003cLabel\u003e)\u003cS-Expression Formula Body\u003e\n```\n\nMatching a formula is not one regex, but a collection of different patterns -- the details can be found [here](https://github.com/sowhat-lang/sowhat/blob/main/src/formula-states.js)\n\nThe formula name or `\u003cLabel\u003e` must conform to the *[Element Label Pattern](#element-label)* above\n\nThe Formula body uses a lisp style s-expression syntax. Any non-space sequence of characters up to 42 in total length registers as an operator.\n\nFormulas are intended to use alongside *Beans*. Beans values could be referenced as arguments to other math functions or invoked as part of a custom function that looks up their value.\n\nFor a reference implementation see the [/tap documentation on Formulas](https://www.tatatap.com/formulas)\n\n### Errors\n\nEven though all text will parse as a valid record, an individual element may contain errors. Errors that are encountered parsing a formula are captured and stored with the formula object. All other errors are stored in the top-level record object. \n\nAll errors include the offending text and location it was encountered.\n\n## Examples\n\nA record in the Folder \"Special Stuff\" which is inside the Folder \"goods\":\n\n```\n/goods/\"Special Stuff\" This is a basic record inside of a subfolder. \n```\n\n```JSON\n{\n  \"date\": null,\n  \"reaction\": null,\n  \"folder\": [\n    {\n      \"value\": \"/goods\",\n      \"text\": \"/goods\",\n      \"offset\": 0,\n      \"line\": 1,\n      \"col\": 1,\n      \"lineBreaks\": 0,\n      \"error\": null\n    },\n    {\n      \"value\": \"/Special Stuff\",\n      \"text\": \"/\\\"Special Stuff\\\"\",\n      \"offset\": 6,\n      \"line\": 1,\n      \"col\": 7,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"todo\": null,\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"/goods/\\\"Special Stuff\\\" This is a basic record inside of a subfolder.\",\n  \"body\": \"This is a basic record inside of a subfolder.\"\n}\n```\n\n\nA Dated record with a Point-in-Time Event \"surprise\":\n\n```\n2021-12-25 !Surprise \n```\n\n```JSON\n{\n  \"date\": {\n    \"value\": \"2021-12-25\",\n    \"text\": \"2021-12-25\",\n    \"offset\": 0,\n    \"line\": 1,\n    \"col\": 1,\n    \"lineBreaks\": 0,\n    \"error\": null\n  },\n  \"reaction\": null,\n  \"folder\": [],\n  \"todo\": null,\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [\n    {\n      \"value\": \"surprise\",\n      \"text\": \"!Surprise\",\n      \"offset\": 11,\n      \"line\": 1,\n      \"col\": 12,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"2021-12-25 !Surprise\",\n  \"body\": \"!Surprise\"\n}\n```\n\nA record that contains an increase of 1000 in the Bean \"cash\" and a decrease of 42.42 in the Bean \"budget\":\n\n```\n+cash:1000 -budget:42.42\n```\n\n\n```JSON\n{\n  \"date\": null,\n  \"reaction\": null,\n  \"folder\": [],\n  \"todo\": null,\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [],\n  \"url\": [],\n  \"bean\": [\n    {\n      \"value\": {\n        \"sign\": \"+\",\n        \"value\": \"1000\",\n        \"symbol\": \"cash\"\n      },\n      \"text\": \"+cash:1000\",\n      \"offset\": 0,\n      \"line\": 1,\n      \"col\": 1,\n      \"lineBreaks\": 0,\n      \"error\": null\n    },\n    {\n      \"value\": {\n        \"sign\": \"-\",\n        \"value\": \"-42.42\",\n        \"symbol\": \"budget\"\n      },\n      \"text\": \"-budget:42.42\",\n      \"offset\": 10,\n      \"line\": 1,\n      \"col\": 11,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"+cash:1000 -budget:42.42\",\n  \"body\": \"+cash:1000 -budget:42.42\"\n}\n```\n\nA record with a Formula that calculates the net value of the Bean \"cash\" divided by 30:\n\n```\n$$(\"NV Cash\")(/ (BEAN cash) 30) \n```\n\n```JSON\n{\n  \"date\": null,\n  \"reaction\": null,\n  \"folder\": [],\n  \"todo\": null,\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [\n    {\n      \"value\": {\n        \"name\": \"NV Cash\",\n        \"procedure\": {\n          \"type\": \"func\",\n          \"operator\": \"/\",\n          \"args\": [\n            {\n              \"type\": \"func\",\n              \"operator\": \"BEAN\",\n              \"args\": [\n                \"cash\"\n              ],\n              \"text\": \"(BEAN cash)\",\n              \"error\": null,\n              \"offset\": 16,\n              \"line\": 1,\n              \"col\": 17,\n              \"lineBreaks\": 0\n            },\n            \"30\"\n          ],\n          \"text\": \"(/ (BEAN cash) 30)\",\n          \"error\": null,\n          \"offset\": 13,\n          \"line\": 1,\n          \"col\": 14,\n          \"lineBreaks\": 0\n        }\n      },\n      \"text\": \"$$(\\\"NV Cash\\\")(/ (BEAN cash) 30)\",\n      \"offset\": 0,\n      \"line\": 1,\n      \"col\": 1,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"text\": \"$$(\\\"NV Cash\\\")(/ (BEAN cash) 30)\",\n  \"body\": \"$$(\\\"NV Cash\\\")(/ (BEAN cash) 30)\"\n}\n```\n\nA record with a Todo: Dated and in the Folder \"work\":\n\n```\n2021-11-24 20:00 /work Todo Put turkey in the oven. \n```\n\n```JSON\n{                                                                                                        \n  \"date\": {\n    \"value\": \"2021-11-24 20:00\",\n    \"text\": \"2021-11-24 20:00\",\n    \"offset\": 0,\n    \"line\": 1,\n    \"col\": 1,\n    \"lineBreaks\": 0,\n    \"error\": null\n  },\n  \"reaction\": null,\n  \"folder\": [\n    {\n      \"value\": \"/work\",\n      \"text\": \"/work\",\n      \"offset\": 17,\n      \"line\": 1,\n      \"col\": 18,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"todo\": {\n    \"value\": \"Todo\",\n    \"text\": \"Todo\",\n    \"offset\": 23,\n    \"line\": 1,\n    \"col\": 24,\n    \"lineBreaks\": 0,\n    \"error\": null\n  },\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"2021-11-24 20:00 /work Todo Put turkey in the oven.\",\n  \"body\": \"Put turkey in the oven.\"\n}\n```\n\nThe same record as above, but Done:\n  \n```\n2021-11-25 08:15 /work Done Put turkey in the oven. \n```\n\n```JSON\n{\n  \"date\": {\n    \"value\": \"2021-11-25 08:15\",\n    \"text\": \"2021-11-25 08:15\",\n    \"offset\": 0,\n    \"line\": 1,\n    \"col\": 1,\n    \"lineBreaks\": 0,\n    \"error\": null\n  },\n  \"reaction\": null,\n  \"folder\": [\n    {\n      \"value\": \"/work\",\n      \"text\": \"/work\",\n      \"offset\": 17,\n      \"line\": 1,\n      \"col\": 18,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"todo\": null,\n  \"done\": {\n    \"value\": \"Done\",\n    \"text\": \"Done\",\n    \"offset\": 23,\n    \"line\": 1,\n    \"col\": 24,\n    \"lineBreaks\": 0,\n    \"error\": null\n  },\n  \"tag\": [],\n  \"event\": [],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"2021-11-25 08:15 /work Done Put turkey in the oven.\",\n  \"body\": \"Put turkey in the oven.\"\n}\n```\n\nA Dated record that contains a Range Event \"Dance\": \n\n  \n```\n2021:02:20 09:00 !Dance...\n```\n\n```JSON\n{\n  \"date\": null,\n  \"reaction\": null,\n  \"folder\": [],\n  \"todo\": null,\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [\n    {\n      \"value\": {\n        \"label\": \"dance\",\n        \"isRange\": true,\n        \"form\": \"open\"\n      },\n      \"text\": \"!Dance...\",\n      \"offset\": 17,\n      \"line\": 1,\n      \"col\": 18,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"2021:02:20 09:00 !Dance...\",\n  \"body\": \"2021:02:20 09:00 !Dance...\"\n}\n```\n  \nClose range\n  \n```\n2021:02:20 10:00 ...Dance\n```\n\n```JSON\n{\n  \"date\": null,\n  \"reaction\": null,\n  \"folder\": [],\n  \"todo\": null,\n  \"done\": null,\n  \"tag\": [],\n  \"event\": [\n    {\n      \"value\": {\n        \"label\": \"dance\",\n        \"isRange\": true,\n        \"form\": \"close\"\n      },\n      \"text\": \"...Dance\",\n      \"offset\": 17,\n      \"line\": 1,\n      \"col\": 18,\n      \"lineBreaks\": 0,\n      \"error\": null\n    }\n  ],\n  \"url\": [],\n  \"bean\": [],\n  \"error\": [],\n  \"formula\": [],\n  \"text\": \"2021:02:20 10:00 ...Dance\",\n  \"body\": \"2021:02:20 10:00 ...Dance\"\n}\n```\n  \n#### Intro Example\n\n```\n2021-01-30 00:55 /lunch\n\nTodo Purchase\n\n* bacon\n* lettuce\n* tomatoes\n* bread\n* mayo\n\n-\"Groceries Budget\":20.50 \n\n$$(\"Cash After Shopping\")\n  (- (BEAN \"All My Money\")\n     (BEAN \"Groceries Budget\"))\n```\n\nThe parsed result of the above record:\n\n```JSON\n{\n  \"date\": {\n    \"value\": \"2021-01-30 00:55\",\n    ...\n  },\n  \"folder\": [\n    {\n      \"value\": \"/lunch\",\n      ....\n    }\n  ],\n  \"todo\": {\n    \"value\": \"Todo\",\n    ...\n  },\n  ...\n  \"bean\": [\n    {\n      \"value\": {\n        \"sign\": \"-\",\n        \"value\": \"-20.00\",\n        \"symbol\": \"Groceries Budget\"\n      },\n      ...\n    }\n  ],\n  ...\n  \"formula\": [\n    {\n      \"value\": {\n        \"name\": \"Cash After Shopping\",\n        \"procedure\": {\n          \"type\": \"func\",\n          \"operator\": \"-\",\n          \"args\": [\n            {\n              \"type\": \"func\",\n              \"operator\": \"BEAN\",\n              \"args\": [\n                \"All My Money\"\n              ],\n              ...\n            },\n            {\n              \"type\": \"func\",\n              \"operator\": \"BEAN\",\n              \"args\": [\n                \"Groceries Budget\"\n              ],\n              ...\n            }\n          ],\n          \"text\": \"(- (BEAN \\\"All My Money\\\")\\n    (BEAN \\\"Groceries Budget\\\"))\",\n          ...\n        }\n      },\n      \"text\": \"...\",                                                                                                     \n     ...\n    }\n  ],\n  \"text\": \"...\",                                                                         \n  \"body\": \"...\" \n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftatatap-com%2Fsowhat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftatatap-com%2Fsowhat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftatatap-com%2Fsowhat/lists"}