├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── FUNDING.yml └── workflows │ └── release.yml ├── .gitignore ├── .npmrc ├── LICENSE ├── README.md ├── docs ├── cover.gif └── examples.md ├── esbuild.config.mjs ├── main.ts ├── manifest.json ├── package-lock.json ├── package.json ├── styles.css ├── styles.scss ├── tsconfig.json ├── version-bump.mjs └── versions.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = 4 10 | tab_width = 4 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | main.js 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "env": { "node": true }, 5 | "plugins": [ 6 | "@typescript-eslint" 7 | ], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "parserOptions": { 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "no-unused-vars": "off", 18 | "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], 19 | "@typescript-eslint/ban-ts-comment": "off", 20 | "no-prototype-builtins": "off", 21 | "@typescript-eslint/no-empty-function": "off" 22 | } 23 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [akopdev] 2 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Build obsidian plugin 2 | 3 | on: 4 | push: 5 | # Sequence of patterns matched against refs/tags 6 | tags: 7 | - "*" # Push events to matching any tag format, i.e. 1.0, 20.15.10 8 | 9 | env: 10 | PLUGIN_NAME: textgrams 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: "21.x" 22 | - name: Build 23 | id: build 24 | run: | 25 | yarn 26 | yarn run build --if-present 27 | mkdir ${{ env.PLUGIN_NAME }} 28 | cp main.js manifest.json styles.css ${{ env.PLUGIN_NAME }} 29 | zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }} 30 | ls 31 | echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)" 32 | - name: Create Release 33 | id: create_release 34 | uses: actions/create-release@v1 35 | env: 36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 37 | VERSION: ${{ github.ref }} 38 | with: 39 | tag_name: ${{ github.ref }} 40 | release_name: ${{ github.ref }} 41 | draft: false 42 | prerelease: false 43 | - name: Upload zip file 44 | id: upload-zip 45 | uses: actions/upload-release-asset@v1 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | with: 49 | upload_url: ${{ steps.create_release.outputs.upload_url }} 50 | asset_path: ./${{ env.PLUGIN_NAME }}.zip 51 | asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip 52 | asset_content_type: application/zip 53 | - name: Upload main.js 54 | id: upload-main 55 | uses: actions/upload-release-asset@v1 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | with: 59 | upload_url: ${{ steps.create_release.outputs.upload_url }} 60 | asset_path: ./main.js 61 | asset_name: main.js 62 | asset_content_type: text/javascript 63 | - name: Upload manifest.json 64 | id: upload-manifest 65 | uses: actions/upload-release-asset@v1 66 | env: 67 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 68 | with: 69 | upload_url: ${{ steps.create_release.outputs.upload_url }} 70 | asset_path: ./manifest.json 71 | asset_name: manifest.json 72 | asset_content_type: application/json 73 | - name: Upload styles.css 74 | id: upload-css 75 | uses: actions/upload-release-asset@v1 76 | env: 77 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 78 | with: 79 | upload_url: ${{ steps.create_release.outputs.upload_url }} 80 | asset_path: ./styles.css 81 | asset_name: styles.css 82 | asset_content_type: text/css 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | .vscode 3 | 4 | # Intellij 5 | *.iml 6 | .idea 7 | 8 | # npm 9 | node_modules 10 | 11 | # Don't include the compiled main.js file in the repo. 12 | # They should be uploaded to GitHub releases instead. 13 | main.js 14 | 15 | # Exclude sourcemaps 16 | *.map 17 | 18 | # obsidian 19 | data.json 20 | 21 | # Exclude macOS Finder (System Explorer) View States 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix="" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Akop Kesheshyan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Textgram Plugin for Obsidian 2 | ============================ 3 | 4 | Obsidian plug-in that allows you to create and store ASCII graphics in your notes. 5 | It can be used to to define diagrams, flowcharts, complex tables, Gantt charts and more 6 | in technical documentation, that will be rendered as a nice SVG graphics in the preview mode. 7 | 8 | This plug-in is based on [typograms](https://github.com/google/typograms) library, originally 9 | developed by [Sam Goto](https://code.sgo.to/2022/06/20/typographic-diagrams.html). 10 | 11 |  12 | 13 | ## Motivation 14 | 15 | I'm a software engineer and I use Obsidian to document my projects, as long as support my 16 | continuous learning process. I often need to create diagrams, flowcharts, tables and other graphics, 17 | that are not locked in a specific tool, but can be easily shared and versioned in my notes. 18 | 19 | Using ASCII graphics allows to create a very flexible and portable content, that can be easily 20 | edited and versioned in a text file, without loosing benefits of a visual representation. 21 | 22 | ## Features 23 | 24 | - [X] Store ASCII graphics in notes and render them as SVG graphics in the preview mode. 25 | - [ ] Use build-in editor to create and modify ASCII graphics without leaving Obsidian. 26 | 27 | ## Installation 28 | 29 | Install the plugin via the Obsidian third-party plugin browser. 30 | 31 | 1. Open the Obsidian settings. 32 | 2. In the sidebar, select `Community plugins`. 33 | 3. Search for `Textgrams` in available plugins. 34 | 4. Click `Install`. 35 | 5. Enable the plugin in the Obsidian settings. 36 | 37 | ## Usage 38 | 39 | Just create a code block with `textgram` language and write your ASCII graphics inside it. 40 | 41 | Example: 42 | 43 |
44 | ```textgram 45 | +-----+ +-----+ 46 | | A | | B | 47 | +--+--+ +--+--+ 48 | | foo | 49 | |----------------->| 50 | | hello | 51 | |----------------->|--+ 52 | | world | | prompts the user 53 | |<-----------------|--+ 54 | | | 55 | --+-- --+-- 56 | ``` 57 |58 | 59 | You can find more examples [here](docs/examples.md). 60 | 61 | ## Development 62 | 63 | If you have any suggestions, issues or feature requests, please open an issue in the GitHub repository. 64 | 65 | ## Support this project 66 | 67 | You can support this project by starring the repository, sharing it with your friends or contributing to 68 | the code. 69 | 70 | You can also support the author by buying him a coffee. Click sponsor button on the top of the page. 71 | -------------------------------------------------------------------------------- /docs/cover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akopdev/obsidian-textgrams/f6396331ec20b0d320eab4ea64ef9e44ceaa1682/docs/cover.gif -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | ```textgram 2 | 3 | +- -+ -+ +- | | | | -+- | / \ \ / +- -+ +- -+ + \ / \ / 4 | | | | | +- -+ -+ +- | -+- +- -+ +- -+ \ / / \ / \ + + + 5 | / \ 6 | 7 | .- -. -. .- | | | | -.- | / \ \ / .- -. .- -. . \ / \ / 8 | | | | | '- -' -' '- | -'- '- -' '- -' \ / / \ / \ ' . . 9 | / \ 10 | 11 | _ _ _ _ ___ _ _ __ __ _ \ / 12 | | | | | |_ _| _| |_ | _|_ /_ _\ \_ _/ \ / / \ / \ \_/ | | 13 | / \ 14 | 15 | 16 | +~ ~+ ~+ +~ : : : : ~+~ : 17 | : : : : +~ ~+ ~+ +~ : ~+~ 18 | 19 | / \ 20 | /\ \/ \ / 21 | 22 | -. .- -. .-. .- .-. 23 | '- -' '-' '-' '-' 24 | ``` 25 | 26 | ## Dots 27 | 28 | ```textgram 29 | o-o *-o #-o | | | \ / \ / \ / \ / \ / \ / 30 | o-* *-* #-* o * # o o o o * * * * # # # # 31 | o-# *-# #-# | | | / \ / \ / \ / \ / \ / \ 32 | ``` 33 | 34 | 35 | ## Arrows 36 | 37 | ```textgram 38 | | ^ ^ ^ / \ 39 | -> <- v | / \ v v 40 | 41 | ->| |<- ->o o<- ->* *<- -># #<- 42 | 43 | - _ * o # 44 | ^ ^ ^ ^ ^ 45 | | | | | | 46 | 47 | | | | | | 48 | v v v v v 49 | - _ * o # 50 | 51 | ---- 52 | \ | | / ^| |^ \ / ^ ^ 53 | v| |v / | | \ v v / \ 54 | ---- 55 | ``` 56 | 57 | ## Protocols 58 | 59 | ```textgram 60 | +-----+ +-----+ 61 | | A | | B | 62 | +--+--+ +--+--+ 63 | | foo | 64 | |----------------->| 65 | | hello | 66 | |----------------->|--+ 67 | | world | | prompts the user 68 | |<-----------------|--+ 69 | | | 70 | --+-- --+-- 71 | ``` 72 | 73 | ## Mocks 74 | 75 | ```textgram 76 | .------------------------. 77 | |.----------------------.| 78 | ||"https://example.com" || 79 | |'----------------------'| 80 | | ______________________ | 81 | || || 82 | || Welcome! || 83 | || || 84 | || || 85 | || .----------------. || 86 | || | username | || 87 | || '----------------' || 88 | || .----------------. || 89 | || |"*******" | || 90 | || '----------------' || 91 | || || 92 | || .----------------. || 93 | || | "Sign-up" | || 94 | || '----------------' || 95 | || || 96 | |+----------------------+| 97 | .------------------------. 98 | ``` 99 | 100 | 101 | ## Architecture 102 | 103 | ```textgram 104 | Sender Mail Server Receiver 105 | _____ 106 | .---------. SMTP |=====| POP .---------. 107 | | |-------------->| |<--------------| | 108 | | Alice | | | | Bob | 109 | +---------+ | o | +---------+ 110 | /// _____ \\\ |_____| /// _____ \\\ 111 | '-------------' '-------------' 112 | +---------------------+ 113 | |"To: bob@bar.com" | 114 | |"From: alice@foo.com"| 115 | |"Body: Hi!" | 116 | +---------------------+ 117 | ``` 118 | 119 | ### Layers 120 | 121 | ```textgram 122 | .---. .---. .---. .---. .---. .---. 123 | '---' '---' '---' '---' '---' '---' 124 | | | | | | | 125 | v v | v | v 126 | .------------. | .-----------. | .-----. 127 | | Filesystem | | | Scheduler | | | MMU | 128 | '------------' | '-----------' | '-----' 129 | | | | | 130 | v | | v 131 | .----. | | .~~~~~~~~~. 132 | | IO |<----' | : Network : 133 | '----' | '~~~~~~~~~' 134 | | | | 135 | v v v 136 | .---------------------------------------. 137 | | HAL | 138 | '---------------------------------------' 139 | ``` 140 | 141 | ## Tables 142 | 143 | ```textgram 144 | +-----+---------+---------+~~~ ~~~+----------+ 145 | | ID | First | Last : : Lang | 146 | +-----+---------+---------+~~~ ~~~+----------+ 147 | | 1 | Joe | Doe : : en-US | 148 | +-----+---------+---------+~~~ ~~~+----------+ 149 | | 2 | Rick | Russel : : en-US | 150 | +-----+---------+---------+~~~ ~~~+----------+ 151 | : : : : : : 152 | 153 | : : : : : : 154 | +-----+---------+---------+~~~ ~~~+----------+ 155 | | 999 | Anna | Merkle : : pt-BR | 156 | +-----+---------+---------+~~~ ~~~+----------+ 157 | ``` 158 | 159 | ## Flow charts 160 | 161 | ```textgram 162 | .-------. + 163 | | START | / \ 164 | '---+---' / \ +-+---------+-+ ___________ 165 | | .-----. / \ | | COMPLEX | | / \ 166 | v | END |<---+CHOICE +--->| | | |->+ PREPARATION +-> X 167 | +-------+ '-----' \ / | | PROCESS | | \___________/ 168 | / INPUT / \ / +-+---------+-+ 169 | +-------+ \ / 170 | | + 171 | v ^ 172 | +---------+ +----+----+ 173 | | PROCESS |------------>| PROCESS |<----- x 174 | +---------+ +---------+ 175 | ``` 176 | 177 | ## Trees 178 | 179 | ```textgram 180 | + + +-- 1 .-- 1 / 1 181 | / \ | +--+ .--+ + 182 | / \ +---+---+ | +-- 2 | '-- 2 / \ 2 183 | + + | | --+ --+ + 184 | / \ / \ +-+-+ +-+-+ | +-- 3 | .-- 3 \ / 3 185 | / \ / \ | | | | +--+ '--+ + 186 | 1 2 3 4 1 2 3 4 +-- 4 '-- 4 \ 4 187 | 188 | 189 | Linux 190 | +--Android 191 | +--Debian 192 | | +--Ubuntu 193 | | | +--Lubuntu 194 | | | +--Kubuntu 195 | | | `--Xubuntu 196 | | `--Mint 197 | +--Centos 198 | `--Fedora 199 | 200 | 201 | X Y 202 | / \ / \ 203 | A Y -> X C 204 | / \ / \ 205 | B C A B 206 | 207 | ``` 208 | 209 | ## Shapes 210 | 211 | ```textgram 212 | +---------+ + +------+ .-----. +~~~~~+ +----+ +----+ 213 | \ / / \ \ \ | | : : / \ / \ 214 | \ / / \ \ \ | | : : / \ | | 215 | \ / / \ \ \ | | : : \ / | | 216 | \ / / \ \ \ | | : : \ / \ / 217 | + +---------+ +------+ '-----' +~~~~~+ +----+ +----+ 218 | ``` 219 | 220 | ### Small Shapes 221 | 222 | ```textgram 223 | __ ____ ___ .---. __ +-+ +-+ 224 | / \ /\ \ / + \ / /\ +-+ +-+ +-+ | | ++ | | _ / / \ \ 225 | \__/ /__\ \/ /_\ + / \ +-+ /_/ \_\ '---' ++ |__| |_| +-+ +-+ 226 | +----+ 227 | ``` 228 | 229 | ### Overlaps and intersections 230 | 231 | ```textgram 232 | .---. .---. .---. .---. .---. 233 | | | | | | | | | | | 234 | .--+---+--. .--+---+--. .--| |--. .--+ +--. .---- |---. 235 | | | | | | | | | | | | | | | 236 | '--+---+--' '--+---+--' '--| |--' '--+ +--' '--| -----' 237 | | | | | | | | | | | 238 | '---' '---' '---' '---' '---' 239 | ``` 240 | 241 | ## Grids 242 | 243 | ```textgram 244 | +----+ +----+ 245 | / \ / \ .-----+-----+-----. 246 | + +----+ +----+ | | | | .-----+-----+-----+-----+ 247 | \ / \ / \ | | | | / / / / / 248 | +----+ +----+ + +-----+-----+-----+ +-----+-----+-----+-----+ 249 | / \ / \ / | | | | / / / / / 250 | + +----+ +----+ | | | | +-----+-----+-----+-----+ 251 | \ / \ / \ +-----+-----+-----+ / / / / / 252 | +----+ +----+ + | | | | +-----+-----+-----+-----+ 253 | \ / \ / | | | | / / / / / 254 | +----+ +----+ '-----+-----+-----' '-----+-----+-----+-----+ 255 | ``` 256 | 257 | ### Small grids 258 | 259 | ```textgram 260 | ___ ___ .---+---+---+---+---. .---+---+---+---. .---. .---. 261 | ___/ \___/ \ | | | | | | / \ / \ / \ / \ / | +---+ | 262 | / \___/ \___/ +---+---+---+---+---+ +---+---+---+---+ +---+ +---+ 263 | \___/ \___/ \ | | | | | | \ / \ / \ / \ / \ | +---+ | 264 | / \___/ \___/ +---+---+---+---+---+ +---+---+---+---+ +---+ +---+ 265 | \___/ \___/ \ | | | | | | / \ / \ / \ / \ / | +---+ | 266 | \___/ \___/ '---+---+---+---+---' '---+---+---+---' '---' '---' 267 | ``` 268 | 269 | ### Dot grids 270 | 271 | ```textgram 272 | o o o o o * * * * * o * * * o o o o * * * . * . . . 273 | o o o o o * * * * * * o o o * o o o o * * * * . o . . . 274 | o o o o o * * * * * o o o o * o o o o o * * * * * . . . . . 275 | o o o o o * * * * * * * * o o o o o o * * * * . o o * . 276 | o o o o o * * * * * o o o * * o o o * * * . o o o o 277 | ``` 278 | 279 | ## Time series 280 | 281 | ```textgram 282 | 283 | 85.67 ┤ ╭╮ 284 | 78.20 ┤ ││ ╭╮ 285 | 70.73 ┤ ││ ╭╮ ╭╮ ╭╮ ╭╮ ╭╯╰─╮ 286 | 63.27 ┤ ╭╮ ╭─╮ ││ ╭╯╰╮│╰─╯╰╮╭╮│╰──╯ │╭ 287 | 55.80 ┤ ╭╮ ╭╮││╭╮ ╭╮╭╮ │ ╰─╯╰─╯ ││ ││││ ╰╯ 288 | 48.33 ┤ │╰╮ ╭──╮ │││││╰╮│╰╯│ │ ╰╯ ╰╯╰╯ 289 | 40.87 ┤╭╮ │ ╰╮╭╮ ╭╯ ╰─╮╭╮╭─╯╰╯╰╯ ╰╯ ╰──╯ 290 | 33.40 ┤││ │ ╰╯╰╮╭╯ ││╰╯ 291 | 25.93 ┤││╭╯ ╰╯ ╰╯ 292 | 18.47 ┼╯││ 293 | 11.00 ┤ ╰╯ 294 | └───────────┴───────────┴───────────┴───────────┴───────────┴──── 295 | 2011 2012 2013 2014 2015 2016 296 | 297 | E +-------------------------*--+ E | o 298 | D |-------------------*--*--|--* D | o o | o 299 | C |-------------*--* | | | | C | o o | | | | 300 | B |-------*--* | | | | | | B | o o | | | | | | 301 | A +-*--*--+--+--+--+--+--+--+--+ A +-o--o--|--|--|--|--|--|--|--| 302 | 5 10 15 20 25 30 35 40 45 50 5 10 15 20 25 30 35 40 45 50 303 | 304 | ▲ 305 | Uin : .------------------------ 306 | : | 307 | : | 308 | *---'~~~~~~~~~~~~~~~~~~~~~~~~▶ 309 | 310 | Udc▲ 311 | Udc_OK : .--------------------- 312 | : / : : 313 | : / : : 314 | *---'~~~~:~~~~~~~:~~~~~~~~~~~▶ 315 | :<----->: 316 | 500ms 317 | ▲ 318 | : 319 | Cpu.Qon :~~~~~~~~~~~~~~~~.----------- 320 | : | Inactive 321 | : Active | 322 | *----------------'~~~~~~~~~~~▶ 323 | ``` 324 | 325 | ## Chips 326 | 327 | ```textgram 328 | +-----+ 329 | +----[PWR]-------------------| USB |--+ 330 | | +-----+ | 331 | | "GND/RST2" [ ][ ] | 332 | | "MOSI2/SCK2" [ ][ ]"A5/SCL"[ ] | C5 333 | | "5V/MISO2" [ ][ ]"A4/SDA"[ ] | C4 334 | | AREF [ ] | 335 | | GND [ ] | 336 | | [ ]"N/C" "SCK/13"[ ] | B5 337 | | [ ] IOREF "MISO/12"[ ] | "." 338 | | [ ] RST "MOSI/11"[ ]~| "." 339 | | [ ] 3V3 +---+ 10 [ ]~| "." 340 | | [ ] 5v | A | 9 [ ]~| "." 341 | | [ ] GND -| R |- 8 [ ] | B0 342 | | [ ] GND -| D |- | 343 | | [ ] Vin -| U |- 7 [ ] | D7 344 | | -| I |- 6 [ ]~| "." 345 | | [ ] A0 -| N |- 5 [ ]~| "." 346 | | [ ] A1 -| O |- 4 [ ] | "." 347 | | [ ] A2 +---+ "INT1/3"[ ]~| "." 348 | | [ ] A3 "INT0/2"[ ] | "." 349 | | [ ]"A4/SDA"RST SCK MISO "TX>1"[ ] | "." 350 | | [ ]"A5/SCL"[ ] [ ] [ ] "RX<0"[ ] | D0 351 | | [ ] [ ] [ ] | 352 | | "UNO_R3" GND MOSI 5V ___________| 353 | |_________________________| 354 | ``` 355 | 356 | ## Circuits 357 | 358 | ```textgram 359 | "+10-15V" ___0,047R 360 | *---------o-----o-|___|-o--o---------o----o-------. 361 | "+"| | | | | | | | 362 | -===- _|_ | | .+. | | | 363 | -===- .-. | | | | 2k2 | | | 364 | -===- 470|"+" | | | | | | _|_ 365 | "-"| uF| '--. | '+' .+. | \ / LED 366 | +---------o |6 |7 |8 1k | | | -+- 367 | ___|___ .-+----+--+--. | | | | 368 | -═══- | | '+' | | 369 | - | |1 | |/ BC | 370 | GND | +------o--+ 547 | 371 | | | | |`> | 372 | | | .+. | | 373 | .-------+ | 220R| | o----||-+ IRF9Z34 374 | | | | | | | |+-> 375 | | | MC34063 | `+' | ||-+ 376 | | | | | | | BYV29 -12V6 377 | | | | '----' o--|<-o----o--X OUT 378 | 6000 micro "-"|"+" | |2 | | | 379 | Farad, 40V ___|_____ | |--o C| | | 380 | Capacitor ~ ~ ~ ~ ~ | | GND 30uH C| | --- 470 381 | | | |3 1nF C| | ### uF 382 | | | |-------||--. | | | + 383 | | '-----+----+-' | GND | GND 384 | | 5| 4| | | 385 | | | '-------------o-------------o 386 | | | ___ | 387 | `-------------*------/\/\/------------o--|___|-' 388 | 2k | 1k0 389 | .+. 390 | | | 5k6 + 3k3 391 | | | in Serie 392 | '+' 393 | | 394 | GND 395 | ``` 396 | 397 | ## Mindmaps 398 | 399 | ```textgram 400 | .--> Alpha 401 | / 402 | .----> Initial Release 403 | Planning *-------. / \ 404 | \ / '---> Patch 1 405 | Initial research \ / \ 406 | * \ / '--> Patch 2 407 | \ \ /---------> Beta 408 | \ \ / 409 | \ o o _______ 410 | \ .---. *-----. / \ 411 | '------> | | '------o-> . Release . 412 | `---' o \_______/ 413 | o o o \ 414 | / \ \ \ 415 | .--' \ \ \ 416 | / \ \ '----+-> Push backs 417 | / \ \ \ 418 | /| \ \ '----> Setbacks 419 | / | \ \ 420 | V /| \ '-----> Reception 421 | Team / | \ 422 | v /| \ 423 | Worklaod / . '-->> Career change 424 | V / 425 | PTO / 426 | V 427 | Bug 428 | ``` 429 | 430 | ## Scribbles 431 | 432 | ```textgram 433 | +----+ o | o * * .----------. 434 | *-+---. '-* -+- | v ^ \ / |.--------.| 435 | | '---> +----+ ->*<- / .-+->*<-o--+ |'------> || 436 | <-' *---+ |<----->| +----' | ^ \ '---------'| 437 | |__| v *----------' 438 | 439 | .---> F 440 | A B C D / 441 | *-------*-----*---*----*-----> E 442 | \ ^ \ 443 | \ / '---> G 444 | B --> C -+ 445 | 446 | ``` 447 | 448 | ### Line ends 449 | 450 | ```textgram 451 | o-o *-o / / * o o o o o * * * * o o o o * * * * o o o o * * * * 452 | o-* *-* v v ^ ^ | | | | | | | | \ \ \ \ \ \ \ \ / / / / / / / / 453 | o-> *-> * o | | o * v o * v o * v o * v o * v o * v 454 | o- *- 455 | 456 | ^ ^ * o | | ^ ^ ^ ^ ^ ^ ^ 457 | | | ^ ^ v v * o ^ ^ ^ ^ | | | | \ \ \ \ \ \ \ \ / / / / / / / 458 | * o * o ^ ^ o * v o * v o * v o * v o * v o * v 459 | 460 | <-o <-* <-> <- -o -* -> -- *<- o<- ->o ->* 461 | 462 | \ | / 463 | \ vvv / \ | / 464 | v+-----+v vvv 465 | ->| |<- ->*<- 466 | ^+-----+^ ^^^ 467 | / ^^^ \ / | \ 468 | / | \ 469 | 470 | ``` 471 | 472 | ### Graph with small nodes 473 | 474 | ```textgram 475 | A 1 2 4 8 476 | *-->o<-->o<--o---------. o 477 | ^ ^ | ^ 478 | | | v | 479 | o<->*<-->o--->*-->o-->o<-->* 480 | 3 B 5 C 6 7 D 481 | ``` 482 | 483 | ### Graphic diagrams 484 | 485 | ```textgram 486 | 0 3 P * Eye / ^ / 487 | *-------* +y \ +) \ / Reflection 488 | 1 /| 2 /| ^ \ \ \ v 489 | *-+-----* | | v0 \ v3 --------*-------- 490 | | |4 | |7 | ◄╮ *----\-----* 491 | | *-----|-* ⤹ +-----> +x / v X \ o 492 | |/ |/ / ⤴ / o \ / \ 493 | *-------* v / \ / \ 494 | 5 6 +z v1 *------------------* v2 o-----o 495 | ``` 496 | 497 | 498 | -------------------------------------------------------------------------------- /esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import process from "process"; 3 | import builtins from "builtin-modules"; 4 | 5 | const banner = 6 | `/* 7 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 8 | if you want to view the source, please visit the github repository of this plugin 9 | */ 10 | `; 11 | 12 | const prod = (process.argv[2] === "production"); 13 | 14 | const context = await esbuild.context({ 15 | banner: { 16 | js: banner, 17 | }, 18 | entryPoints: ["main.ts"], 19 | bundle: true, 20 | external: [ 21 | "obsidian", 22 | "electron", 23 | "@codemirror/autocomplete", 24 | "@codemirror/collab", 25 | "@codemirror/commands", 26 | "@codemirror/language", 27 | "@codemirror/lint", 28 | "@codemirror/search", 29 | "@codemirror/state", 30 | "@codemirror/view", 31 | "@lezer/common", 32 | "@lezer/highlight", 33 | "@lezer/lr", 34 | ...builtins], 35 | format: "cjs", 36 | target: "es2018", 37 | logLevel: "info", 38 | sourcemap: prod ? false : "inline", 39 | treeShaking: true, 40 | outfile: "main.js", 41 | minify: prod, 42 | }); 43 | 44 | if (prod) { 45 | await context.rebuild(); 46 | process.exit(0); 47 | } else { 48 | await context.watch(); 49 | } 50 | -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; 2 | // @ts-ignore 3 | import create from "typograms/src/typograms.js"; 4 | 5 | interface TextgramsSettings { 6 | zoom: string; 7 | } 8 | 9 | const DEFAULT_SETTINGS: TextgramsSettings = { 10 | zoom: "1" 11 | } 12 | 13 | export default class Textgrams extends Plugin { 14 | settings: TextgramsSettings; 15 | 16 | async onload() { 17 | await this.loadSettings(); 18 | 19 | this.registerMarkdownCodeBlockProcessor("textgram", (source, el, ctx) => { 20 | const svg = create("\n" + source + "\n", +this.settings.zoom, false); 21 | el.addClass("textgram"); 22 | el.appendChild(svg); 23 | }); 24 | 25 | this.addSettingTab(new TextgramsSettingTab(this.app, this)); 26 | } 27 | 28 | async loadSettings() { 29 | this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); 30 | } 31 | 32 | async saveSettings() { 33 | await this.saveData(this.settings); 34 | } 35 | } 36 | 37 | class TextgramsSettingTab extends PluginSettingTab { 38 | plugin: Textgrams; 39 | 40 | constructor(app: App, plugin: Textgrams) { 41 | super(app, plugin); 42 | this.plugin = plugin; 43 | } 44 | 45 | display(): void { 46 | const {containerEl} = this; 47 | 48 | containerEl.empty(); 49 | 50 | new Setting(containerEl) 51 | .setName('Zoom level') 52 | .setDesc('Zoom level for textgrams. Default is 1 and it works best for most cases.') 53 | .addText(text => text 54 | .setPlaceholder('Default: 1') 55 | .setValue(this.plugin.settings.zoom) 56 | .onChange(async (value) => { 57 | this.plugin.settings.zoom = value; 58 | await this.plugin.saveSettings(); 59 | })); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "textgrams", 3 | "name": "Textgrams", 4 | "version": "0.6.0", 5 | "minAppVersion": "1.5.0", 6 | "description": "Store and visualise ASCII graphics and charts", 7 | "author": "Akop Kesheshyan", 8 | "authorUrl": "https://github.com/akopdev", 9 | "isDesktopOnly": false 10 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "textgrams", 3 | "version": "0.6.0", 4 | "description": "Store and visualise ASCII graphics and charts", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "node esbuild.config.mjs && sass --no-source-map *.scss styles.css", 8 | "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", 9 | "sass-build": "sass --no-source-map *.scss styles.css", 10 | "version": "node version-bump.mjs && git add manifest.json versions.json" 11 | }, 12 | "keywords": [ 13 | "ascii", 14 | "graphics", 15 | "charts", 16 | "typograms", 17 | "textgrams", 18 | "obsidian" 19 | ], 20 | "author": "Akop Kesheshyan", 21 | "license": "MIT", 22 | "devDependencies": { 23 | "@types/node": "^16.11.6", 24 | "@typescript-eslint/eslint-plugin": "5.29.0", 25 | "@typescript-eslint/parser": "5.29.0", 26 | "builtin-modules": "3.3.0", 27 | "esbuild": "0.17.3", 28 | "obsidian": "latest", 29 | "sass": "^1.81.1", 30 | "tslib": "2.4.0", 31 | "typescript": "4.7.4" 32 | }, 33 | "dependencies": { 34 | "typograms": "github:google/typograms" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | .textgram svg { 2 | max-width: 100%; 3 | padding: 20px; 4 | height: auto; 5 | } 6 | .textgram .diagram line, 7 | .textgram .diagram circle, 8 | .textgram .diagram rect { 9 | stroke: currentColor; 10 | } 11 | .textgram .debug[debug=true] .reserved { 12 | fill: currentColor; 13 | } 14 | .textgram .debug[debug=true] line.grid { 15 | stroke: currentColor; 16 | fill: currentColor; 17 | } 18 | .textgram .debug[debug=true] polygon.inner { 19 | fill: currentColor; 20 | stroke: currentColor; 21 | } 22 | .textgram polygon { 23 | stroke: currentColor; 24 | fill: currentColor; 25 | } 26 | .textgram line.part { 27 | stroke: currentColor; 28 | } 29 | .textgram .debug[debug=true] line.center { 30 | stroke: currentColor; 31 | } 32 | .textgram text:not(.reserved) { 33 | fill: currentColor; 34 | } 35 | .textgram text::selection { 36 | fill: currentColor; 37 | } 38 | .textgram path { 39 | fill: currentColor; 40 | } 41 | .textgram circle { 42 | fill: currentColor; 43 | } 44 | -------------------------------------------------------------------------------- /styles.scss: -------------------------------------------------------------------------------- 1 | $color: currentColor; 2 | 3 | .textgram { 4 | svg { 5 | max-width: 100%; 6 | padding: 20px; 7 | height: auto; 8 | } 9 | 10 | .diagram line, 11 | .diagram circle, 12 | .diagram rect { 13 | stroke: $color; 14 | } 15 | 16 | 17 | .debug[debug="true"] .reserved { 18 | fill: $color; 19 | } 20 | 21 | .debug[debug="true"] line.grid { 22 | stroke: $color; 23 | fill: $color; 24 | } 25 | 26 | 27 | .debug[debug="true"] polygon.inner { 28 | fill: $color; 29 | stroke: $color; 30 | } 31 | 32 | polygon { 33 | stroke: $color; 34 | fill: $color; 35 | } 36 | 37 | line.part { 38 | stroke: $color; 39 | } 40 | 41 | .debug[debug="true"] line.center { 42 | stroke: $color; 43 | } 44 | 45 | text:not(.reserved) { 46 | fill: $color; 47 | } 48 | 49 | text::selection { 50 | fill: $color; 51 | } 52 | 53 | path { 54 | fill: $color; 55 | } 56 | 57 | circle { 58 | fill: $color; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "ES6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "isolatedModules": true, 13 | "strictNullChecks": true, 14 | "lib": [ 15 | "DOM", 16 | "ES5", 17 | "ES6", 18 | "ES7" 19 | ] 20 | }, 21 | "include": [ 22 | "**/*.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /version-bump.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync, writeFileSync } from "fs"; 2 | 3 | const targetVersion = process.env.npm_package_version; 4 | 5 | // read minAppVersion from manifest.json and bump version to target version 6 | let manifest = JSON.parse(readFileSync("manifest.json", "utf8")); 7 | const { minAppVersion } = manifest; 8 | manifest.version = targetVersion; 9 | writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t")); 10 | 11 | // update versions.json with target version and minAppVersion from manifest.json 12 | let versions = JSON.parse(readFileSync("versions.json", "utf8")); 13 | versions[targetVersion] = minAppVersion; 14 | writeFileSync("versions.json", JSON.stringify(versions, null, "\t")); 15 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "0.5.0": "1.5.0", 3 | "0.5.1": "1.5.0", 4 | "0.6.0": "1.5.0" 5 | } --------------------------------------------------------------------------------