├── .gitignore ├── Gemfile ├── Gemfile.lock ├── HOWTO.md ├── README.md ├── benchmark.js ├── benchmark.py ├── benchmark.rb ├── package-lock.json ├── package.json ├── report.js ├── reports ├── javascript.eno ├── python.eno └── ruby.eno ├── requirements.txt └── samples ├── abstract_hierarchy ├── hierarchy.eno ├── hierarchy.toml └── hierarchy.yaml ├── content_heavy ├── content.eno ├── content.toml └── content.yaml ├── invented_server_configuration ├── configuration.eno ├── configuration.toml └── configuration.yaml ├── jekyll_post_example ├── post.eno ├── post.md ├── post.toml ├── post.yaml └── source.txt ├── journey_route_data ├── journey.eno ├── journey.toml └── journey.yaml └── yaml_invoice_example ├── invoice.eno ├── invoice.toml ├── invoice.yaml └── source.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /composer.phar 2 | /node_modules/ 3 | /vendor/ 4 | /venv/ 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'enolib' 4 | gem 'enotype' 5 | gem 'toml' 6 | gem 'toml-rb' 7 | gem 'tomlrb' 8 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | citrus (3.0.2) 5 | enolib (0.8.1) 6 | enotype (0.3.1) 7 | parslet (2.0.0) 8 | toml (0.3.0) 9 | parslet (>= 1.8.0, < 3.0.0) 10 | toml-rb (2.1.2) 11 | citrus (~> 3.0, > 3.0) 12 | tomlrb (2.0.1) 13 | 14 | PLATFORMS 15 | ruby 16 | 17 | DEPENDENCIES 18 | enolib 19 | enotype 20 | toml 21 | toml-rb 22 | tomlrb 23 | 24 | BUNDLED WITH 25 | 2.3.10 26 | -------------------------------------------------------------------------------- /HOWTO.md: -------------------------------------------------------------------------------- 1 | # How to run it yourself 2 | 3 | You can run all benchmarks yourself, simply follow the steps outlined below. The 4 | `benchmark.*` scripts run the actual benchmarks and collect the results in the 5 | respective `reports/*.eno` files. The actual report (which gets rendered as this 6 | repository's `README.md`) can be generated by the `report.js` script (see last 7 | section). 8 | 9 | ## Benchmarks 10 | 11 | These measure the performance and store the results. 12 | 13 | ### JavaScript 14 | 15 | ```bash 16 | npm i 17 | node benchmark.js 18 | ``` 19 | 20 | ### Python 21 | 22 | ```bash 23 | python -m venv venv 24 | source venv/bin/activate 25 | pip install -r requirements.txt 26 | python benchmark.py 27 | ``` 28 | 29 | ### Ruby 30 | 31 | ```bash 32 | bundle 33 | ruby benchmark.rb 34 | ``` 35 | 36 | ## Report 37 | 38 | This compiles the report itself: 39 | 40 | ```bash 41 | npm i # unless you already ran this 42 | node report.js 43 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # enolib benchmarks 2 | 3 | **Last updated April 30, 2022** 4 | 5 | These benchmarks evaluate the performance of all enolib implementations, 6 | compared also to the most popular yaml/toml parsers out there. As with all 7 | statistics please take these findings with a grain of salt, and feel invited to 8 | re-run these benchmarks or point out flaws and possible improvements to the 9 | methodology and code (some instructions are provided below the results). 10 | 11 | Benchmarks are currently performed on Arch Linux on an Intel® Xeon(R) CPU E5-1650 v3 @ 3.50GHz × 12 (see language sections below for detailed runtime info). 12 | 13 | ## Graphical results 14 | 15 | **[-]** indicates a pure **parsing** run with unsafe results. **(\*)** 16 | 17 | **[✓]** indicates a benchmark for **parsing plus querying and validating** the whole document. **(\*\*)** 18 | 19 | **░░ 0.123** Shorter bars/numbers indicate **better performance**. 20 | 21 | **░░░░░░░░░ 456789** Larger bars/numbers indicate **worse performance**. 22 | 23 | Each ░ represents one second. 24 | 25 | ### JavaScript 26 | 27 | Evaluated in **node v16.14.2 [linux-x64]** on **April 29, 2022**. 28 | 29 | #### *abstract_hierarchy* 30 | 31 |   32 | ``` 33 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 34 | 35 | [-] enolib (git) [] 0.991 seconds 36 | [✓] enolib (git) [▓] 1.355 seconds 37 | [-] js-yaml 4.1.0 [░░] 2.113 seconds 38 | [-] toml-j0.4 1.1.1 [░░░░░] 5.836 seconds 39 | 40 | ... ... OFF THE SCALE 41 | 42 | [-] toml 3.0.0 1+ minutes 43 | ``` 44 | 45 | #### *content_heavy* 46 | 47 |   48 | ``` 49 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 50 | 51 | [✓] enolib (git) [] 0.621 seconds 52 | [-] enolib (git) [] 0.653 seconds 53 | [-] js-yaml 4.1.0 [░░░░░░░░] 8.989 seconds 54 | 55 | ... ... OFF THE SCALE 56 | 57 | [-] toml-j0.4 1.1.1 5+ minutes 58 | [-] toml 3.0.0 166+ minutes 59 | ``` 60 | 61 | #### *invented_server_configuration* 62 | 63 |   64 | ``` 65 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 66 | 67 | [-] enolib (git) [] 0.862 seconds 68 | [✓] enolib (git) [▓] 1.232 seconds 69 | [-] js-yaml 4.1.0 [░░] 2.478 seconds 70 | [-] toml-j0.4 1.1.1 [░░░░░░░░] 8.671 seconds 71 | 72 | ... ... OFF THE SCALE 73 | 74 | [-] toml 3.0.0 3+ minutes 75 | ``` 76 | 77 | #### *jekyll_post_example* 78 | 79 |   80 | ``` 81 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 82 | 83 | [-] enolib (git) [] 0.516 seconds 84 | [✓] enolib (git) [] 0.746 seconds 85 | [-] js-yaml 4.1.0 [░] 1.068 seconds 86 | [-] toml-j0.4 1.1.1 [░░░░░░░░░░░] 11.397 seconds 87 | 88 | ... ... OFF THE SCALE 89 | 90 | [-] toml 3.0.0 3+ minutes 91 | ``` 92 | 93 | #### *journey_route_data* 94 | 95 |   96 | ``` 97 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 98 | 99 | [-] enolib (git) [▓▓] 2.375 seconds 100 | [✓] enolib (git) [▓▓▓] 3.490 seconds 101 | [-] js-yaml 4.1.0 [░░░░] 4.431 seconds 102 | [-] toml-j0.4 1.1.1 [░░░░░░░░░░░░░] 13.878 seconds 103 | 104 | ... ... OFF THE SCALE 105 | 106 | [-] toml 3.0.0 2+ minutes 107 | ``` 108 | 109 | #### *yaml_invoice_example* 110 | 111 |   112 | ``` 113 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 114 | 115 | [-] enolib (git) [▓▓] 2.071 seconds 116 | [-] js-yaml 4.1.0 [░░░] 3.144 seconds 117 | [✓] enolib (git) [▓▓▓] 3.323 seconds 118 | [-] toml-j0.4 1.1.1 [░░░░░░░░░░░] 11.032 seconds 119 | 120 | ... ... OFF THE SCALE 121 | 122 | [-] toml 3.0.0 1+ minutes 123 | ``` 124 | 125 | ### Python 126 | 127 | Evaluated in **CPython 3.10.4 [Linux-5.17.4-arch1-1-x86_64-with-glibc2.35]** on **April 29, 2022**. 128 | 129 | #### *abstract_hierarchy* 130 | 131 |   132 | ``` 133 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 134 | 135 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓] 9.722 seconds 136 | [-] pyyaml (CLoader) 6.0 [░░░░░░░░░░░░] 12.872 seconds 137 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 18.011 seconds 138 | [-] toml 0.10.2 [░░░░░░░░░░░░░░░░░░░░] 20.201 seconds 139 | [-] qtoml 0.3.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 31.738 seconds 140 | [-] ruamel.yaml 0.17.21 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 31.934 seconds 141 | 142 | ... ... OFF THE SCALE 143 | 144 | [-] pyyaml (FullLoader) 6.0 2+ minutes 145 | [-] tomlkit 0.10.2 3+ minutes 146 | ``` 147 | 148 | #### *content_heavy* 149 | 150 |   151 | ``` 152 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 153 | 154 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓] 9.377 seconds 155 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓] 10.980 seconds 156 | [-] pyyaml (CLoader) 6.0 [░░░░░░░░░░░] 11.789 seconds 157 | [-] ruamel.yaml 0.17.21 [░░░░░░░░░░░░░░░░░░░░] 20.965 seconds 158 | 159 | ... ... OFF THE SCALE 160 | 161 | [-] toml 0.10.2 9+ minutes 162 | [-] qtoml 0.3.1 11+ minutes 163 | [-] pyyaml (FullLoader) 6.0 17+ minutes 164 | [-] tomlkit 0.10.2 101+ minutes 165 | ``` 166 | 167 | #### *invented_server_configuration* 168 | 169 |   170 | ``` 171 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 172 | 173 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓] 9.745 seconds 174 | [-] pyyaml (CLoader) 6.0 [░░░░░░░░░░░░░] 13.371 seconds 175 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 23.574 seconds 176 | [-] toml 0.10.2 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 30.444 seconds 177 | [-] ruamel.yaml 0.17.21 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 32.375 seconds 178 | [-] qtoml 0.3.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 49.098 seconds 179 | 180 | ... ... OFF THE SCALE 181 | 182 | [-] pyyaml (FullLoader) 6.0 2+ minutes 183 | [-] tomlkit 0.10.2 5+ minutes 184 | ``` 185 | 186 | #### *jekyll_post_example* 187 | 188 |   189 | ``` 190 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 191 | 192 | [-] enolib 0.8.1 [▓▓▓▓] 4.358 seconds 193 | [-] pyyaml (CLoader) 6.0 [░░░░░] 5.185 seconds 194 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓] 10.486 seconds 195 | [-] ruamel.yaml 0.17.21 [░░░░░░░░░░░░░░░] 15.789 seconds 196 | [-] toml 0.10.2 [░░░░░░░░░░░░░░░░░░░░░░░░░] 25.397 seconds 197 | [-] qtoml 0.3.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 28.791 seconds 198 | 199 | ... ... OFF THE SCALE 200 | 201 | [-] pyyaml (FullLoader) 6.0 1+ minutes 202 | [-] tomlkit 0.10.2 3+ minutes 203 | ``` 204 | 205 | #### *journey_route_data* 206 | 207 |   208 | ``` 209 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 210 | 211 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 22.366 seconds 212 | [-] pyyaml (CLoader) 6.0 [░░░░░░░░░░░░░░░░░░░░░░░░░] 25.494 seconds 213 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 38.252 seconds 214 | [-] toml 0.10.2 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 48.619 seconds 215 | [-] ruamel.yaml 0.17.21 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 57.387 seconds 216 | 217 | ... ... OFF THE SCALE 218 | 219 | [-] qtoml 0.3.1 1+ minutes 220 | [-] pyyaml (FullLoader) 6.0 4+ minutes 221 | [-] tomlkit 0.10.2 6+ minutes 222 | ``` 223 | 224 | #### *yaml_invoice_example* 225 | 226 |   227 | ``` 228 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 229 | 230 | [-] pyyaml (CLoader) 6.0 [░░░░░░░░░░░░░░░░░░░] 19.352 seconds 231 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 20.276 seconds 232 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 35.178 seconds 233 | [-] toml 0.10.2 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 37.578 seconds 234 | [-] ruamel.yaml 0.17.21 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 46.486 seconds 235 | [-] qtoml 0.3.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 56.400 seconds 236 | 237 | ... ... OFF THE SCALE 238 | 239 | [-] pyyaml (FullLoader) 6.0 3+ minutes 240 | [-] tomlkit 0.10.2 5+ minutes 241 | ``` 242 | 243 | ### Ruby 244 | 245 | Evaluated in **ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]** on **April 30, 2022**. 246 | 247 | #### *abstract_hierarchy* 248 | 249 |   250 | ``` 251 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 252 | 253 | [-] enolib 0.8.1 [▓▓▓▓▓▓] 6.566 seconds 254 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓] 11.042 seconds 255 | [-] yaml 3.0.0 [░░░░░░░░░░░] 11.542 seconds 256 | [-] tomlrb 2.0.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 33.200 seconds 257 | 258 | ... ... OFF THE SCALE 259 | 260 | [-] toml-rb 2.1.2 6+ minutes 261 | [-] toml 0.3.0 8+ minutes 262 | ``` 263 | 264 | #### *content_heavy* 265 | 266 |   267 | ``` 268 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 269 | 270 | [-] enolib 0.8.1 [▓▓▓▓▓] 5.882 seconds 271 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓] 7.130 seconds 272 | [-] yaml 3.0.0 [░░░░░░░░░░░░] 12.834 seconds 273 | 274 | ... ... OFF THE SCALE 275 | 276 | [-] tomlrb 2.0.1 1+ minutes 277 | [-] toml-rb 2.1.2 42+ minutes 278 | ``` 279 | 280 | #### *invented_server_configuration* 281 | 282 |   283 | ``` 284 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 285 | 286 | [-] enolib 0.8.1 [▓▓▓▓▓▓] 6.806 seconds 287 | [-] yaml 3.0.0 [░░░░░░░░░░░░] 12.082 seconds 288 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 15.213 seconds 289 | [-] tomlrb 2.0.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 58.850 seconds 290 | 291 | ... ... OFF THE SCALE 292 | 293 | [-] toml-rb 2.1.2 10+ minutes 294 | [-] toml 0.3.0 14+ minutes 295 | ``` 296 | 297 | #### *jekyll_post_example* 298 | 299 |   300 | ``` 301 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 302 | 303 | [-] enolib 0.8.1 [▓▓▓▓▓] 5.189 seconds 304 | [-] yaml 3.0.0 [░░░░░░░] 7.283 seconds 305 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓] 8.222 seconds 306 | [-] tomlrb 2.0.1 [░░░░░░░░░░░] 11.753 seconds 307 | ``` 308 | 309 | #### *journey_route_data* 310 | 311 |   312 | ``` 313 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 314 | 315 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 14.216 seconds 316 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 23.535 seconds 317 | [-] yaml 3.0.0 [░░░░░░░░░░░░░░░░░░░░░░░░░] 25.262 seconds 318 | 319 | ... ... OFF THE SCALE 320 | 321 | [-] tomlrb 2.0.1 1+ minutes 322 | [-] toml 0.3.0 18+ minutes 323 | ``` 324 | 325 | #### *yaml_invoice_example* 326 | 327 |   328 | ``` 329 | VAL LIBRARY NUMBER OF SECONDS FOR 100K (***) ITERATIONS 330 | 331 | [-] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 17.903 seconds 332 | [-] yaml 3.0.0 [░░░░░░░░░░░░░░░░░░] 18.520 seconds 333 | [✓] enolib 0.8.1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 28.548 seconds 334 | [-] tomlrb 2.0.1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 53.659 seconds 335 | ``` 336 | 337 | ## Numerical results 338 | 339 | **[-]** indicates a pure **parsing** run with unsafe results. **(\*)** 340 | 341 | **[✓]** indicates a benchmark for **parsing plus querying and validating** the whole document. **(\*\*)** 342 | 343 | **0.123** Smaller numbers indicate **better performance**. 344 | 345 | **4565789** Larger numbers indicate **worse performance**. 346 | 347 | 348 | ### JavaScript 349 | 350 | Evaluated in **node v16.14.2 [linux-x64]** on **April 29, 2022**. 351 | 352 | #### *abstract_hierarchy* 353 | 354 | | Library | Number of seconds for 100k (***) iterations | 355 | | ------- | ------------------------------------- | 356 | | **[-] enolib (git)** | **0.991** | 357 | | **[✓] enolib (git)** | **1.355** | 358 | | [-] js-yaml 4.1.0 | 2.113 | 359 | | [-] toml-j0.4 1.1.1 | 5.836 | 360 | | [-] toml 3.0.0 | 86.159 | 361 | 362 | #### *content_heavy* 363 | 364 | | Library | Number of seconds for 100k (***) iterations | 365 | | ------- | ------------------------------------- | 366 | | **[✓] enolib (git)** | **0.621** | 367 | | **[-] enolib (git)** | **0.653** | 368 | | [-] js-yaml 4.1.0 | 8.989 | 369 | | [-] toml-j0.4 1.1.1 | 322.459 | 370 | | [-] toml 3.0.0 | 9945.710 | 371 | 372 | #### *invented_server_configuration* 373 | 374 | | Library | Number of seconds for 100k (***) iterations | 375 | | ------- | ------------------------------------- | 376 | | **[-] enolib (git)** | **0.862** | 377 | | **[✓] enolib (git)** | **1.232** | 378 | | [-] js-yaml 4.1.0 | 2.478 | 379 | | [-] toml-j0.4 1.1.1 | 8.671 | 380 | | [-] toml 3.0.0 | 155.783 | 381 | 382 | #### *jekyll_post_example* 383 | 384 | | Library | Number of seconds for 100k (***) iterations | 385 | | ------- | ------------------------------------- | 386 | | **[-] enolib (git)** | **0.516** | 387 | | **[✓] enolib (git)** | **0.746** | 388 | | [-] js-yaml 4.1.0 | 1.068 | 389 | | [-] toml-j0.4 1.1.1 | 11.397 | 390 | | [-] toml 3.0.0 | 204.921 | 391 | 392 | #### *journey_route_data* 393 | 394 | | Library | Number of seconds for 100k (***) iterations | 395 | | ------- | ------------------------------------- | 396 | | **[-] enolib (git)** | **2.375** | 397 | | **[✓] enolib (git)** | **3.490** | 398 | | [-] js-yaml 4.1.0 | 4.431 | 399 | | [-] toml-j0.4 1.1.1 | 13.878 | 400 | | [-] toml 3.0.0 | 132.145 | 401 | 402 | #### *yaml_invoice_example* 403 | 404 | | Library | Number of seconds for 100k (***) iterations | 405 | | ------- | ------------------------------------- | 406 | | **[-] enolib (git)** | **2.071** | 407 | | [-] js-yaml 4.1.0 | 3.144 | 408 | | **[✓] enolib (git)** | **3.323** | 409 | | [-] toml-j0.4 1.1.1 | 11.032 | 410 | | [-] toml 3.0.0 | 75.226 | 411 | 412 | ### Python 413 | 414 | Evaluated in **CPython 3.10.4 [Linux-5.17.4-arch1-1-x86_64-with-glibc2.35]** on **April 29, 2022**. 415 | 416 | #### *abstract_hierarchy* 417 | 418 | | Library | Number of seconds for 100k (***) iterations | 419 | | ------- | ------------------------------------- | 420 | | **[-] enolib 0.8.1** | **9.722** | 421 | | [-] pyyaml (CLoader) 6.0 | 12.872 | 422 | | **[✓] enolib 0.8.1** | **18.011** | 423 | | [-] toml 0.10.2 | 20.201 | 424 | | [-] qtoml 0.3.1 | 31.738 | 425 | | [-] ruamel.yaml 0.17.21 | 31.934 | 426 | | [-] pyyaml (FullLoader) 6.0 | 128.326 | 427 | | [-] tomlkit 0.10.2 | 150.259 | 428 | 429 | #### *content_heavy* 430 | 431 | | Library | Number of seconds for 100k (***) iterations | 432 | | ------- | ------------------------------------- | 433 | | **[-] enolib 0.8.1** | **9.377** | 434 | | **[✓] enolib 0.8.1** | **10.980** | 435 | | [-] pyyaml (CLoader) 6.0 | 11.789 | 436 | | [-] ruamel.yaml 0.17.21 | 20.965 | 437 | | [-] toml 0.10.2 | 567.749 | 438 | | [-] qtoml 0.3.1 | 632.328 | 439 | | [-] pyyaml (FullLoader) 6.0 | 1016.106 | 440 | | [-] tomlkit 0.10.2 | 6078.838 | 441 | 442 | #### *invented_server_configuration* 443 | 444 | | Library | Number of seconds for 100k (***) iterations | 445 | | ------- | ------------------------------------- | 446 | | **[-] enolib 0.8.1** | **9.745** | 447 | | [-] pyyaml (CLoader) 6.0 | 13.371 | 448 | | **[✓] enolib 0.8.1** | **23.574** | 449 | | [-] toml 0.10.2 | 30.444 | 450 | | [-] ruamel.yaml 0.17.21 | 32.375 | 451 | | [-] qtoml 0.3.1 | 49.098 | 452 | | [-] pyyaml (FullLoader) 6.0 | 128.064 | 453 | | [-] tomlkit 0.10.2 | 275.489 | 454 | 455 | #### *jekyll_post_example* 456 | 457 | | Library | Number of seconds for 100k (***) iterations | 458 | | ------- | ------------------------------------- | 459 | | **[-] enolib 0.8.1** | **4.358** | 460 | | [-] pyyaml (CLoader) 6.0 | 5.185 | 461 | | **[✓] enolib 0.8.1** | **10.486** | 462 | | [-] ruamel.yaml 0.17.21 | 15.789 | 463 | | [-] toml 0.10.2 | 25.397 | 464 | | [-] qtoml 0.3.1 | 28.791 | 465 | | [-] pyyaml (FullLoader) 6.0 | 69.788 | 466 | | [-] tomlkit 0.10.2 | 196.152 | 467 | 468 | #### *journey_route_data* 469 | 470 | | Library | Number of seconds for 100k (***) iterations | 471 | | ------- | ------------------------------------- | 472 | | **[-] enolib 0.8.1** | **22.366** | 473 | | [-] pyyaml (CLoader) 6.0 | 25.494 | 474 | | **[✓] enolib 0.8.1** | **38.252** | 475 | | [-] toml 0.10.2 | 48.619 | 476 | | [-] ruamel.yaml 0.17.21 | 57.387 | 477 | | [-] qtoml 0.3.1 | 72.072 | 478 | | [-] pyyaml (FullLoader) 6.0 | 262.894 | 479 | | [-] tomlkit 0.10.2 | 383.605 | 480 | 481 | #### *yaml_invoice_example* 482 | 483 | | Library | Number of seconds for 100k (***) iterations | 484 | | ------- | ------------------------------------- | 485 | | [-] pyyaml (CLoader) 6.0 | 19.352 | 486 | | **[-] enolib 0.8.1** | **20.276** | 487 | | **[✓] enolib 0.8.1** | **35.178** | 488 | | [-] toml 0.10.2 | 37.578 | 489 | | [-] ruamel.yaml 0.17.21 | 46.486 | 490 | | [-] qtoml 0.3.1 | 56.400 | 491 | | [-] pyyaml (FullLoader) 6.0 | 186.652 | 492 | | [-] tomlkit 0.10.2 | 305.260 | 493 | 494 | ### Ruby 495 | 496 | Evaluated in **ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]** on **April 30, 2022**. 497 | 498 | #### *abstract_hierarchy* 499 | 500 | | Library | Number of seconds for 100k (***) iterations | 501 | | ------- | ------------------------------------- | 502 | | **[-] enolib 0.8.1** | **6.566** | 503 | | **[✓] enolib 0.8.1** | **11.042** | 504 | | [-] yaml 3.0.0 | 11.542 | 505 | | [-] tomlrb 2.0.1 | 33.200 | 506 | | [-] toml-rb 2.1.2 | 370.530 | 507 | | [-] toml 0.3.0 | 501.418 | 508 | 509 | #### *content_heavy* 510 | 511 | | Library | Number of seconds for 100k (***) iterations | 512 | | ------- | ------------------------------------- | 513 | | **[-] enolib 0.8.1** | **5.882** | 514 | | **[✓] enolib 0.8.1** | **7.130** | 515 | | [-] yaml 3.0.0 | 12.834 | 516 | | [-] tomlrb 2.0.1 | 61.495 | 517 | | [-] toml-rb 2.1.2 | 2508.009 | 518 | 519 | #### *invented_server_configuration* 520 | 521 | | Library | Number of seconds for 100k (***) iterations | 522 | | ------- | ------------------------------------- | 523 | | **[-] enolib 0.8.1** | **6.806** | 524 | | [-] yaml 3.0.0 | 12.082 | 525 | | **[✓] enolib 0.8.1** | **15.213** | 526 | | [-] tomlrb 2.0.1 | 58.850 | 527 | | [-] toml-rb 2.1.2 | 623.452 | 528 | | [-] toml 0.3.0 | 828.296 | 529 | 530 | #### *jekyll_post_example* 531 | 532 | | Library | Number of seconds for 100k (***) iterations | 533 | | ------- | ------------------------------------- | 534 | | **[-] enolib 0.8.1** | **5.189** | 535 | | [-] yaml 3.0.0 | 7.283 | 536 | | **[✓] enolib 0.8.1** | **8.222** | 537 | | [-] tomlrb 2.0.1 | 11.753 | 538 | 539 | #### *journey_route_data* 540 | 541 | | Library | Number of seconds for 100k (***) iterations | 542 | | ------- | ------------------------------------- | 543 | | **[-] enolib 0.8.1** | **14.216** | 544 | | **[✓] enolib 0.8.1** | **23.535** | 545 | | [-] yaml 3.0.0 | 25.262 | 546 | | [-] tomlrb 2.0.1 | 61.633 | 547 | | [-] toml 0.3.0 | 1098.928 | 548 | 549 | #### *yaml_invoice_example* 550 | 551 | | Library | Number of seconds for 100k (***) iterations | 552 | | ------- | ------------------------------------- | 553 | | **[-] enolib 0.8.1** | **17.903** | 554 | | [-] yaml 3.0.0 | 18.520 | 555 | | **[✓] enolib 0.8.1** | **28.548** | 556 | | [-] tomlrb 2.0.1 | 53.659 | 557 | 558 | --- 559 | 560 | ## How the data is gathered 561 | 562 | To see how the measurements were obtained, please take a look at the source of `benchmark.js/py/rb` inside this repository. 563 | To see how the report was compiled, please study `report.js` inside this repository. 564 | 565 | 566 | ## Notes 567 | 568 | As you might have noticed, the benchmark figures for ruby are occasionally 569 | missing one or two libraries for specific benchmarks – the reason for this is 570 | simply that these libraries failed on those respective benchmarks, either by 571 | raising an error or even by segfaulting. 572 | 573 | **(\*)**: The majority of YAML/TOML parsers produce plain object dumps which are inherently unvalidated. 574 | 575 | **(\*\*)**: In the enolib libraries a document is validated through querying. 576 | If the whole document is queried, the whole document is validated. If only a portion of the document is queried 577 | less validation and less memory allocation happens and the performance thereby increases too. The results displayed 578 | here represent the (performance-wise worst) case of using all data present in a document. 579 | 580 | **(\*\*\*)**: Some libraries included in the benchmarks exhibit an up to 1000x 581 | slower performance compared to the top ranking parsers, these have been 582 | partially sampled with up to only 1k iterations, with the total duration 583 | extrapolated for the global comparison again. 584 | -------------------------------------------------------------------------------- /benchmark.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { performance } from 'perf_hooks'; 4 | import { parse, register } from 'enolib'; 5 | import { boolean, date, datetime, float, integer } from 'enotype'; 6 | import jsYaml from 'js-yaml'; 7 | import toml from 'toml'; 8 | import tomlJ04 from 'toml-j0.4'; 9 | 10 | const enolibVersion = JSON.parse(fs.readFileSync('./node_modules/enolib/package.json', 'utf-8')).version; 11 | const jsYamlVersion = JSON.parse(fs.readFileSync('./node_modules/js-yaml/package.json', 'utf-8')).version; 12 | const tomlVersion = JSON.parse(fs.readFileSync('./node_modules/toml/package.json', 'utf-8')).version; 13 | const tomlJ04Version = JSON.parse(fs.readFileSync('./node_modules/toml-j0.4/package.json', 'utf-8')).version; 14 | 15 | const ITERATIONS = 100000; 16 | 17 | register({ boolean, date, datetime, float, integer }); 18 | 19 | let enoInput, mdInput, tomlInput, yamlInput; 20 | 21 | let report = ` 22 | evaluated: ${(new Date()).toISOString().replace(/\.[0-9]{3}/, '')} 23 | iterations: ${ITERATIONS} 24 | runtime: node ${process.version} [${process.platform}-${process.arch}] 25 | 26 | # scenarios 27 | `.trimStart(); 28 | 29 | const scenario = (file) => { 30 | report += `\n${file}:\n`; 31 | 32 | console.log(file); 33 | }; 34 | 35 | const benchmark = (library, version, perform, iteration_cutback_factor = 1) => { 36 | const iterations = ITERATIONS / iteration_cutback_factor; 37 | 38 | const before = performance.now(); 39 | for (let i = 0; i < iterations; i++) 40 | perform(); 41 | const after = performance.now(); 42 | 43 | const duration = ((after - before) / 1000.0); 44 | const durationNormalized = duration * iteration_cutback_factor; 45 | 46 | report += `${library} ${version} = ${durationNormalized}\n`; 47 | 48 | if (iteration_cutback_factor > 1) { 49 | console.log(`\x1b[33m${library} - ${iterations / 1000}k iterations => ${duration} seconds / ${durationNormalized} normalized seconds\x1b[0m`); 50 | } else { 51 | console.log(`${library} - ${iterations / 1000}k iterations => ${duration} seconds / ${durationNormalized} normalized seconds`); 52 | } 53 | }; 54 | 55 | 56 | scenario('abstract_hierarchy'); 57 | 58 | const enoHierarchy = fs.readFileSync(path.resolve('samples/abstract_hierarchy/hierarchy.eno'), 'utf-8'); 59 | const yamlHierarchy = fs.readFileSync(path.resolve('samples/abstract_hierarchy/hierarchy.yaml'), 'utf-8'); 60 | const tomlHierarchy = fs.readFileSync(path.resolve('samples/abstract_hierarchy/hierarchy.toml'), 'utf-8'); 61 | 62 | benchmark('[-] enolib', enolibVersion, () => parse(enoHierarchy)); 63 | benchmark('[✓] enolib', enolibVersion, () => { 64 | const document = parse(enoHierarchy); 65 | const doc = document.section('doc'); 66 | doc.field('colors').requiredStringValues(); 67 | const traits = doc.field('traits'); 68 | traits.attribute('tired').requiredStringValue(); 69 | traits.attribute('extroverted').requiredStringValue(); 70 | traits.attribute('funny').requiredStringValue(); 71 | traits.attribute('inventive').requiredStringValue(); 72 | doc.field('things').requiredStringValues(); 73 | const deep = doc.section('deep'); 74 | deep.field('sea').requiredStringValue(); 75 | const deeper = deep.section('deep'); 76 | deeper.field('sea').requiredStringValue(); 77 | const deepest = deeper.section('deep'); 78 | deepest.field('sea').requiredStringValue(); 79 | }); 80 | benchmark('[-] js-yaml', jsYamlVersion, () => jsYaml.load(yamlHierarchy)); 81 | benchmark('[-] toml', tomlVersion, () => toml.parse(tomlHierarchy), 10); 82 | benchmark('[-] toml-j0.4', tomlJ04Version, () => tomlJ04.parse(tomlHierarchy)); 83 | 84 | 85 | scenario('content_heavy'); 86 | 87 | const enoContent = fs.readFileSync(path.resolve('samples/content_heavy/content.eno'), 'utf-8'); 88 | const yamlContent = fs.readFileSync(path.resolve('samples/content_heavy/content.yaml'), 'utf-8'); 89 | const tomlContent = fs.readFileSync(path.resolve('samples/content_heavy/content.toml'), 'utf-8'); 90 | 91 | benchmark('[-] enolib', enolibVersion, () => parse(enoContent)); 92 | benchmark('[✓] enolib', enolibVersion, () => { 93 | parse(enoContent).embed('content').requiredStringValue(); 94 | }); 95 | benchmark('[-] js-yaml', jsYamlVersion, () => jsYaml.load(yamlContent)); 96 | benchmark('[-] toml', tomlVersion, () => toml.parse(tomlContent), 100); 97 | benchmark('[-] toml-j0.4', tomlJ04Version, () => tomlJ04.parse(tomlContent), 10); 98 | 99 | 100 | scenario('invented_server_configuration'); 101 | 102 | const enoConfiguration = fs.readFileSync(path.resolve('samples/invented_server_configuration/configuration.eno'), 'utf-8'); 103 | const yamlConfiguration = fs.readFileSync(path.resolve('samples/invented_server_configuration/configuration.yaml'), 'utf-8'); 104 | const tomlConfiguration = fs.readFileSync(path.resolve('samples/invented_server_configuration/configuration.toml'), 'utf-8'); 105 | 106 | benchmark('[-] enolib', enolibVersion, () => parse(enoConfiguration)); 107 | benchmark('[✓] enolib', enolibVersion, () => { 108 | const document = parse(enoConfiguration); 109 | for (const environment of document.sections()) { 110 | for (const server of environment.sections()) { 111 | const conf = server.field('conf'); 112 | conf.attribute('ruby').requiredBooleanValue(); 113 | conf.attribute('python').requiredBooleanValue(); 114 | server.field('clean').requiredBooleanValue(); 115 | server.field('steps').requiredStringValues(); 116 | } 117 | } 118 | }); 119 | benchmark('[-] js-yaml', jsYamlVersion, () => jsYaml.load(yamlConfiguration)); 120 | benchmark('[-] toml', tomlVersion, () => toml.parse(tomlConfiguration), 10); 121 | benchmark('[-] toml-j0.4', tomlJ04Version, () => tomlJ04.parse(tomlConfiguration)); 122 | 123 | 124 | scenario('jekyll_post_example'); 125 | 126 | const enoPost = fs.readFileSync(path.resolve('samples/jekyll_post_example/post.eno'), 'utf-8'); 127 | const tomlPost = fs.readFileSync(path.resolve('samples/jekyll_post_example/post.toml'), 'utf-8'); 128 | const yamlPost = fs.readFileSync(path.resolve('samples/jekyll_post_example/post.yaml'), 'utf-8'); 129 | 130 | benchmark('[-] enolib', enolibVersion, () => parse(enoPost)); 131 | benchmark('[✓] enolib', enolibVersion, () => { 132 | const document = parse(enoPost); 133 | document.field('layout').requiredStringValue(); 134 | document.field('title').requiredStringValue(); 135 | document.field('date').requiredDatetimeValue(); 136 | document.field('categories').requiredStringValue(); 137 | document.embed('markdown').requiredStringValue(); 138 | }); 139 | benchmark('[-] js-yaml', jsYamlVersion, () => jsYaml.load(yamlPost)); 140 | benchmark('[-] toml', tomlVersion, () => toml.parse(tomlPost), 10); 141 | benchmark('[-] toml-j0.4', tomlJ04Version, () => tomlJ04.parse(tomlPost)); 142 | 143 | 144 | scenario('journey_route_data'); 145 | 146 | const enoJourney = fs.readFileSync(path.resolve('samples/journey_route_data/journey.eno'), 'utf-8'); 147 | const yamlJourney = fs.readFileSync(path.resolve('samples/journey_route_data/journey.yaml'), 'utf-8'); 148 | const tomlJourney = fs.readFileSync(path.resolve('samples/journey_route_data/journey.toml'), 'utf-8'); 149 | 150 | benchmark('[-] enolib', enolibVersion, () => parse(enoJourney)); 151 | benchmark('[✓] enolib', enolibVersion, () => { 152 | const document = parse(enoJourney); 153 | document.field('title').requiredStringValue(); 154 | document.field('date').requiredDateValue(); 155 | document.field('time').requiredStringValue(); 156 | document.field('abstract').requiredStringValue(); 157 | for (const checkpoint of document.sections('checkpoint')) { 158 | checkpoint.field('coordinates').requiredStringValue(); 159 | checkpoint.field('hint').optionalStringValue(); 160 | checkpoint.field('special').optionalStringValue(); 161 | checkpoint.field('location').requiredStringValue(); 162 | const safezone = checkpoint.optionalSection('safezone'); 163 | if (safezone) { 164 | safezone.field('shape').requiredStringValue(); 165 | safezone.field('center').requiredStringValue(); 166 | safezone.field('radius').requiredIntegerValue(); 167 | } 168 | } 169 | }); 170 | benchmark('[-] js-yaml', jsYamlVersion, () => jsYaml.load(yamlJourney)); 171 | benchmark('[-] toml', tomlVersion, () => toml.parse(tomlJourney), 10); 172 | benchmark('[-] toml-j0.4', tomlJ04Version, () => tomlJ04.parse(tomlJourney)); 173 | 174 | 175 | scenario('yaml_invoice_example'); 176 | 177 | const enoInvoice = fs.readFileSync(path.resolve('samples/yaml_invoice_example/invoice.eno'), 'utf-8'); 178 | const yamlInvoice = fs.readFileSync(path.resolve('samples/yaml_invoice_example/invoice.yaml'), 'utf-8'); 179 | const tomlInvoice = fs.readFileSync(path.resolve('samples/yaml_invoice_example/invoice.toml'), 'utf-8'); 180 | 181 | benchmark('[-] enolib', enolibVersion, () => parse(enoInvoice)); 182 | benchmark('[✓] enolib', enolibVersion, () => { 183 | const document = parse(enoInvoice); 184 | document.field('invoice').requiredIntegerValue(); 185 | document.field('date').requiredDateValue(); 186 | document.field('tax').requiredFloatValue(); 187 | document.field('total').requiredFloatValue(); 188 | document.embed('comments').requiredStringValue(); 189 | for (const type of ['bill-to', 'ship-to']) { 190 | const contact = document.section(type); 191 | contact.field('given').requiredStringValue(); 192 | contact.field('family').requiredStringValue(); 193 | const address = contact.section('address'); 194 | address.embed('lines').requiredStringValue(); 195 | address.field('city').requiredStringValue(); 196 | address.field('state').requiredStringValue(); 197 | address.field('postal').requiredStringValue(); 198 | } 199 | for (const product of document.sections('product')) { 200 | product.field('sku').requiredStringValue(); 201 | product.field('quantity').requiredIntegerValue(); 202 | product.field('description').requiredStringValue(); 203 | product.field('price').requiredStringValue(); 204 | } 205 | }); 206 | benchmark('[-] js-yaml', jsYamlVersion, () => jsYaml.load(yamlInvoice)); 207 | benchmark('[-] toml', tomlVersion, () => toml.parse(tomlInvoice)); 208 | benchmark('[-] toml-j0.4', tomlJ04Version, () => tomlJ04.parse(tomlInvoice)); 209 | 210 | 211 | fs.writeFileSync(path.resolve('reports/javascript.eno'), report); 212 | -------------------------------------------------------------------------------- /benchmark.py: -------------------------------------------------------------------------------- 1 | import pkg_resources 2 | from datetime import datetime as python_datetime, timezone 3 | from platform import platform, python_implementation, python_version 4 | from timeit import default_timer 5 | 6 | import enolib 7 | ENOLIB_VERSION = pkg_resources.get_distribution('enolib').version 8 | 9 | from enotype import boolean, date, datetime, float, integer 10 | enolib.register(boolean, date, datetime, float, integer) 11 | 12 | import qtoml 13 | QTOML_VERSION = pkg_resources.get_distribution('qtoml').version 14 | 15 | import toml 16 | TOML_VERSION = pkg_resources.get_distribution('toml').version 17 | 18 | import tomlkit 19 | TOMLKIT_VERSION = pkg_resources.get_distribution('tomlkit').version 20 | 21 | import yaml 22 | PYYAML_VERSION = pkg_resources.get_distribution('pyyaml').version 23 | 24 | from ruamel.yaml import YAML 25 | ruamel = YAML(typ='safe') 26 | RUAMEL_YAML_VERSION = pkg_resources.get_distribution('ruamel.yaml').version 27 | 28 | class PythonReport: 29 | ITERATIONS = 100000 30 | 31 | def __init__(self): 32 | self.report = f""" 33 | evaluated: {python_datetime.utcnow().replace(microsecond=0, tzinfo=timezone.utc).isoformat()} 34 | iterations: {self.ITERATIONS} 35 | runtime: {python_implementation()} {python_version()} [{platform()}] 36 | 37 | # scenarios 38 | """.lstrip() 39 | 40 | def generate(self): 41 | self.scenario('abstract_hierarchy') 42 | 43 | with open('samples/abstract_hierarchy/hierarchy.eno') as file: 44 | eno_hierarchy = file.read() 45 | with open('samples/abstract_hierarchy/hierarchy.toml') as file: 46 | toml_hierarchy = file.read() 47 | with open('samples/abstract_hierarchy/hierarchy.yaml') as file: 48 | yaml_hierarchy = file.read() 49 | 50 | def eno_hierarchy_query(): 51 | document = enolib.parse(eno_hierarchy) 52 | doc = document.section('doc') 53 | doc.list('colors').required_string_values() 54 | traits = doc.fieldset('traits') 55 | traits.entry('tired').required_string_value() 56 | traits.entry('extroverted').required_string_value() 57 | traits.entry('funny').required_string_value() 58 | traits.entry('inventive').required_string_value() 59 | doc.list('things').required_string_values() 60 | deep = doc.section('deep') 61 | deep.field('sea').required_string_value() 62 | deeper = deep.section('deep') 63 | deeper.field('sea').required_string_value() 64 | deepest = deeper.section('deep') 65 | deepest.field('sea').required_string_value() 66 | 67 | self.benchmark('[-] enolib', ENOLIB_VERSION, lambda: enolib.parse(eno_hierarchy)) 68 | self.benchmark('[✓] enolib', ENOLIB_VERSION, eno_hierarchy_query) 69 | self.benchmark('[-] pyyaml (FullLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_hierarchy, Loader=yaml.FullLoader), 10) 70 | self.benchmark('[-] pyyaml (CLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_hierarchy, Loader=yaml.CLoader)) 71 | self.benchmark('[-] qtoml', QTOML_VERSION, lambda: qtoml.loads(toml_hierarchy)) 72 | self.benchmark('[-] ruamel.yaml', RUAMEL_YAML_VERSION, lambda: ruamel.load(yaml_hierarchy)) 73 | self.benchmark('[-] toml', TOML_VERSION, lambda: toml.loads(toml_hierarchy)) 74 | self.benchmark('[-] tomlkit', TOMLKIT_VERSION, lambda: tomlkit.parse(toml_hierarchy), 10) 75 | 76 | 77 | self.scenario('content_heavy') 78 | 79 | with open('samples/content_heavy/content.eno') as file: 80 | eno_content = file.read() 81 | with open('samples/content_heavy/content.toml') as file: 82 | toml_content = file.read() 83 | with open('samples/content_heavy/content.yaml') as file: 84 | yaml_content = file.read() 85 | 86 | def eno_content_query(): 87 | enolib.parse(eno_content).field('content').required_string_value() 88 | 89 | self.benchmark('[-] enolib', ENOLIB_VERSION, lambda: enolib.parse(eno_content)) 90 | self.benchmark('[✓] enolib', ENOLIB_VERSION, eno_content_query) 91 | self.benchmark('[-] pyyaml (FullLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_content, Loader=yaml.FullLoader), 100) 92 | self.benchmark('[-] pyyaml (CLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_content, Loader=yaml.CLoader)) 93 | self.benchmark('[-] qtoml', QTOML_VERSION, lambda: qtoml.loads(toml_content), 100) 94 | self.benchmark('[-] ruamel.yaml', RUAMEL_YAML_VERSION, lambda: ruamel.load(yaml_content)) 95 | self.benchmark('[-] toml', TOML_VERSION, lambda: toml.loads(toml_content), 10) 96 | self.benchmark('[-] tomlkit', TOMLKIT_VERSION, lambda: tomlkit.parse(toml_content), 100) 97 | 98 | 99 | self.scenario('invented_server_configuration') 100 | 101 | with open('samples/invented_server_configuration/configuration.eno') as file: 102 | eno_configuration = file.read() 103 | with open('samples/invented_server_configuration/configuration.toml') as file: 104 | toml_configuration = file.read() 105 | with open('samples/invented_server_configuration/configuration.yaml') as file: 106 | yaml_configuration = file.read() 107 | 108 | def eno_configuration_query(): 109 | document = enolib.parse(eno_configuration) 110 | for environment in document.sections(): 111 | for server in environment.sections(): 112 | conf = server.fieldset('conf') 113 | conf.entry('ruby').required_boolean_value() 114 | conf.entry('python').required_boolean_value() 115 | server.field('clean').required_boolean_value() 116 | server.list('steps').required_string_values() 117 | 118 | self.benchmark('[-] enolib', ENOLIB_VERSION, lambda: enolib.parse(eno_configuration)) 119 | self.benchmark('[✓] enolib', ENOLIB_VERSION, eno_configuration_query) 120 | self.benchmark('[-] pyyaml (FullLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_configuration, Loader=yaml.FullLoader), 10) 121 | self.benchmark('[-] pyyaml (CLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_configuration, Loader=yaml.CLoader)) 122 | self.benchmark('[-] qtoml', QTOML_VERSION, lambda: qtoml.loads(toml_configuration)) 123 | self.benchmark('[-] ruamel.yaml', RUAMEL_YAML_VERSION, lambda: ruamel.load(yaml_configuration)) 124 | self.benchmark('[-] toml', TOML_VERSION, lambda: toml.loads(toml_configuration)) 125 | self.benchmark('[-] tomlkit', TOMLKIT_VERSION, lambda: tomlkit.parse(toml_configuration), 10) 126 | 127 | self.scenario('jekyll_post_example') 128 | 129 | with open('samples/jekyll_post_example/post.eno') as file: 130 | eno_post = file.read() 131 | with open('samples/jekyll_post_example/post.toml') as file: 132 | toml_post = file.read() 133 | with open('samples/jekyll_post_example/post.yaml') as file: 134 | yaml_post = file.read() 135 | 136 | def eno_post_query(): 137 | document = enolib.parse(eno_post) 138 | document.field('layout').required_string_value() 139 | document.field('title').required_string_value() 140 | document.field('date').required_datetime_value() 141 | document.field('categories').required_string_value() 142 | document.field('markdown').required_string_value() 143 | 144 | self.benchmark('[-] enolib', ENOLIB_VERSION, lambda: enolib.parse(eno_post)) 145 | self.benchmark('[✓] enolib', ENOLIB_VERSION, eno_post_query) 146 | self.benchmark('[-] pyyaml (FullLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_post, Loader=yaml.FullLoader), 10) 147 | self.benchmark('[-] pyyaml (CLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_post, Loader=yaml.CLoader)) 148 | self.benchmark('[-] qtoml', QTOML_VERSION, lambda: qtoml.loads(toml_post)) 149 | self.benchmark('[-] ruamel.yaml', RUAMEL_YAML_VERSION, lambda: ruamel.load(yaml_post)) 150 | self.benchmark('[-] toml', TOML_VERSION, lambda: toml.loads(toml_post)) 151 | self.benchmark('[-] tomlkit', TOMLKIT_VERSION, lambda: tomlkit.parse(toml_post), 10) 152 | 153 | self.scenario('journey_route_data') 154 | 155 | with open('samples/journey_route_data/journey.eno') as file: 156 | eno_journey = file.read() 157 | with open('samples/journey_route_data/journey.toml') as file: 158 | toml_journey = file.read() 159 | with open('samples/journey_route_data/journey.yaml') as file: 160 | yaml_journey = file.read() 161 | 162 | def eno_journey_query(): 163 | document = enolib.parse(eno_journey) 164 | document.field('title').required_string_value() 165 | document.field('date').required_date_value() 166 | document.field('time').required_string_value() 167 | document.field('abstract').required_string_value() 168 | for checkpoint in document.sections('checkpoint'): 169 | checkpoint.field('coordinates').required_string_value() 170 | checkpoint.field('hint').optional_string_value() 171 | checkpoint.field('special').optional_string_value() 172 | checkpoint.field('location').required_string_value() 173 | safezone = checkpoint.optional_section('safezone') 174 | if safezone: 175 | safezone.field('shape').required_string_value() 176 | safezone.field('center').required_string_value() 177 | safezone.field('radius').required_integer_value() 178 | 179 | self.benchmark('[-] enolib', ENOLIB_VERSION, lambda: enolib.parse(eno_journey)) 180 | self.benchmark('[✓] enolib', ENOLIB_VERSION, eno_journey_query) 181 | self.benchmark('[-] pyyaml (FullLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_journey, Loader=yaml.FullLoader), 10) 182 | self.benchmark('[-] pyyaml (CLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_journey, Loader=yaml.CLoader)) 183 | self.benchmark('[-] qtoml', QTOML_VERSION, lambda: qtoml.loads(toml_journey), 10) 184 | self.benchmark('[-] ruamel.yaml', RUAMEL_YAML_VERSION, lambda: ruamel.load(yaml_journey), 10) 185 | self.benchmark('[-] toml', TOML_VERSION, lambda: toml.loads(toml_journey)) 186 | self.benchmark('[-] tomlkit', TOMLKIT_VERSION, lambda: tomlkit.parse(toml_journey), 10) 187 | 188 | self.scenario('yaml_invoice_example') 189 | 190 | with open('samples/yaml_invoice_example/invoice.eno') as file: 191 | eno_invoice = file.read() 192 | with open('samples/yaml_invoice_example/invoice.toml') as file: 193 | toml_invoice = file.read() 194 | with open('samples/yaml_invoice_example/invoice.yaml') as file: 195 | yaml_invoice = file.read() 196 | 197 | def eno_invoice_query(): 198 | document = enolib.parse(eno_invoice) 199 | document.field('invoice').required_integer_value() 200 | document.field('date').required_date_value() 201 | document.field('tax').required_float_value() 202 | document.field('total').required_float_value() 203 | document.field('comments').required_string_value() 204 | for type in ['bill-to', 'ship-to']: 205 | contact = document.section(type) 206 | contact.field('given').required_string_value() 207 | contact.field('family').required_string_value() 208 | address = contact.section('address') 209 | address.field('lines').required_string_value() 210 | address.field('city').required_string_value() 211 | address.field('state').required_string_value() 212 | address.field('postal').required_string_value() 213 | for product in document.sections('product'): 214 | product.field('sku').required_string_value() 215 | product.field('quantity').required_integer_value() 216 | product.field('description').required_string_value() 217 | product.field('price').required_string_value() 218 | 219 | self.benchmark('[-] enolib', ENOLIB_VERSION, lambda: enolib.parse(eno_invoice)) 220 | self.benchmark('[✓] enolib', ENOLIB_VERSION, eno_invoice_query) 221 | self.benchmark('[-] pyyaml (FullLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_invoice, Loader=yaml.FullLoader), 10) 222 | self.benchmark('[-] pyyaml (CLoader)', PYYAML_VERSION, lambda: yaml.load(yaml_invoice, Loader=yaml.CLoader)) 223 | self.benchmark('[-] qtoml', QTOML_VERSION, lambda: qtoml.loads(toml_invoice), 10) 224 | self.benchmark('[-] ruamel.yaml', RUAMEL_YAML_VERSION, lambda: ruamel.load(yaml_invoice)) 225 | self.benchmark('[-] toml', TOML_VERSION, lambda: toml.loads(toml_invoice)) 226 | self.benchmark('[-] tomlkit', TOMLKIT_VERSION, lambda: tomlkit.parse(toml_invoice), 10) 227 | 228 | with open('reports/python.eno', 'w') as file: 229 | file.write(self.report) 230 | 231 | def scenario(self, file): 232 | self.report += f"\n{file}:\n" 233 | 234 | print(file) 235 | 236 | def benchmark(self, library, version, perform, iteration_cutback_factor=1): 237 | iterations = int(self.ITERATIONS / iteration_cutback_factor) 238 | 239 | before = default_timer() 240 | for i in range(0, iterations): 241 | perform() 242 | after = default_timer() 243 | 244 | duration = after - before 245 | duration_normalized = (after - before) * iteration_cutback_factor 246 | 247 | self.report += f"{library} {version} = {duration_normalized}\n" 248 | 249 | if iteration_cutback_factor > 1: 250 | print(f"\x1b[33m{library} - {int(iterations/1000)}k iterations => {duration} seconds / {duration_normalized} normalized seconds\x1b[0m") 251 | else: 252 | print(f"{library} - {int(iterations/1000)}k iterations => {duration} seconds / {duration_normalized} normalized seconds") 253 | 254 | report = PythonReport() 255 | report.generate() 256 | -------------------------------------------------------------------------------- /benchmark.rb: -------------------------------------------------------------------------------- 1 | require 'benchmark' 2 | require 'time' 3 | 4 | require 'enolib' 5 | ENOLIB_VERSION = Gem.loaded_specs['enolib'].version 6 | 7 | require 'enotype' 8 | Enolib.register( 9 | boolean: ->(value) { Enotype::boolean(value) }, 10 | date: ->(value) { Enotype::date(value) }, 11 | datetime: ->(value) { Enotype::datetime(value) }, 12 | float: ->(value) { Enotype::float(value) }, 13 | integer: ->(value) { Enotype::integer(value) } 14 | ) 15 | 16 | require 'toml' 17 | TOML_VERSION = Gem.loaded_specs['toml'].version 18 | 19 | require 'toml-rb' 20 | TOML_RB_VERSION = Gem.loaded_specs['toml-rb'].version 21 | 22 | require 'tomlrb' 23 | TOMLRB_VERSION = Gem.loaded_specs['tomlrb'].version 24 | 25 | require 'yaml' 26 | YAML_VERSION = RUBY_VERSION 27 | 28 | class RubyReport 29 | ITERATIONS = 100000 30 | 31 | def initialize 32 | @report = <<~ENO 33 | evaluated: #{Time.now.utc.iso8601} 34 | iterations: #{ITERATIONS} 35 | runtime: #{RUBY_DESCRIPTION} 36 | 37 | # scenarios 38 | ENO 39 | end 40 | 41 | def benchmark(library, version, iteration_cutback_factor = 1) 42 | iterations = (ITERATIONS / iteration_cutback_factor).to_i 43 | 44 | result = Benchmark.measure do 45 | iterations.times { yield } 46 | end 47 | 48 | duration = result.total 49 | duration_normalized = duration * iteration_cutback_factor 50 | 51 | @report += "#{library} #{version} = #{duration_normalized}\n" 52 | 53 | if iteration_cutback_factor > 1 54 | puts "\x1b[33m#{library} - #{iterations/1000}k iterations => #{duration} seconds / #{duration_normalized} normalized seconds\x1b[0m" 55 | else 56 | puts "#{library} - #{iterations/1000}k iterations => #{duration} seconds / #{duration_normalized} normalized seconds" 57 | end 58 | end 59 | 60 | def generate 61 | scenario('abstract_hierarchy') 62 | 63 | eno_hierarchy = File.read('samples/abstract_hierarchy/hierarchy.eno') 64 | toml_hierarchy = File.read('samples/abstract_hierarchy/hierarchy.toml') 65 | yaml_hierarchy = File.read('samples/abstract_hierarchy/hierarchy.yaml') 66 | 67 | benchmark('[-] enolib', ENOLIB_VERSION) { Enolib.parse(eno_hierarchy) } 68 | benchmark('[✓] enolib', ENOLIB_VERSION) do 69 | document = Enolib.parse(eno_hierarchy) 70 | doc = document.section('doc') 71 | doc.list('colors').required_string_values 72 | traits = doc.fieldset('traits') 73 | traits.entry('tired').required_string_value 74 | traits.entry('extroverted').required_string_value 75 | traits.entry('funny').required_string_value 76 | traits.entry('inventive').required_string_value 77 | doc.list('things').required_string_values 78 | deep = doc.section('deep') 79 | deep.field('sea').required_string_value 80 | deeper = deep.section('deep') 81 | deeper.field('sea').required_string_value 82 | deepest = deeper.section('deep') 83 | deepest.field('sea').required_string_value 84 | end 85 | benchmark('[-] toml', TOML_VERSION, 10) { TOML.load(toml_hierarchy) } 86 | benchmark('[-] toml-rb', TOML_RB_VERSION, 10) { TomlRB.parse(toml_hierarchy) } 87 | benchmark('[-] tomlrb', TOMLRB_VERSION) { Tomlrb.parse(toml_hierarchy) } 88 | benchmark('[-] yaml', YAML_VERSION) { YAML.load(yaml_hierarchy) } 89 | 90 | 91 | scenario('content_heavy') 92 | 93 | eno_content = File.read('samples/content_heavy/content.eno') 94 | toml_content = File.read('samples/content_heavy/content.toml') 95 | yaml_content = File.read('samples/content_heavy/content.yaml') 96 | 97 | benchmark('[-] enolib', ENOLIB_VERSION) { Enolib.parse(eno_content) } 98 | benchmark('[✓] enolib', ENOLIB_VERSION) do 99 | Enolib.parse(eno_content).field('content').required_string_value 100 | end 101 | # ERRORS benchmark('[-] toml', TOML_VERSION, 100) { TOML.load(toml_content) } 102 | benchmark('[-] toml-rb', TOML_RB_VERSION, 100) { TomlRB.parse(toml_content) } 103 | benchmark('[-] tomlrb', TOMLRB_VERSION) { Tomlrb.parse(toml_content) } 104 | benchmark('[-] yaml', YAML_VERSION) { YAML.load(yaml_content) } 105 | 106 | 107 | scenario('invented_server_configuration') 108 | 109 | eno_configuration = File.read('samples/invented_server_configuration/configuration.eno') 110 | toml_configuration = File.read('samples/invented_server_configuration/configuration.toml') 111 | yaml_configuration = File.read('samples/invented_server_configuration/configuration.yaml') 112 | 113 | benchmark('[-] enolib', ENOLIB_VERSION) { Enolib.parse(eno_configuration) } 114 | benchmark('[✓] enolib', ENOLIB_VERSION) do 115 | document = Enolib.parse(eno_configuration) 116 | document.sections.each do |environment| 117 | environment.sections.each do |server| 118 | conf = server.fieldset('conf') 119 | conf.entry('ruby').required_boolean_value 120 | conf.entry('python').required_boolean_value 121 | server.field('clean').required_boolean_value 122 | server.list('steps').required_string_values 123 | end 124 | end 125 | end 126 | benchmark('[-] toml', TOML_VERSION, 100) { TOML.load(toml_configuration) } 127 | benchmark('[-] toml-rb', TOML_RB_VERSION, 10) { TomlRB.parse(toml_configuration) } 128 | benchmark('[-] tomlrb', TOMLRB_VERSION) { Tomlrb.parse(toml_configuration) } 129 | benchmark('[-] yaml', YAML_VERSION) { YAML.load(yaml_configuration) } 130 | 131 | 132 | scenario('jekyll_post_example') 133 | 134 | eno_post = File.read('samples/jekyll_post_example/post.eno') 135 | toml_post = File.read('samples/jekyll_post_example/post.toml') 136 | yaml_post = File.read('samples/jekyll_post_example/post.yaml') 137 | 138 | benchmark('[-] enolib', ENOLIB_VERSION) { Enolib.parse(eno_post) } 139 | benchmark('[✓] enolib', ENOLIB_VERSION) do 140 | document = Enolib.parse(eno_post) 141 | document.field('layout').required_string_value 142 | document.field('title').required_string_value 143 | document.field('date').required_datetime_value 144 | document.field('categories').required_string_value 145 | document.field('markdown').required_string_value 146 | end 147 | # ERRORS benchmark('[-] toml', TOML_VERSION, 100) { TOML.load(toml_post) } 148 | # SEGFAULTS benchmark('[-] toml-rb', TOML_RB_VERSION, 10) { TomlRB.parse(toml_post) } 149 | benchmark('[-] tomlrb', TOMLRB_VERSION) { Tomlrb.parse(toml_post) } 150 | benchmark('[-] yaml', YAML_VERSION) { YAML.load(yaml_post) } 151 | 152 | 153 | scenario('journey_route_data') 154 | 155 | eno_journey = File.read('samples/journey_route_data/journey.eno') 156 | toml_journey = File.read('samples/journey_route_data/journey.toml') 157 | yaml_journey = File.read('samples/journey_route_data/journey.yaml') 158 | 159 | benchmark('[-] enolib', ENOLIB_VERSION) { Enolib.parse(eno_journey) } 160 | benchmark('[✓] enolib', ENOLIB_VERSION) do 161 | document = Enolib.parse(eno_journey) 162 | document.field('title').required_string_value 163 | document.field('date').required_date_value 164 | document.field('time').required_string_value 165 | document.field('abstract').required_string_value 166 | document.sections('checkpoint').each do |checkpoint| 167 | checkpoint.field('coordinates').required_string_value 168 | checkpoint.field('hint').optional_string_value 169 | checkpoint.field('special').optional_string_value 170 | checkpoint.field('location').required_string_value 171 | safezone = checkpoint.optional_section('safezone') 172 | if safezone 173 | safezone.field('shape').required_string_value 174 | safezone.field('center').required_string_value 175 | safezone.field('radius').required_integer_value 176 | end 177 | end 178 | end 179 | benchmark('[-] toml', TOML_VERSION, 100) { TOML.load(toml_journey) } 180 | # SEGFAULTS benchmark('[-] toml-rb', TOML_RB_VERSION, 10) { TomlRB.parse(toml_journey) } 181 | benchmark('[-] tomlrb', TOMLRB_VERSION) { Tomlrb.parse(toml_journey) } 182 | benchmark('[-] yaml', YAML_VERSION) { YAML.load(yaml_journey) } 183 | 184 | 185 | scenario('yaml_invoice_example') 186 | 187 | eno_invoice = File.read('samples/yaml_invoice_example/invoice.eno') 188 | toml_invoice = File.read('samples/yaml_invoice_example/invoice.toml') 189 | yaml_invoice = File.read('samples/yaml_invoice_example/invoice.yaml') 190 | 191 | benchmark('[-] enolib', ENOLIB_VERSION) { Enolib.parse(eno_invoice) } 192 | benchmark('[✓] enolib', ENOLIB_VERSION) do 193 | document = Enolib.parse(eno_invoice) 194 | document.field('invoice').required_integer_value 195 | document.field('date').required_date_value 196 | document.field('tax').required_float_value 197 | document.field('total').required_float_value 198 | document.field('comments').required_string_value 199 | ['bill-to', 'ship-to'].each do |type| 200 | contact = document.section(type) 201 | contact.field('given').required_string_value 202 | contact.field('family').required_string_value 203 | address = contact.section('address') 204 | address.field('lines').required_string_value 205 | address.field('city').required_string_value 206 | address.field('state').required_string_value 207 | address.field('postal').required_string_value 208 | end 209 | document.sections('product').each do |product| 210 | product.field('sku').required_string_value 211 | product.field('quantity').required_integer_value 212 | product.field('description').required_string_value 213 | product.field('price').required_string_value 214 | end 215 | end 216 | # ERRORS benchmark('[-] toml', TOML_VERSION) { TOML.load(toml_invoice) } 217 | # SEGFAULTS benchmark('[-] toml-rb', TOML_RB_VERSION, 10) { TomlRB.parse(toml_invoice) } 218 | benchmark('[-] tomlrb', TOMLRB_VERSION) { Tomlrb.parse(toml_invoice) } 219 | benchmark('[-] yaml', YAML_VERSION) { YAML.load(yaml_invoice) } 220 | 221 | File.write('reports/ruby.eno', @report) 222 | end 223 | 224 | def scenario(file) 225 | @report += "\n#{file}:\n" 226 | puts file 227 | end 228 | end 229 | 230 | report = RubyReport.new 231 | report.generate 232 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "enolib-benchmarks", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "enolib-benchmarks", 8 | "dependencies": { 9 | "enolib": "git+https://codeberg.org/simonrepp/enolib-js.git", 10 | "enotype": "^0.3.0", 11 | "js-yaml": "^4.1.0", 12 | "toml": "^3.0.0", 13 | "toml-j0.4": "^1.1.1" 14 | } 15 | }, 16 | "node_modules/argparse": { 17 | "version": "2.0.1", 18 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 19 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 20 | }, 21 | "node_modules/enolib": { 22 | "version": "0.8.2", 23 | "resolved": "git+https://codeberg.org/simonrepp/enolib-js.git#2069b1e45c279a4ca47c6dab82fffcc5ff8aa983", 24 | "license": "MIT" 25 | }, 26 | "node_modules/enotype": { 27 | "version": "0.3.0", 28 | "resolved": "https://registry.npmjs.org/enotype/-/enotype-0.3.0.tgz", 29 | "integrity": "sha512-vUfQZj5ZIFMCYEhSww8pk2NIE0ZWsEI22Z79zFvRulx8TBtr+SPdVDHiesQQaUdQQKkkkB2z1VP8GXokONqIAQ==" 30 | }, 31 | "node_modules/js-yaml": { 32 | "version": "4.1.0", 33 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 34 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 35 | "dependencies": { 36 | "argparse": "^2.0.1" 37 | }, 38 | "bin": { 39 | "js-yaml": "bin/js-yaml.js" 40 | } 41 | }, 42 | "node_modules/toml": { 43 | "version": "3.0.0", 44 | "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", 45 | "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" 46 | }, 47 | "node_modules/toml-j0.4": { 48 | "version": "1.1.1", 49 | "resolved": "https://registry.npmjs.org/toml-j0.4/-/toml-j0.4-1.1.1.tgz", 50 | "integrity": "sha512-lYK5otg0+cto8YmsWcPEfeiTiC/VU6P6HA6ooaYI9K/KYT24Jg0BrYtRZK1K3cwakSMyh6nttfJL9RmQH0gyCg==" 51 | } 52 | }, 53 | "dependencies": { 54 | "argparse": { 55 | "version": "2.0.1", 56 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 57 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 58 | }, 59 | "enolib": { 60 | "version": "git+https://codeberg.org/simonrepp/enolib-js.git#2069b1e45c279a4ca47c6dab82fffcc5ff8aa983", 61 | "from": "enolib@git+https://codeberg.org/simonrepp/enolib-js.git" 62 | }, 63 | "enotype": { 64 | "version": "0.3.0", 65 | "resolved": "https://registry.npmjs.org/enotype/-/enotype-0.3.0.tgz", 66 | "integrity": "sha512-vUfQZj5ZIFMCYEhSww8pk2NIE0ZWsEI22Z79zFvRulx8TBtr+SPdVDHiesQQaUdQQKkkkB2z1VP8GXokONqIAQ==" 67 | }, 68 | "js-yaml": { 69 | "version": "4.1.0", 70 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 71 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 72 | "requires": { 73 | "argparse": "^2.0.1" 74 | } 75 | }, 76 | "toml": { 77 | "version": "3.0.0", 78 | "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", 79 | "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" 80 | }, 81 | "toml-j0.4": { 82 | "version": "1.1.1", 83 | "resolved": "https://registry.npmjs.org/toml-j0.4/-/toml-j0.4-1.1.1.tgz", 84 | "integrity": "sha512-lYK5otg0+cto8YmsWcPEfeiTiC/VU6P6HA6ooaYI9K/KYT24Jg0BrYtRZK1K3cwakSMyh6nttfJL9RmQH0gyCg==" 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "enolib": "git+https://codeberg.org/simonrepp/enolib-js.git", 4 | "enotype": "^0.3.0", 5 | "js-yaml": "^4.1.0", 6 | "toml": "^3.0.0", 7 | "toml-j0.4": "^1.1.1" 8 | }, 9 | "name": "enolib-benchmarks", 10 | "private": true, 11 | "scripts": { 12 | "report": "node report.js" 13 | }, 14 | "type": "module" 15 | } 16 | -------------------------------------------------------------------------------- /report.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { TerminalReporter, parse, register } from 'enolib'; 4 | import { datetime, float, integer } from 'enotype'; 5 | 6 | register({ datetime, float, integer }); 7 | 8 | const results = { 9 | JavaScript: { scenarios: {} }, 10 | Python: { scenarios: {} }, 11 | Ruby: { scenarios: {} } 12 | }; 13 | 14 | let maxTime = 0; 15 | let previousIterations; 16 | 17 | const formatDate = isoString => (isoString ? new Date(isoString) : new Date()).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); 18 | 19 | for (const language of Object.keys(results)) { 20 | const file = path.resolve(`reports/${language.toLowerCase()}.eno`); 21 | const input = fs.readFileSync(file, 'utf-8'); 22 | const document = parse(input, { reporter: TerminalReporter, source: file }); 23 | 24 | const iterations = document.field('iterations').requiredIntegerValue(); 25 | 26 | if (previousIterations && iterations !== previousIterations) { 27 | throw document.field('iterations').error(`This benchmark has a different number of iterations (${iterations}) than one of the others (${previousIterations}).`); 28 | } else { 29 | previousIterations = iterations; 30 | } 31 | 32 | results[language].evaluated = document.field('evaluated').requiredDatetimeValue(); 33 | results[language].runtime = document.field('runtime').requiredStringValue(); 34 | 35 | for (const scenarioField of document.requiredSection('scenarios').fields()) { 36 | const scenario = scenarioField.stringKey(); 37 | 38 | results[language].scenarios[scenario] = []; 39 | 40 | for (const benchmark of scenarioField.attributes()) { 41 | const time = benchmark.requiredFloatValue(); 42 | 43 | results[language].scenarios[scenario].push({ 44 | library: benchmark.stringKey(), 45 | time: time 46 | }); 47 | 48 | maxTime = Math.max(maxTime, time); 49 | } 50 | 51 | results[language].scenarios[scenario] = results[language].scenarios[scenario].sort((a, b) => a.time - b.time); 52 | } 53 | } 54 | 55 | let report = ` 56 | # enolib benchmarks 57 | 58 | **Last updated ${formatDate()}** 59 | 60 | These benchmarks evaluate the performance of all enolib implementations, 61 | compared also to the most popular yaml/toml parsers out there. As with all 62 | statistics please take these findings with a grain of salt, and feel invited to 63 | re-run these benchmarks or point out flaws and possible improvements to the 64 | methodology and code (some instructions are provided below the results). 65 | 66 | Benchmarks are currently performed on Arch Linux on an Intel® Xeon(R) CPU E5-1650 v3 @ 3.50GHz × 12 (see language sections below for detailed runtime info). 67 | `.trimStart(); 68 | 69 | report += ` 70 | ## Graphical results 71 | 72 | **[-]** indicates a pure **parsing** run with unsafe results. **(\\*)** 73 | 74 | **[✓]** indicates a benchmark for **parsing plus querying and validating** the whole document. **(\\*\\*)** 75 | 76 | **░░ 0.123** Shorter bars/numbers indicate **better performance**. 77 | 78 | **░░░░░░░░░ 456789** Larger bars/numbers indicate **worse performance**. 79 | 80 | Each ░ represents one second. 81 | `; 82 | 83 | for (const [language, languageData] of Object.entries(results)) { 84 | report += ` 85 | ### ${language} 86 | 87 | Evaluated in **${languageData.runtime}** on **${formatDate(languageData.evaluated)}**. 88 | `; 89 | 90 | for (const [scenario, benchmarks] of Object.entries(languageData.scenarios)) { 91 | report += `\n#### *${scenario}*\n\n  \n\`\`\`\n`; 92 | 93 | report += 'VAL LIBRARY'.padEnd(28) + ' NUMBER OF SECONDS FOR 100K (***) ITERATIONS\n\n'; 94 | 95 | let offTheScale = false; 96 | for (const benchmark of benchmarks) { 97 | const isEno = benchmark.library.includes('eno'); 98 | let bar = benchmark.time; 99 | const block = isEno ? '▓' : '░'; 100 | 101 | if (bar < 60) { 102 | report += `${benchmark.library.padEnd(28)} [${block.repeat(bar)}] ${benchmark.time.toFixed(3)} seconds\n`; 103 | } else { 104 | if (!offTheScale) { 105 | report += '\n' + '... ...'.padEnd(28) + ' OFF THE SCALE\n\n'; 106 | offTheScale = true; 107 | } 108 | 109 | const minutes = Math.round(bar/60); 110 | report += `${benchmark.library.padEnd(28)} ${minutes}+ minutes\n`; 111 | } 112 | 113 | } 114 | 115 | report += `\`\`\`\n`; 116 | } 117 | } 118 | 119 | 120 | report += ` 121 | ## Numerical results 122 | 123 | **[-]** indicates a pure **parsing** run with unsafe results. **(\\*)** 124 | 125 | **[✓]** indicates a benchmark for **parsing plus querying and validating** the whole document. **(\\*\\*)** 126 | 127 | **0.123** Smaller numbers indicate **better performance**. 128 | 129 | **4565789** Larger numbers indicate **worse performance**. 130 | 131 | `; 132 | 133 | 134 | for (const [language, languageData] of Object.entries(results)) { 135 | report += ` 136 | ### ${language} 137 | 138 | Evaluated in **${languageData.runtime}** on **${formatDate(languageData.evaluated)}**. 139 | `; 140 | 141 | for (const [scenario, benchmarks] of Object.entries(languageData.scenarios)) { 142 | report += `\n#### *${scenario}*\n\n`; 143 | 144 | report += `| Library | Number of seconds for 100k (***) iterations |\n`; 145 | report += `| ------- | ------------------------------------- |\n`; 146 | 147 | for (const benchmark of benchmarks) { 148 | const isEno = benchmark.library.includes('eno'); 149 | report += `| ${isEno ? '**':''}${benchmark.library}${isEno ? '**':''} | ${isEno ? '**':''}${benchmark.time.toFixed(3)}${isEno ? '**':''} |\n`; 150 | } 151 | } 152 | } 153 | 154 | report += ` 155 | --- 156 | 157 | ## How the data is gathered 158 | 159 | To see how the measurements were obtained, please take a look at the source of \`benchmark.js/py/rb\` inside this repository. 160 | To see how the report was compiled, please study \`report.js\` inside this repository. 161 | 162 | 163 | ## Notes 164 | 165 | As you might have noticed, the benchmark figures for ruby are occasionally 166 | missing one or two libraries for specific benchmarks – the reason for this is 167 | simply that these libraries failed on those respective benchmarks, either by 168 | raising an error or even by segfaulting. 169 | 170 | **(\\*)**: The majority of YAML/TOML parsers produce plain object dumps which are inherently unvalidated. 171 | 172 | **(\\*\\*)**: In the enolib libraries a document is validated through querying. 173 | If the whole document is queried, the whole document is validated. If only a portion of the document is queried 174 | less validation and less memory allocation happens and the performance thereby increases too. The results displayed 175 | here represent the (performance-wise worst) case of using all data present in a document. 176 | 177 | **(\\*\\*\\*)**: Some libraries included in the benchmarks exhibit an up to 1000x 178 | slower performance compared to the top ranking parsers, these have been 179 | partially sampled with up to only 1k iterations, with the total duration 180 | extrapolated for the global comparison again. 181 | `; 182 | 183 | fs.writeFileSync(path.resolve('README.md'), report); 184 | -------------------------------------------------------------------------------- /reports/javascript.eno: -------------------------------------------------------------------------------- 1 | evaluated: 2022-04-29T18:48:48Z 2 | iterations: 100000 3 | runtime: node v16.14.2 [linux-x64] 4 | 5 | # scenarios 6 | 7 | abstract_hierarchy: 8 | [-] enolib (git) = 0.9906451900005341 9 | [✓] enolib (git) = 1.3545888329967857 10 | [-] js-yaml 4.1.0 = 2.1130163460001348 11 | [-] toml 3.0.0 = 86.15874518997968 12 | [-] toml-j0.4 1.1.1 = 5.836372074998915 13 | 14 | content_heavy: 15 | [-] enolib (git) = 0.6528849509954453 16 | [✓] enolib (git) = 0.6214131169989705 17 | [-] js-yaml 4.1.0 = 8.988973702996969 18 | [-] toml 3.0.0 = 9945.709865099938 19 | [-] toml-j0.4 1.1.1 = 322.45939718998966 20 | 21 | invented_server_configuration: 22 | [-] enolib (git) = 0.8622047730013728 23 | [✓] enolib (git) = 1.2323724990040064 24 | [-] js-yaml 4.1.0 = 2.477657805994153 25 | [-] toml 3.0.0 = 155.78282979004084 26 | [-] toml-j0.4 1.1.1 = 8.670540839001536 27 | 28 | jekyll_post_example: 29 | [-] enolib (git) = 0.5155324880033731 30 | [✓] enolib (git) = 0.7463200320005416 31 | [-] js-yaml 4.1.0 = 1.0681472110003234 32 | [-] toml 3.0.0 = 204.9212373699993 33 | [-] toml-j0.4 1.1.1 = 11.397456769995392 34 | 35 | journey_route_data: 36 | [-] enolib (git) = 2.3752881060019138 37 | [✓] enolib (git) = 3.4902450180053712 38 | [-] js-yaml 4.1.0 = 4.430680881999433 39 | [-] toml 3.0.0 = 132.1450736500323 40 | [-] toml-j0.4 1.1.1 = 13.877505913995206 41 | 42 | yaml_invoice_example: 43 | [-] enolib (git) = 2.071474564999342 44 | [✓] enolib (git) = 3.3230939719974995 45 | [-] js-yaml 4.1.0 = 3.144271203994751 46 | [-] toml 3.0.0 = 75.22617781900614 47 | [-] toml-j0.4 1.1.1 = 11.032221832998097 48 | -------------------------------------------------------------------------------- /reports/python.eno: -------------------------------------------------------------------------------- 1 | evaluated: 2022-04-29T19:05:56+00:00 2 | iterations: 100000 3 | runtime: CPython 3.10.4 [Linux-5.17.4-arch1-1-x86_64-with-glibc2.35] 4 | 5 | # scenarios 6 | 7 | abstract_hierarchy: 8 | [-] enolib 0.8.1 = 9.722321713001293 9 | [✓] enolib 0.8.1 = 18.010859809997783 10 | [-] pyyaml (FullLoader) 6.0 = 128.3263594100572 11 | [-] pyyaml (CLoader) 6.0 = 12.871710004001216 12 | [-] qtoml 0.3.1 = 31.738332525004807 13 | [-] ruamel.yaml 0.17.21 = 31.934130834000825 14 | [-] toml 0.10.2 = 20.201103857005364 15 | [-] tomlkit 0.10.2 = 150.25909840005625 16 | 17 | content_heavy: 18 | [-] enolib 0.8.1 = 9.37653371199849 19 | [✓] enolib 0.8.1 = 10.979708620994643 20 | [-] pyyaml (FullLoader) 6.0 = 1016.1062503000721 21 | [-] pyyaml (CLoader) 6.0 = 11.788839508997626 22 | [-] qtoml 0.3.1 = 632.3282204000861 23 | [-] ruamel.yaml 0.17.21 = 20.964816407002218 24 | [-] toml 0.10.2 = 567.7488816299592 25 | [-] tomlkit 0.10.2 = 6078.838421999535 26 | 27 | invented_server_configuration: 28 | [-] enolib 0.8.1 = 9.744687525999325 29 | [✓] enolib 0.8.1 = 23.573965110001154 30 | [-] pyyaml (FullLoader) 6.0 = 128.06401727000775 31 | [-] pyyaml (CLoader) 6.0 = 13.371140135997848 32 | [-] qtoml 0.3.1 = 49.09805294599937 33 | [-] ruamel.yaml 0.17.21 = 32.37525555799948 34 | [-] toml 0.10.2 = 30.444373869002447 35 | [-] tomlkit 0.10.2 = 275.4891294400295 36 | 37 | jekyll_post_example: 38 | [-] enolib 0.8.1 = 4.35808107000048 39 | [✓] enolib 0.8.1 = 10.486271488000057 40 | [-] pyyaml (FullLoader) 6.0 = 69.7883460400044 41 | [-] pyyaml (CLoader) 6.0 = 5.1853519569995115 42 | [-] qtoml 0.3.1 = 28.791317734001495 43 | [-] ruamel.yaml 0.17.21 = 15.789307683997322 44 | [-] toml 0.10.2 = 25.397276896997937 45 | [-] tomlkit 0.10.2 = 196.1517813699902 46 | 47 | journey_route_data: 48 | [-] enolib 0.8.1 = 22.365788529001293 49 | [✓] enolib 0.8.1 = 38.25198214199918 50 | [-] pyyaml (FullLoader) 6.0 = 262.8937801400025 51 | [-] pyyaml (CLoader) 6.0 = 25.49366254999768 52 | [-] qtoml 0.3.1 = 72.07223174998944 53 | [-] ruamel.yaml 0.17.21 = 57.38733938997029 54 | [-] toml 0.10.2 = 48.61940198799857 55 | [-] tomlkit 0.10.2 = 383.60510300000897 56 | 57 | yaml_invoice_example: 58 | [-] enolib 0.8.1 = 20.275982480001403 59 | [✓] enolib 0.8.1 = 35.17805813100131 60 | [-] pyyaml (FullLoader) 6.0 = 186.6521914999612 61 | [-] pyyaml (CLoader) 6.0 = 19.352128353006265 62 | [-] qtoml 0.3.1 = 56.399673909982084 63 | [-] ruamel.yaml 0.17.21 = 46.486141792003764 64 | [-] toml 0.10.2 = 37.57768651000515 65 | [-] tomlkit 0.10.2 = 305.2597561800212 66 | -------------------------------------------------------------------------------- /reports/ruby.eno: -------------------------------------------------------------------------------- 1 | evaluated: 2022-04-30T07:28:34Z 2 | iterations: 100000 3 | runtime: ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux] 4 | 5 | # scenarios 6 | 7 | abstract_hierarchy: 8 | [-] enolib 0.8.1 = 6.565898000000001 9 | [✓] enolib 0.8.1 = 11.042372 10 | [-] toml 0.3.0 = 501.41778 11 | [-] toml-rb 2.1.2 = 370.53017 12 | [-] tomlrb 2.0.1 = 33.20000200000001 13 | [-] yaml 3.0.0 = 11.541595999999998 14 | 15 | content_heavy: 16 | [-] enolib 0.8.1 = 5.882159000000009 17 | [✓] enolib 0.8.1 = 7.130401999999975 18 | [-] toml-rb 2.1.2 = 2508.0087999999987 19 | [-] tomlrb 2.0.1 = 61.495326000000006 20 | [-] yaml 3.0.0 = 12.834096999999979 21 | 22 | invented_server_configuration: 23 | [-] enolib 0.8.1 = 6.806253999999967 24 | [✓] enolib 0.8.1 = 15.213271 25 | [-] toml 0.3.0 = 828.2962999999995 26 | [-] toml-rb 2.1.2 = 623.4525 27 | [-] tomlrb 2.0.1 = 58.850481 28 | [-] yaml 3.0.0 = 12.081687999999986 29 | 30 | jekyll_post_example: 31 | [-] enolib 0.8.1 = 5.188773000000026 32 | [✓] enolib 0.8.1 = 8.221777999999972 33 | [-] tomlrb 2.0.1 = 11.752586000000008 34 | [-] yaml 3.0.0 = 7.283086000000026 35 | 36 | journey_route_data: 37 | [-] enolib 0.8.1 = 14.216060000000008 38 | [✓] enolib 0.8.1 = 23.534896000000032 39 | [-] toml 0.3.0 = 1098.9280000000026 40 | [-] tomlrb 2.0.1 = 61.63321400000002 41 | [-] yaml 3.0.0 = 25.26177400000006 42 | 43 | yaml_invoice_example: 44 | [-] enolib 0.8.1 = 17.903017999999978 45 | [✓] enolib 0.8.1 = 28.54772700000001 46 | [-] tomlrb 2.0.1 = 53.65921700000001 47 | [-] yaml 3.0.0 = 18.51987900000006 48 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | enolib==0.8.1 2 | enotype==0.3.0 3 | pyyaml==6.0 4 | qtoml==0.3.1 5 | ruamel.yaml==0.17.21 6 | toml==0.10.2 7 | tomlkit==0.10.2 8 | -------------------------------------------------------------------------------- /samples/abstract_hierarchy/hierarchy.eno: -------------------------------------------------------------------------------- 1 | # doc 2 | colors: 3 | - blue 4 | - green 5 | - orange 6 | - red 7 | traits: 8 | tired = somewhat 9 | extroverted = sometimes 10 | funny = always 11 | inventive = occasionally 12 | things: 13 | - boxes 14 | - canes 15 | - pyramids 16 | - cubes 17 | ## deep 18 | sea: blue 19 | ### deep 20 | sea: darkblue 21 | #### deep 22 | sea: black 23 | -------------------------------------------------------------------------------- /samples/abstract_hierarchy/hierarchy.toml: -------------------------------------------------------------------------------- 1 | [doc] 2 | colors = [ 3 | "blue", 4 | "green", 5 | "orange", 6 | "red" 7 | ] 8 | things = [ 9 | "boxes", 10 | "canes", 11 | "pyramids", 12 | "cubes" 13 | ] 14 | [doc.traits] 15 | tired = "somewhat" 16 | extroverted = "sometimes" 17 | funny = "always" 18 | inventive = "occasionally" 19 | [doc.deep] 20 | sea = "blue" 21 | [doc.deep.deep] 22 | sea = "darkblue" 23 | [doc.deep.deep.deep] 24 | sea = "black" 25 | -------------------------------------------------------------------------------- /samples/abstract_hierarchy/hierarchy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | doc: 3 | colors: 4 | - blue 5 | - green 6 | - orange 7 | - red 8 | traits: 9 | tired: somewhat 10 | extroverted: sometimes 11 | funny: always 12 | inventive: occasionally 13 | things: 14 | - boxes 15 | - canes 16 | - pyramids 17 | - cubes 18 | deep: 19 | sea: blue 20 | deep: 21 | sea: darkblue 22 | deep: 23 | sea: black 24 | -------------------------------------------------------------------------------- /samples/content_heavy/content.eno: -------------------------------------------------------------------------------- 1 | -- content 2 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis dolor quis orci vestibulum tempor. Donec sodales urna quam, eget consectetur risus venenatis a. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent finibus tortor libero, in semper nisi efficitur eget. Vivamus pharetra diam arcu, a bibendum massa condimentum eu. In ullamcorper varius quam sit amet placerat. Aliquam tempus, dolor vel dapibus facilisis, erat lectus aliquet urna, varius rutrum orci justo vel ex. Donec lobortis congue tellus, quis scelerisque dui suscipit vitae. 3 | 4 | Nulla libero sapien, porttitor eu eros a, maximus viverra eros. Fusce fermentum malesuada cursus. Sed vitae dictum erat, id auctor erat. Suspendisse quis urna commodo, rhoncus justo in, tincidunt dolor. Sed pulvinar eros volutpat ipsum dictum venenatis. Etiam dui nisl, porta nec malesuada et, suscipit sit amet enim. Quisque at dignissim augue. Sed tincidunt, eros at sollicitudin laoreet, odio orci ornare sapien, et tempor arcu diam eget mauris. Vivamus blandit auctor libero ut auctor. Cras laoreet massa ut ipsum suscipit blandit. Nunc vel purus quis enim congue pharetra id ac nisi. Nam tincidunt luctus lorem, sit amet mattis est porttitor et. Suspendisse potenti. Cras condimentum purus non elementum pharetra. Nulla at porttitor ante. Morbi pellentesque commodo mi, at rutrum dui efficitur in. 5 | 6 | Aliquam a porttitor nisi. Phasellus pellentesque feugiat mi, bibendum dignissim odio aliquet id. Aenean vitae massa erat. Nulla vestibulum vestibulum elit id rhoncus. Aenean sodales molestie dapibus. Nunc vitae nibh eget elit bibendum consectetur sit amet a orci. Ut laoreet velit sagittis mauris porttitor, a laoreet mauris gravida. Pellentesque vehicula leo vel faucibus bibendum. Aliquam dapibus vulputate gravida. Etiam facilisis ligula ut porttitor convallis. Morbi venenatis purus id nisi mattis, vitae commodo est imperdiet. Aliquam elementum nulla ut accumsan vestibulum. Pellentesque blandit lorem elit, ut ornare erat pharetra non. Pellentesque euismod ullamcorper imperdiet. Aenean sollicitudin turpis ut lorem pharetra, non pulvinar augue posuere. Vestibulum risus enim, ultrices eu urna eu, bibendum tincidunt est. 7 | 8 | Maecenas maximus, erat vel faucibus hendrerit, nulla augue dictum erat, at ultricies velit mauris id nibh. Phasellus malesuada luctus dapibus. Fusce odio justo, accumsan id sapien vel, tristique gravida massa. Proin pellentesque, ipsum nec euismod dictum, purus nisl convallis velit, quis pulvinar libero orci eu nisi. Proin eu viverra arcu, nec suscipit orci. Nam a tortor laoreet, auctor erat posuere, imperdiet enim. Nam consectetur erat nisi, sit amet dapibus neque pharetra non. Quisque mollis nulla sed enim hendrerit, vel lacinia mauris iaculis. Donec interdum, est auctor euismod scelerisque, neque lectus pharetra lacus, eu ornare velit mauris quis libero. Nullam quis dolor porta, pulvinar lectus ac, tincidunt ex. Praesent malesuada tempus mollis. Proin id sapien consectetur, semper risus nec, tempor metus. Donec in nisi ac massa accumsan cursus. Mauris consectetur commodo fringilla. 9 | 10 | Fusce ultricies neque vel vehicula ullamcorper. Etiam non tellus nisl. Mauris tellus massa, sodales et dui vel, faucibus malesuada ipsum. Quisque dignissim, ante in placerat venenatis, nulla nisl placerat lacus, eget pellentesque velit nisl at ipsum. Aliquam erat volutpat. Proin quam diam, blandit in felis et, imperdiet volutpat augue. Nam ultricies quam eu efficitur semper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse vel euismod risus. Donec consequat orci quis ex elementum suscipit. Nullam ultrices odio ut turpis molestie convallis. In tempus ipsum sit amet lobortis euismod. Donec hendrerit laoreet elit, non malesuada massa porttitor eu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 11 | 12 | Nunc eleifend nibh vitae convallis pharetra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce a nunc at velit euismod tincidunt. Sed orci nisi, varius convallis erat et, fringilla consequat velit. Curabitur sem felis, pellentesque non ullamcorper eu, accumsan ut enim. Cras sit amet sollicitudin est. Donec quis porta urna. Ut ultricies quis nibh nec venenatis. Morbi pharetra condimentum ipsum. Praesent maximus elit nec ipsum lobortis finibus. 13 | 14 | Nulla facilisi. Sed id ante libero. Fusce non risus eget neque facilisis consequat ac non nisl. Duis aliquam condimentum urna non blandit. Etiam convallis ex in orci ornare facilisis. Praesent vel arcu pellentesque, ultrices lacus at, dapibus mauris. Suspendisse potenti. Fusce luctus sapien quam, vel blandit metus posuere sit amet. Mauris faucibus dolor non turpis auctor cursus. Nulla pretium nulla pulvinar libero suscipit viverra. Suspendisse potenti. Etiam elementum, tellus nec porttitor consequat, dui libero lacinia sem, vel ultricies nunc ex ut risus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. 15 | 16 | Vivamus accumsan maximus nibh id blandit. Pellentesque blandit blandit magna nec vestibulum. Morbi gravida lectus leo, id vehicula quam hendrerit sed. Phasellus congue metus ut varius cursus. Curabitur quam arcu, hendrerit sit amet nulla rutrum, facilisis pulvinar orci. In hac habitasse platea dictumst. Sed a maximus ante. Sed convallis tempor arcu eget blandit. Nulla vel consectetur turpis, dignissim tincidunt mi. 17 | 18 | Sed in est sit amet augue imperdiet condimentum ut at odio. Maecenas auctor sem erat, pretium molestie quam maximus sed. Ut rhoncus orci ut diam pulvinar sodales. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum maximus facilisis commodo. Nunc tempor diam turpis, et condimentum velit aliquam eget. In hac habitasse platea dictumst. Praesent volutpat turpis non pharetra luctus. Quisque ut porta metus. Quisque nec mi ornare, dignissim diam at, posuere mauris. Nullam molestie interdum elit non volutpat. Maecenas libero lectus, rutrum eu porta non, vestibulum in mauris. 19 | 20 | Donec sit amet purus a felis iaculis sollicitudin porttitor non elit. Nullam tincidunt lectus a tincidunt bibendum. Vivamus condimentum, enim non finibus rutrum, enim erat interdum odio, at aliquet turpis dui vel quam. Mauris imperdiet sem quis magna faucibus, a vestibulum risus posuere. Integer dapibus, leo in tincidunt vehicula, elit lacus bibendum ligula, nec facilisis lacus ligula vel neque. Nam id dolor arcu. Cras non facilisis risus. Quisque odio metus, vestibulum quis nunc rhoncus, congue efficitur magna. Morbi ut porta nisl. Vestibulum sed sagittis nunc. Nunc vel condimentum metus. 21 | 22 | Praesent malesuada auctor pellentesque. Integer non eros sit amet ante cursus imperdiet. Donec imperdiet dui neque, non iaculis felis blandit vel. Maecenas justo metus, facilisis vitae lectus id, sodales facilisis arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac orci a mi sollicitudin consequat. Praesent euismod, sem id porttitor porta, nunc mi laoreet orci, eget ullamcorper augue diam a lorem. Nam porta metus vel vehicula pharetra. Duis hendrerit porta ante sit amet auctor. Suspendisse potenti. Nam ut placerat tellus. Vivamus quis auctor neque, ut sagittis quam. Aliquam erat volutpat. 23 | 24 | Aliquam erat volutpat. Mauris mollis tellus nec imperdiet interdum. Phasellus sagittis erat nec consectetur fringilla. Donec lobortis interdum dolor non venenatis. Integer egestas tellus eu eros iaculis maximus. Maecenas dapibus pulvinar odio, a tempus sapien porta fermentum. Integer sagittis dolor in tortor faucibus, ac lacinia velit fermentum. Mauris molestie, nulla id facilisis viverra, enim neque gravida quam, at lobortis orci augue id neque. Aenean ornare eros in accumsan tempus. 25 | 26 | Nullam sed viverra felis. Nulla malesuada nibh a volutpat ultrices. Ut nulla ante, euismod eget porttitor sed, finibus et nunc. Praesent cursus mauris at laoreet tempor. Aliquam vitae mattis risus. Vivamus porta neque vel aliquet pellentesque. Vestibulum tincidunt faucibus ligula, ut iaculis sem. Morbi feugiat tellus id felis vestibulum aliquet. Suspendisse augue nunc, condimentum non erat eget, imperdiet varius velit. Donec accumsan mattis molestie. Suspendisse potenti. In viverra elit elit, sodales eleifend quam vestibulum eu. Mauris sed scelerisque nulla. Donec dapibus tortor in dapibus venenatis. Integer accumsan mi eget sapien posuere, a hendrerit erat suscipit. 27 | 28 | Nunc sed sapien sit amet felis blandit porttitor vitae eu augue. Sed posuere euismod eros sed suscipit. Aliquam erat volutpat. Aenean sit amet mi iaculis turpis faucibus venenatis eu eu neque. Praesent tincidunt dictum tortor, eu tincidunt mauris posuere nec. Curabitur non orci rutrum, malesuada mauris sit amet, commodo libero. Proin risus neque, tincidunt in aliquet nec, fringilla nec massa. Nunc porttitor laoreet nisi eget iaculis. Suspendisse quis arcu maximus, tincidunt elit volutpat, bibendum orci. Aenean sodales, augue elementum convallis dignissim, orci tortor consequat orci, sed sollicitudin ligula ipsum non leo. Fusce egestas rutrum enim, eget venenatis tellus gravida ac. Duis lobortis nisi vitae interdum mattis. 29 | 30 | Mauris faucibus faucibus nunc. Cras at molestie est. Praesent eget neque leo. Morbi tempor sollicitudin erat. Praesent ornare ultricies erat, vel pulvinar neque luctus id. Aliquam posuere auctor nunc, porttitor interdum nulla varius non. Morbi eu nulla id velit accumsan egestas sit amet id orci. Proin et lobortis tortor. Donec lacinia tempus ligula nec tincidunt. Suspendisse in placerat turpis. Cras eleifend diam a venenatis consequat. Donec eu velit id neque commodo tincidunt. Aenean finibus metus ut odio sodales imperdiet. Phasellus ac urna nibh. Praesent viverra accumsan justo, vel gravida ipsum laoreet et. 31 | 32 | Fusce ultricies velit leo, sit amet fermentum velit malesuada non. Sed eget lectus at ipsum porta sodales eget pulvinar neque. Sed vel rutrum neque. Nam sollicitudin interdum vestibulum. Nullam et neque nec sapien porttitor interdum ac quis nisl. Aenean maximus tellus consequat nisi efficitur, a pellentesque ipsum scelerisque. Donec rutrum quam enim, vitae tristique augue sagittis accumsan. Phasellus bibendum odio at odio tincidunt, eget laoreet lorem molestie. Phasellus mauris elit, efficitur ac nunc vel, porta vulputate sapien. In pulvinar tellus vitae purus pellentesque interdum. Pellentesque dapibus magna imperdiet ex porta, sed iaculis elit semper. Quisque at tempor tortor. In lorem nulla, euismod placerat pretium ut, suscipit vitae lectus. Donec finibus tristique libero, sit amet varius dui sodales vel. Fusce auctor et lorem et aliquam. 33 | 34 | Sed tincidunt ornare augue, id malesuada arcu varius faucibus. Ut id gravida ligula. Curabitur efficitur justo id eros luctus blandit. Etiam quam elit, auctor nec ante quis, pulvinar placerat ipsum. Nullam sodales turpis vel lorem sodales, eget pulvinar purus feugiat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut semper enim sit amet leo egestas, finibus dictum leo molestie. Nunc eu feugiat arcu, ut pellentesque justo. Quisque convallis aliquam purus, sed malesuada risus malesuada feugiat. Ut bibendum enim est, eget lacinia mi suscipit vitae. Pellentesque sollicitudin fringilla lorem vel aliquam. Praesent dapibus elit sed metus tincidunt malesuada. Quisque suscipit risus nec nibh varius, sed dictum dolor tempor. 35 | 36 | Aliquam magna arcu, tincidunt vel tristique vel, feugiat eget dui. Sed aliquam sagittis nisi in tempor. Ut vitae leo malesuada, fermentum nisl quis, porttitor dui. Suspendisse elementum, lacus ac hendrerit dictum, sapien dui placerat magna, in egestas felis leo et ante. Curabitur ac molestie est. Sed dapibus neque eget lorem gravida, eu vulputate turpis tempus. Sed fringilla a dui accumsan viverra. Quisque id odio mi. Curabitur facilisis vehicula ipsum, ut vehicula nisi mattis sit amet. Nunc in nisl vitae est eleifend molestie sit amet ac dolor. 37 | 38 | Nullam rutrum massa vitae leo molestie tempus. Duis laoreet turpis dui, eget placerat purus suscipit id. Fusce in dolor hendrerit, rutrum tortor sed, egestas quam. Vestibulum sed felis a turpis mollis dapibus. Nullam facilisis gravida vulputate. Sed sollicitudin id tellus in faucibus. Maecenas convallis est leo, a laoreet dolor venenatis in. 39 | 40 | In sagittis augue varius eros eleifend, sit amet interdum nisi tincidunt. Sed dapibus vulputate ligula, sed consequat metus vulputate in. Sed facilisis justo at turpis aliquam dictum. Mauris hendrerit arcu in nisl auctor viverra. Vivamus orci nunc, commodo non maximus ac, sagittis dignissim dui. Aenean magna magna, iaculis quis odio a, semper accumsan ipsum. Mauris condimentum diam ac posuere venenatis. Aliquam erat volutpat. Vestibulum nec eros a odio venenatis cursus. Vivamus iaculis nisi vel nunc elementum sagittis. Phasellus mollis felis tellus, sed finibus arcu vestibulum id. Nulla laoreet, orci non scelerisque luctus, justo elit auctor ligula, quis accumsan purus mauris et felis. 41 | 42 | Quisque sed ex suscipit, venenatis mauris quis, consectetur lectus. Pellentesque pellentesque ante dui, vel bibendum augue sollicitudin vitae. Ut faucibus nisi in convallis finibus. Maecenas quis diam diam. Sed quis aliquam augue. Integer egestas purus elit, in efficitur sem pellentesque semper. Phasellus convallis quis turpis eu varius. Etiam eu diam at ante dignissim interdum ac eu ante. 43 | 44 | Duis dolor risus, tempus sed ipsum eget, sodales accumsan ligula. Aenean varius euismod libero, sed semper dolor commodo ac. Donec at blandit elit. Nunc et vestibulum orci, ac placerat justo. Sed nec est mattis, efficitur tellus in, imperdiet nisi. Nam fermentum felis urna. Ut consectetur dui quis fermentum tempor. Cras ultricies efficitur justo vitae mollis. Donec sodales felis quis sapien semper commodo. Etiam cursus tempus sapien in interdum. Donec non nisl feugiat, congue massa vel, auctor tellus. Morbi varius, magna vel sodales rutrum, tellus dolor auctor ligula, fermentum sagittis dolor nisi vitae diam. Mauris sollicitudin tempus nisi, at finibus nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 45 | 46 | Suspendisse lorem mi, iaculis a odio nec, porttitor pharetra ex. Sed pretium lectus id lectus dictum suscipit. In hac habitasse platea dictumst. Aliquam a felis in sapien bibendum pellentesque. Cras ligula enim, congue vel dapibus non, condimentum ut odio. Nam eget consectetur lectus, eget aliquam dolor. Phasellus interdum nisl sit amet orci dignissim dapibus. Nam auctor varius nisl eu pulvinar. Curabitur aliquam nibh vitae ultrices mattis. Donec auctor sem eget aliquam molestie. 47 | 48 | Proin mollis a libero vel suscipit. Praesent ullamcorper varius sollicitudin. Quisque vel viverra orci. Mauris quis viverra leo, quis finibus lacus. In hac habitasse platea dictumst. Fusce iaculis porta ex ut suscipit. Proin ipsum eros, lacinia a sem eget, tincidunt auctor urna. Aliquam quis fringilla sem. 49 | 50 | Nulla dapibus commodo efficitur. In erat erat, malesuada et ullamcorper in, eleifend eu magna. In hac habitasse platea dictumst. Morbi in lectus at augue maximus sagittis ac in ex. Nullam vitae neque nec tellus mattis mollis eu in felis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus sed blandit diam. Phasellus eget mi vel justo egestas venenatis. Etiam aliquet est purus, nec dictum dolor varius at. Ut ex augue, pretium eget dictum ut, tempus at turpis. Nulla hendrerit iaculis congue. Etiam commodo cursus viverra. Phasellus fermentum purus ut maximus hendrerit. Sed feugiat ipsum justo, posuere feugiat est semper nec. Nunc cursus, libero vel finibus vulputate, erat urna vestibulum mi, pretium suscipit massa lectus ut mi. Ut nec tristique lacus, ultricies volutpat odio. 51 | 52 | Donec fermentum, enim ac hendrerit semper, magna magna rutrum velit, vestibulum imperdiet eros ex a est. Ut dapibus quis erat at vestibulum. Aenean non massa ac arcu consectetur semper. Mauris nec odio porta, lobortis elit at, dictum justo. Aenean porttitor accumsan nulla, vitae laoreet velit interdum ut. Maecenas hendrerit porta neque ac commodo. Aenean eget pulvinar nisl, vel finibus lectus. Maecenas fringilla pellentesque velit, vel mollis dolor pellentesque sed. Cras ac dignissim massa. Maecenas lobortis leo id felis dapibus, volutpat faucibus metus vulputate. Maecenas dictum enim turpis, ac tincidunt augue imperdiet et. Nullam consequat sapien in nisi tincidunt volutpat. Cras posuere imperdiet felis, auctor ullamcorper nunc luctus id. Sed eget dapibus lorem. Nam sit amet sagittis augue. 53 | 54 | Nulla vitae metus nec quam eleifend finibus. Etiam nisi orci, faucibus sed enim id, fringilla volutpat ipsum. Sed consectetur nulla elementum aliquam venenatis. Donec pretium elit sed mi molestie, in placerat risus tincidunt. Vivamus vulputate nunc dolor, non facilisis sapien fringilla id. Nullam fermentum ipsum sit amet ligula semper, a mollis urna laoreet. Vivamus non sodales lorem, in mattis erat. Praesent dapibus quis sapien vitae porta. Ut accumsan, diam vitae suscipit ullamcorper, nisl metus rhoncus sem, congue lobortis quam metus nec mauris. In consequat egestas libero a ultrices. Nulla consectetur nibh felis, nec finibus odio mollis id. 55 | 56 | Vivamus eleifend orci eget sapien elementum iaculis. Quisque ullamcorper, arcu id vestibulum cursus, mauris risus dignissim augue, ut vehicula nisl nisi ut felis. Suspendisse sit amet sodales nunc. Nam accumsan dignissim cursus. Suspendisse eget porta felis. Praesent aliquet, nisi sed semper molestie, nulla lorem rutrum elit, a aliquet velit neque nec lacus. Sed nec malesuada magna, at cursus justo. Aenean non libero mauris. 57 | 58 | Curabitur in aliquet enim, sit amet rhoncus sapien. Phasellus blandit lorem eu tortor venenatis vestibulum. Nunc sodales sem est, nec iaculis magna tristique ac. Mauris suscipit, nibh vitae facilisis facilisis, urna sem porttitor purus, vitae commodo turpis massa quis eros. Quisque et neque purus. Duis non sodales odio. Aliquam sed tortor porttitor, congue dui vel, fringilla leo. Suspendisse molestie tempus est cursus imperdiet. Donec non convallis dolor. 59 | 60 | Proin elementum ultrices efficitur. Cras mi turpis, porta id mi quis, imperdiet imperdiet purus. Duis sit amet orci egestas, dictum elit nec, feugiat nulla. Sed sollicitudin ligula vitae vulputate lacinia. Fusce bibendum odio sit amet mauris interdum, gravida pellentesque orci iaculis. In hac habitasse platea dictumst. Fusce molestie luctus purus, sed porttitor augue bibendum nec. Integer faucibus augue vitae dictum placerat. Cras dui massa, commodo quis blandit eget, dictum in diam. Donec feugiat massa ut tempus posuere. Praesent semper faucibus scelerisque. Phasellus nec viverra metus, volutpat fermentum lectus. Vestibulum non orci quis sapien tempor sollicitudin. Pellentesque id metus vel diam efficitur ultricies. 61 | -- content 62 | -------------------------------------------------------------------------------- /samples/content_heavy/content.toml: -------------------------------------------------------------------------------- 1 | content = """ 2 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis dolor quis orci vestibulum tempor. Donec sodales urna quam, eget consectetur risus venenatis a. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent finibus tortor libero, in semper nisi efficitur eget. Vivamus pharetra diam arcu, a bibendum massa condimentum eu. In ullamcorper varius quam sit amet placerat. Aliquam tempus, dolor vel dapibus facilisis, erat lectus aliquet urna, varius rutrum orci justo vel ex. Donec lobortis congue tellus, quis scelerisque dui suscipit vitae. 3 | 4 | Nulla libero sapien, porttitor eu eros a, maximus viverra eros. Fusce fermentum malesuada cursus. Sed vitae dictum erat, id auctor erat. Suspendisse quis urna commodo, rhoncus justo in, tincidunt dolor. Sed pulvinar eros volutpat ipsum dictum venenatis. Etiam dui nisl, porta nec malesuada et, suscipit sit amet enim. Quisque at dignissim augue. Sed tincidunt, eros at sollicitudin laoreet, odio orci ornare sapien, et tempor arcu diam eget mauris. Vivamus blandit auctor libero ut auctor. Cras laoreet massa ut ipsum suscipit blandit. Nunc vel purus quis enim congue pharetra id ac nisi. Nam tincidunt luctus lorem, sit amet mattis est porttitor et. Suspendisse potenti. Cras condimentum purus non elementum pharetra. Nulla at porttitor ante. Morbi pellentesque commodo mi, at rutrum dui efficitur in. 5 | 6 | Aliquam a porttitor nisi. Phasellus pellentesque feugiat mi, bibendum dignissim odio aliquet id. Aenean vitae massa erat. Nulla vestibulum vestibulum elit id rhoncus. Aenean sodales molestie dapibus. Nunc vitae nibh eget elit bibendum consectetur sit amet a orci. Ut laoreet velit sagittis mauris porttitor, a laoreet mauris gravida. Pellentesque vehicula leo vel faucibus bibendum. Aliquam dapibus vulputate gravida. Etiam facilisis ligula ut porttitor convallis. Morbi venenatis purus id nisi mattis, vitae commodo est imperdiet. Aliquam elementum nulla ut accumsan vestibulum. Pellentesque blandit lorem elit, ut ornare erat pharetra non. Pellentesque euismod ullamcorper imperdiet. Aenean sollicitudin turpis ut lorem pharetra, non pulvinar augue posuere. Vestibulum risus enim, ultrices eu urna eu, bibendum tincidunt est. 7 | 8 | Maecenas maximus, erat vel faucibus hendrerit, nulla augue dictum erat, at ultricies velit mauris id nibh. Phasellus malesuada luctus dapibus. Fusce odio justo, accumsan id sapien vel, tristique gravida massa. Proin pellentesque, ipsum nec euismod dictum, purus nisl convallis velit, quis pulvinar libero orci eu nisi. Proin eu viverra arcu, nec suscipit orci. Nam a tortor laoreet, auctor erat posuere, imperdiet enim. Nam consectetur erat nisi, sit amet dapibus neque pharetra non. Quisque mollis nulla sed enim hendrerit, vel lacinia mauris iaculis. Donec interdum, est auctor euismod scelerisque, neque lectus pharetra lacus, eu ornare velit mauris quis libero. Nullam quis dolor porta, pulvinar lectus ac, tincidunt ex. Praesent malesuada tempus mollis. Proin id sapien consectetur, semper risus nec, tempor metus. Donec in nisi ac massa accumsan cursus. Mauris consectetur commodo fringilla. 9 | 10 | Fusce ultricies neque vel vehicula ullamcorper. Etiam non tellus nisl. Mauris tellus massa, sodales et dui vel, faucibus malesuada ipsum. Quisque dignissim, ante in placerat venenatis, nulla nisl placerat lacus, eget pellentesque velit nisl at ipsum. Aliquam erat volutpat. Proin quam diam, blandit in felis et, imperdiet volutpat augue. Nam ultricies quam eu efficitur semper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse vel euismod risus. Donec consequat orci quis ex elementum suscipit. Nullam ultrices odio ut turpis molestie convallis. In tempus ipsum sit amet lobortis euismod. Donec hendrerit laoreet elit, non malesuada massa porttitor eu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 11 | 12 | Nunc eleifend nibh vitae convallis pharetra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce a nunc at velit euismod tincidunt. Sed orci nisi, varius convallis erat et, fringilla consequat velit. Curabitur sem felis, pellentesque non ullamcorper eu, accumsan ut enim. Cras sit amet sollicitudin est. Donec quis porta urna. Ut ultricies quis nibh nec venenatis. Morbi pharetra condimentum ipsum. Praesent maximus elit nec ipsum lobortis finibus. 13 | 14 | Nulla facilisi. Sed id ante libero. Fusce non risus eget neque facilisis consequat ac non nisl. Duis aliquam condimentum urna non blandit. Etiam convallis ex in orci ornare facilisis. Praesent vel arcu pellentesque, ultrices lacus at, dapibus mauris. Suspendisse potenti. Fusce luctus sapien quam, vel blandit metus posuere sit amet. Mauris faucibus dolor non turpis auctor cursus. Nulla pretium nulla pulvinar libero suscipit viverra. Suspendisse potenti. Etiam elementum, tellus nec porttitor consequat, dui libero lacinia sem, vel ultricies nunc ex ut risus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. 15 | 16 | Vivamus accumsan maximus nibh id blandit. Pellentesque blandit blandit magna nec vestibulum. Morbi gravida lectus leo, id vehicula quam hendrerit sed. Phasellus congue metus ut varius cursus. Curabitur quam arcu, hendrerit sit amet nulla rutrum, facilisis pulvinar orci. In hac habitasse platea dictumst. Sed a maximus ante. Sed convallis tempor arcu eget blandit. Nulla vel consectetur turpis, dignissim tincidunt mi. 17 | 18 | Sed in est sit amet augue imperdiet condimentum ut at odio. Maecenas auctor sem erat, pretium molestie quam maximus sed. Ut rhoncus orci ut diam pulvinar sodales. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum maximus facilisis commodo. Nunc tempor diam turpis, et condimentum velit aliquam eget. In hac habitasse platea dictumst. Praesent volutpat turpis non pharetra luctus. Quisque ut porta metus. Quisque nec mi ornare, dignissim diam at, posuere mauris. Nullam molestie interdum elit non volutpat. Maecenas libero lectus, rutrum eu porta non, vestibulum in mauris. 19 | 20 | Donec sit amet purus a felis iaculis sollicitudin porttitor non elit. Nullam tincidunt lectus a tincidunt bibendum. Vivamus condimentum, enim non finibus rutrum, enim erat interdum odio, at aliquet turpis dui vel quam. Mauris imperdiet sem quis magna faucibus, a vestibulum risus posuere. Integer dapibus, leo in tincidunt vehicula, elit lacus bibendum ligula, nec facilisis lacus ligula vel neque. Nam id dolor arcu. Cras non facilisis risus. Quisque odio metus, vestibulum quis nunc rhoncus, congue efficitur magna. Morbi ut porta nisl. Vestibulum sed sagittis nunc. Nunc vel condimentum metus. 21 | 22 | Praesent malesuada auctor pellentesque. Integer non eros sit amet ante cursus imperdiet. Donec imperdiet dui neque, non iaculis felis blandit vel. Maecenas justo metus, facilisis vitae lectus id, sodales facilisis arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac orci a mi sollicitudin consequat. Praesent euismod, sem id porttitor porta, nunc mi laoreet orci, eget ullamcorper augue diam a lorem. Nam porta metus vel vehicula pharetra. Duis hendrerit porta ante sit amet auctor. Suspendisse potenti. Nam ut placerat tellus. Vivamus quis auctor neque, ut sagittis quam. Aliquam erat volutpat. 23 | 24 | Aliquam erat volutpat. Mauris mollis tellus nec imperdiet interdum. Phasellus sagittis erat nec consectetur fringilla. Donec lobortis interdum dolor non venenatis. Integer egestas tellus eu eros iaculis maximus. Maecenas dapibus pulvinar odio, a tempus sapien porta fermentum. Integer sagittis dolor in tortor faucibus, ac lacinia velit fermentum. Mauris molestie, nulla id facilisis viverra, enim neque gravida quam, at lobortis orci augue id neque. Aenean ornare eros in accumsan tempus. 25 | 26 | Nullam sed viverra felis. Nulla malesuada nibh a volutpat ultrices. Ut nulla ante, euismod eget porttitor sed, finibus et nunc. Praesent cursus mauris at laoreet tempor. Aliquam vitae mattis risus. Vivamus porta neque vel aliquet pellentesque. Vestibulum tincidunt faucibus ligula, ut iaculis sem. Morbi feugiat tellus id felis vestibulum aliquet. Suspendisse augue nunc, condimentum non erat eget, imperdiet varius velit. Donec accumsan mattis molestie. Suspendisse potenti. In viverra elit elit, sodales eleifend quam vestibulum eu. Mauris sed scelerisque nulla. Donec dapibus tortor in dapibus venenatis. Integer accumsan mi eget sapien posuere, a hendrerit erat suscipit. 27 | 28 | Nunc sed sapien sit amet felis blandit porttitor vitae eu augue. Sed posuere euismod eros sed suscipit. Aliquam erat volutpat. Aenean sit amet mi iaculis turpis faucibus venenatis eu eu neque. Praesent tincidunt dictum tortor, eu tincidunt mauris posuere nec. Curabitur non orci rutrum, malesuada mauris sit amet, commodo libero. Proin risus neque, tincidunt in aliquet nec, fringilla nec massa. Nunc porttitor laoreet nisi eget iaculis. Suspendisse quis arcu maximus, tincidunt elit volutpat, bibendum orci. Aenean sodales, augue elementum convallis dignissim, orci tortor consequat orci, sed sollicitudin ligula ipsum non leo. Fusce egestas rutrum enim, eget venenatis tellus gravida ac. Duis lobortis nisi vitae interdum mattis. 29 | 30 | Mauris faucibus faucibus nunc. Cras at molestie est. Praesent eget neque leo. Morbi tempor sollicitudin erat. Praesent ornare ultricies erat, vel pulvinar neque luctus id. Aliquam posuere auctor nunc, porttitor interdum nulla varius non. Morbi eu nulla id velit accumsan egestas sit amet id orci. Proin et lobortis tortor. Donec lacinia tempus ligula nec tincidunt. Suspendisse in placerat turpis. Cras eleifend diam a venenatis consequat. Donec eu velit id neque commodo tincidunt. Aenean finibus metus ut odio sodales imperdiet. Phasellus ac urna nibh. Praesent viverra accumsan justo, vel gravida ipsum laoreet et. 31 | 32 | Fusce ultricies velit leo, sit amet fermentum velit malesuada non. Sed eget lectus at ipsum porta sodales eget pulvinar neque. Sed vel rutrum neque. Nam sollicitudin interdum vestibulum. Nullam et neque nec sapien porttitor interdum ac quis nisl. Aenean maximus tellus consequat nisi efficitur, a pellentesque ipsum scelerisque. Donec rutrum quam enim, vitae tristique augue sagittis accumsan. Phasellus bibendum odio at odio tincidunt, eget laoreet lorem molestie. Phasellus mauris elit, efficitur ac nunc vel, porta vulputate sapien. In pulvinar tellus vitae purus pellentesque interdum. Pellentesque dapibus magna imperdiet ex porta, sed iaculis elit semper. Quisque at tempor tortor. In lorem nulla, euismod placerat pretium ut, suscipit vitae lectus. Donec finibus tristique libero, sit amet varius dui sodales vel. Fusce auctor et lorem et aliquam. 33 | 34 | Sed tincidunt ornare augue, id malesuada arcu varius faucibus. Ut id gravida ligula. Curabitur efficitur justo id eros luctus blandit. Etiam quam elit, auctor nec ante quis, pulvinar placerat ipsum. Nullam sodales turpis vel lorem sodales, eget pulvinar purus feugiat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut semper enim sit amet leo egestas, finibus dictum leo molestie. Nunc eu feugiat arcu, ut pellentesque justo. Quisque convallis aliquam purus, sed malesuada risus malesuada feugiat. Ut bibendum enim est, eget lacinia mi suscipit vitae. Pellentesque sollicitudin fringilla lorem vel aliquam. Praesent dapibus elit sed metus tincidunt malesuada. Quisque suscipit risus nec nibh varius, sed dictum dolor tempor. 35 | 36 | Aliquam magna arcu, tincidunt vel tristique vel, feugiat eget dui. Sed aliquam sagittis nisi in tempor. Ut vitae leo malesuada, fermentum nisl quis, porttitor dui. Suspendisse elementum, lacus ac hendrerit dictum, sapien dui placerat magna, in egestas felis leo et ante. Curabitur ac molestie est. Sed dapibus neque eget lorem gravida, eu vulputate turpis tempus. Sed fringilla a dui accumsan viverra. Quisque id odio mi. Curabitur facilisis vehicula ipsum, ut vehicula nisi mattis sit amet. Nunc in nisl vitae est eleifend molestie sit amet ac dolor. 37 | 38 | Nullam rutrum massa vitae leo molestie tempus. Duis laoreet turpis dui, eget placerat purus suscipit id. Fusce in dolor hendrerit, rutrum tortor sed, egestas quam. Vestibulum sed felis a turpis mollis dapibus. Nullam facilisis gravida vulputate. Sed sollicitudin id tellus in faucibus. Maecenas convallis est leo, a laoreet dolor venenatis in. 39 | 40 | In sagittis augue varius eros eleifend, sit amet interdum nisi tincidunt. Sed dapibus vulputate ligula, sed consequat metus vulputate in. Sed facilisis justo at turpis aliquam dictum. Mauris hendrerit arcu in nisl auctor viverra. Vivamus orci nunc, commodo non maximus ac, sagittis dignissim dui. Aenean magna magna, iaculis quis odio a, semper accumsan ipsum. Mauris condimentum diam ac posuere venenatis. Aliquam erat volutpat. Vestibulum nec eros a odio venenatis cursus. Vivamus iaculis nisi vel nunc elementum sagittis. Phasellus mollis felis tellus, sed finibus arcu vestibulum id. Nulla laoreet, orci non scelerisque luctus, justo elit auctor ligula, quis accumsan purus mauris et felis. 41 | 42 | Quisque sed ex suscipit, venenatis mauris quis, consectetur lectus. Pellentesque pellentesque ante dui, vel bibendum augue sollicitudin vitae. Ut faucibus nisi in convallis finibus. Maecenas quis diam diam. Sed quis aliquam augue. Integer egestas purus elit, in efficitur sem pellentesque semper. Phasellus convallis quis turpis eu varius. Etiam eu diam at ante dignissim interdum ac eu ante. 43 | 44 | Duis dolor risus, tempus sed ipsum eget, sodales accumsan ligula. Aenean varius euismod libero, sed semper dolor commodo ac. Donec at blandit elit. Nunc et vestibulum orci, ac placerat justo. Sed nec est mattis, efficitur tellus in, imperdiet nisi. Nam fermentum felis urna. Ut consectetur dui quis fermentum tempor. Cras ultricies efficitur justo vitae mollis. Donec sodales felis quis sapien semper commodo. Etiam cursus tempus sapien in interdum. Donec non nisl feugiat, congue massa vel, auctor tellus. Morbi varius, magna vel sodales rutrum, tellus dolor auctor ligula, fermentum sagittis dolor nisi vitae diam. Mauris sollicitudin tempus nisi, at finibus nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 45 | 46 | Suspendisse lorem mi, iaculis a odio nec, porttitor pharetra ex. Sed pretium lectus id lectus dictum suscipit. In hac habitasse platea dictumst. Aliquam a felis in sapien bibendum pellentesque. Cras ligula enim, congue vel dapibus non, condimentum ut odio. Nam eget consectetur lectus, eget aliquam dolor. Phasellus interdum nisl sit amet orci dignissim dapibus. Nam auctor varius nisl eu pulvinar. Curabitur aliquam nibh vitae ultrices mattis. Donec auctor sem eget aliquam molestie. 47 | 48 | Proin mollis a libero vel suscipit. Praesent ullamcorper varius sollicitudin. Quisque vel viverra orci. Mauris quis viverra leo, quis finibus lacus. In hac habitasse platea dictumst. Fusce iaculis porta ex ut suscipit. Proin ipsum eros, lacinia a sem eget, tincidunt auctor urna. Aliquam quis fringilla sem. 49 | 50 | Nulla dapibus commodo efficitur. In erat erat, malesuada et ullamcorper in, eleifend eu magna. In hac habitasse platea dictumst. Morbi in lectus at augue maximus sagittis ac in ex. Nullam vitae neque nec tellus mattis mollis eu in felis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus sed blandit diam. Phasellus eget mi vel justo egestas venenatis. Etiam aliquet est purus, nec dictum dolor varius at. Ut ex augue, pretium eget dictum ut, tempus at turpis. Nulla hendrerit iaculis congue. Etiam commodo cursus viverra. Phasellus fermentum purus ut maximus hendrerit. Sed feugiat ipsum justo, posuere feugiat est semper nec. Nunc cursus, libero vel finibus vulputate, erat urna vestibulum mi, pretium suscipit massa lectus ut mi. Ut nec tristique lacus, ultricies volutpat odio. 51 | 52 | Donec fermentum, enim ac hendrerit semper, magna magna rutrum velit, vestibulum imperdiet eros ex a est. Ut dapibus quis erat at vestibulum. Aenean non massa ac arcu consectetur semper. Mauris nec odio porta, lobortis elit at, dictum justo. Aenean porttitor accumsan nulla, vitae laoreet velit interdum ut. Maecenas hendrerit porta neque ac commodo. Aenean eget pulvinar nisl, vel finibus lectus. Maecenas fringilla pellentesque velit, vel mollis dolor pellentesque sed. Cras ac dignissim massa. Maecenas lobortis leo id felis dapibus, volutpat faucibus metus vulputate. Maecenas dictum enim turpis, ac tincidunt augue imperdiet et. Nullam consequat sapien in nisi tincidunt volutpat. Cras posuere imperdiet felis, auctor ullamcorper nunc luctus id. Sed eget dapibus lorem. Nam sit amet sagittis augue. 53 | 54 | Nulla vitae metus nec quam eleifend finibus. Etiam nisi orci, faucibus sed enim id, fringilla volutpat ipsum. Sed consectetur nulla elementum aliquam venenatis. Donec pretium elit sed mi molestie, in placerat risus tincidunt. Vivamus vulputate nunc dolor, non facilisis sapien fringilla id. Nullam fermentum ipsum sit amet ligula semper, a mollis urna laoreet. Vivamus non sodales lorem, in mattis erat. Praesent dapibus quis sapien vitae porta. Ut accumsan, diam vitae suscipit ullamcorper, nisl metus rhoncus sem, congue lobortis quam metus nec mauris. In consequat egestas libero a ultrices. Nulla consectetur nibh felis, nec finibus odio mollis id. 55 | 56 | Vivamus eleifend orci eget sapien elementum iaculis. Quisque ullamcorper, arcu id vestibulum cursus, mauris risus dignissim augue, ut vehicula nisl nisi ut felis. Suspendisse sit amet sodales nunc. Nam accumsan dignissim cursus. Suspendisse eget porta felis. Praesent aliquet, nisi sed semper molestie, nulla lorem rutrum elit, a aliquet velit neque nec lacus. Sed nec malesuada magna, at cursus justo. Aenean non libero mauris. 57 | 58 | Curabitur in aliquet enim, sit amet rhoncus sapien. Phasellus blandit lorem eu tortor venenatis vestibulum. Nunc sodales sem est, nec iaculis magna tristique ac. Mauris suscipit, nibh vitae facilisis facilisis, urna sem porttitor purus, vitae commodo turpis massa quis eros. Quisque et neque purus. Duis non sodales odio. Aliquam sed tortor porttitor, congue dui vel, fringilla leo. Suspendisse molestie tempus est cursus imperdiet. Donec non convallis dolor. 59 | 60 | Proin elementum ultrices efficitur. Cras mi turpis, porta id mi quis, imperdiet imperdiet purus. Duis sit amet orci egestas, dictum elit nec, feugiat nulla. Sed sollicitudin ligula vitae vulputate lacinia. Fusce bibendum odio sit amet mauris interdum, gravida pellentesque orci iaculis. In hac habitasse platea dictumst. Fusce molestie luctus purus, sed porttitor augue bibendum nec. Integer faucibus augue vitae dictum placerat. Cras dui massa, commodo quis blandit eget, dictum in diam. Donec feugiat massa ut tempus posuere. Praesent semper faucibus scelerisque. Phasellus nec viverra metus, volutpat fermentum lectus. Vestibulum non orci quis sapien tempor sollicitudin. Pellentesque id metus vel diam efficitur ultricies. 61 | """ 62 | -------------------------------------------------------------------------------- /samples/content_heavy/content.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | content: | 3 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis dolor quis orci vestibulum tempor. Donec sodales urna quam, eget consectetur risus venenatis a. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent finibus tortor libero, in semper nisi efficitur eget. Vivamus pharetra diam arcu, a bibendum massa condimentum eu. In ullamcorper varius quam sit amet placerat. Aliquam tempus, dolor vel dapibus facilisis, erat lectus aliquet urna, varius rutrum orci justo vel ex. Donec lobortis congue tellus, quis scelerisque dui suscipit vitae. 4 | 5 | Nulla libero sapien, porttitor eu eros a, maximus viverra eros. Fusce fermentum malesuada cursus. Sed vitae dictum erat, id auctor erat. Suspendisse quis urna commodo, rhoncus justo in, tincidunt dolor. Sed pulvinar eros volutpat ipsum dictum venenatis. Etiam dui nisl, porta nec malesuada et, suscipit sit amet enim. Quisque at dignissim augue. Sed tincidunt, eros at sollicitudin laoreet, odio orci ornare sapien, et tempor arcu diam eget mauris. Vivamus blandit auctor libero ut auctor. Cras laoreet massa ut ipsum suscipit blandit. Nunc vel purus quis enim congue pharetra id ac nisi. Nam tincidunt luctus lorem, sit amet mattis est porttitor et. Suspendisse potenti. Cras condimentum purus non elementum pharetra. Nulla at porttitor ante. Morbi pellentesque commodo mi, at rutrum dui efficitur in. 6 | 7 | Aliquam a porttitor nisi. Phasellus pellentesque feugiat mi, bibendum dignissim odio aliquet id. Aenean vitae massa erat. Nulla vestibulum vestibulum elit id rhoncus. Aenean sodales molestie dapibus. Nunc vitae nibh eget elit bibendum consectetur sit amet a orci. Ut laoreet velit sagittis mauris porttitor, a laoreet mauris gravida. Pellentesque vehicula leo vel faucibus bibendum. Aliquam dapibus vulputate gravida. Etiam facilisis ligula ut porttitor convallis. Morbi venenatis purus id nisi mattis, vitae commodo est imperdiet. Aliquam elementum nulla ut accumsan vestibulum. Pellentesque blandit lorem elit, ut ornare erat pharetra non. Pellentesque euismod ullamcorper imperdiet. Aenean sollicitudin turpis ut lorem pharetra, non pulvinar augue posuere. Vestibulum risus enim, ultrices eu urna eu, bibendum tincidunt est. 8 | 9 | Maecenas maximus, erat vel faucibus hendrerit, nulla augue dictum erat, at ultricies velit mauris id nibh. Phasellus malesuada luctus dapibus. Fusce odio justo, accumsan id sapien vel, tristique gravida massa. Proin pellentesque, ipsum nec euismod dictum, purus nisl convallis velit, quis pulvinar libero orci eu nisi. Proin eu viverra arcu, nec suscipit orci. Nam a tortor laoreet, auctor erat posuere, imperdiet enim. Nam consectetur erat nisi, sit amet dapibus neque pharetra non. Quisque mollis nulla sed enim hendrerit, vel lacinia mauris iaculis. Donec interdum, est auctor euismod scelerisque, neque lectus pharetra lacus, eu ornare velit mauris quis libero. Nullam quis dolor porta, pulvinar lectus ac, tincidunt ex. Praesent malesuada tempus mollis. Proin id sapien consectetur, semper risus nec, tempor metus. Donec in nisi ac massa accumsan cursus. Mauris consectetur commodo fringilla. 10 | 11 | Fusce ultricies neque vel vehicula ullamcorper. Etiam non tellus nisl. Mauris tellus massa, sodales et dui vel, faucibus malesuada ipsum. Quisque dignissim, ante in placerat venenatis, nulla nisl placerat lacus, eget pellentesque velit nisl at ipsum. Aliquam erat volutpat. Proin quam diam, blandit in felis et, imperdiet volutpat augue. Nam ultricies quam eu efficitur semper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse vel euismod risus. Donec consequat orci quis ex elementum suscipit. Nullam ultrices odio ut turpis molestie convallis. In tempus ipsum sit amet lobortis euismod. Donec hendrerit laoreet elit, non malesuada massa porttitor eu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 12 | 13 | Nunc eleifend nibh vitae convallis pharetra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce a nunc at velit euismod tincidunt. Sed orci nisi, varius convallis erat et, fringilla consequat velit. Curabitur sem felis, pellentesque non ullamcorper eu, accumsan ut enim. Cras sit amet sollicitudin est. Donec quis porta urna. Ut ultricies quis nibh nec venenatis. Morbi pharetra condimentum ipsum. Praesent maximus elit nec ipsum lobortis finibus. 14 | 15 | Nulla facilisi. Sed id ante libero. Fusce non risus eget neque facilisis consequat ac non nisl. Duis aliquam condimentum urna non blandit. Etiam convallis ex in orci ornare facilisis. Praesent vel arcu pellentesque, ultrices lacus at, dapibus mauris. Suspendisse potenti. Fusce luctus sapien quam, vel blandit metus posuere sit amet. Mauris faucibus dolor non turpis auctor cursus. Nulla pretium nulla pulvinar libero suscipit viverra. Suspendisse potenti. Etiam elementum, tellus nec porttitor consequat, dui libero lacinia sem, vel ultricies nunc ex ut risus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. 16 | 17 | Vivamus accumsan maximus nibh id blandit. Pellentesque blandit blandit magna nec vestibulum. Morbi gravida lectus leo, id vehicula quam hendrerit sed. Phasellus congue metus ut varius cursus. Curabitur quam arcu, hendrerit sit amet nulla rutrum, facilisis pulvinar orci. In hac habitasse platea dictumst. Sed a maximus ante. Sed convallis tempor arcu eget blandit. Nulla vel consectetur turpis, dignissim tincidunt mi. 18 | 19 | Sed in est sit amet augue imperdiet condimentum ut at odio. Maecenas auctor sem erat, pretium molestie quam maximus sed. Ut rhoncus orci ut diam pulvinar sodales. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum maximus facilisis commodo. Nunc tempor diam turpis, et condimentum velit aliquam eget. In hac habitasse platea dictumst. Praesent volutpat turpis non pharetra luctus. Quisque ut porta metus. Quisque nec mi ornare, dignissim diam at, posuere mauris. Nullam molestie interdum elit non volutpat. Maecenas libero lectus, rutrum eu porta non, vestibulum in mauris. 20 | 21 | Donec sit amet purus a felis iaculis sollicitudin porttitor non elit. Nullam tincidunt lectus a tincidunt bibendum. Vivamus condimentum, enim non finibus rutrum, enim erat interdum odio, at aliquet turpis dui vel quam. Mauris imperdiet sem quis magna faucibus, a vestibulum risus posuere. Integer dapibus, leo in tincidunt vehicula, elit lacus bibendum ligula, nec facilisis lacus ligula vel neque. Nam id dolor arcu. Cras non facilisis risus. Quisque odio metus, vestibulum quis nunc rhoncus, congue efficitur magna. Morbi ut porta nisl. Vestibulum sed sagittis nunc. Nunc vel condimentum metus. 22 | 23 | Praesent malesuada auctor pellentesque. Integer non eros sit amet ante cursus imperdiet. Donec imperdiet dui neque, non iaculis felis blandit vel. Maecenas justo metus, facilisis vitae lectus id, sodales facilisis arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac orci a mi sollicitudin consequat. Praesent euismod, sem id porttitor porta, nunc mi laoreet orci, eget ullamcorper augue diam a lorem. Nam porta metus vel vehicula pharetra. Duis hendrerit porta ante sit amet auctor. Suspendisse potenti. Nam ut placerat tellus. Vivamus quis auctor neque, ut sagittis quam. Aliquam erat volutpat. 24 | 25 | Aliquam erat volutpat. Mauris mollis tellus nec imperdiet interdum. Phasellus sagittis erat nec consectetur fringilla. Donec lobortis interdum dolor non venenatis. Integer egestas tellus eu eros iaculis maximus. Maecenas dapibus pulvinar odio, a tempus sapien porta fermentum. Integer sagittis dolor in tortor faucibus, ac lacinia velit fermentum. Mauris molestie, nulla id facilisis viverra, enim neque gravida quam, at lobortis orci augue id neque. Aenean ornare eros in accumsan tempus. 26 | 27 | Nullam sed viverra felis. Nulla malesuada nibh a volutpat ultrices. Ut nulla ante, euismod eget porttitor sed, finibus et nunc. Praesent cursus mauris at laoreet tempor. Aliquam vitae mattis risus. Vivamus porta neque vel aliquet pellentesque. Vestibulum tincidunt faucibus ligula, ut iaculis sem. Morbi feugiat tellus id felis vestibulum aliquet. Suspendisse augue nunc, condimentum non erat eget, imperdiet varius velit. Donec accumsan mattis molestie. Suspendisse potenti. In viverra elit elit, sodales eleifend quam vestibulum eu. Mauris sed scelerisque nulla. Donec dapibus tortor in dapibus venenatis. Integer accumsan mi eget sapien posuere, a hendrerit erat suscipit. 28 | 29 | Nunc sed sapien sit amet felis blandit porttitor vitae eu augue. Sed posuere euismod eros sed suscipit. Aliquam erat volutpat. Aenean sit amet mi iaculis turpis faucibus venenatis eu eu neque. Praesent tincidunt dictum tortor, eu tincidunt mauris posuere nec. Curabitur non orci rutrum, malesuada mauris sit amet, commodo libero. Proin risus neque, tincidunt in aliquet nec, fringilla nec massa. Nunc porttitor laoreet nisi eget iaculis. Suspendisse quis arcu maximus, tincidunt elit volutpat, bibendum orci. Aenean sodales, augue elementum convallis dignissim, orci tortor consequat orci, sed sollicitudin ligula ipsum non leo. Fusce egestas rutrum enim, eget venenatis tellus gravida ac. Duis lobortis nisi vitae interdum mattis. 30 | 31 | Mauris faucibus faucibus nunc. Cras at molestie est. Praesent eget neque leo. Morbi tempor sollicitudin erat. Praesent ornare ultricies erat, vel pulvinar neque luctus id. Aliquam posuere auctor nunc, porttitor interdum nulla varius non. Morbi eu nulla id velit accumsan egestas sit amet id orci. Proin et lobortis tortor. Donec lacinia tempus ligula nec tincidunt. Suspendisse in placerat turpis. Cras eleifend diam a venenatis consequat. Donec eu velit id neque commodo tincidunt. Aenean finibus metus ut odio sodales imperdiet. Phasellus ac urna nibh. Praesent viverra accumsan justo, vel gravida ipsum laoreet et. 32 | 33 | Fusce ultricies velit leo, sit amet fermentum velit malesuada non. Sed eget lectus at ipsum porta sodales eget pulvinar neque. Sed vel rutrum neque. Nam sollicitudin interdum vestibulum. Nullam et neque nec sapien porttitor interdum ac quis nisl. Aenean maximus tellus consequat nisi efficitur, a pellentesque ipsum scelerisque. Donec rutrum quam enim, vitae tristique augue sagittis accumsan. Phasellus bibendum odio at odio tincidunt, eget laoreet lorem molestie. Phasellus mauris elit, efficitur ac nunc vel, porta vulputate sapien. In pulvinar tellus vitae purus pellentesque interdum. Pellentesque dapibus magna imperdiet ex porta, sed iaculis elit semper. Quisque at tempor tortor. In lorem nulla, euismod placerat pretium ut, suscipit vitae lectus. Donec finibus tristique libero, sit amet varius dui sodales vel. Fusce auctor et lorem et aliquam. 34 | 35 | Sed tincidunt ornare augue, id malesuada arcu varius faucibus. Ut id gravida ligula. Curabitur efficitur justo id eros luctus blandit. Etiam quam elit, auctor nec ante quis, pulvinar placerat ipsum. Nullam sodales turpis vel lorem sodales, eget pulvinar purus feugiat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut semper enim sit amet leo egestas, finibus dictum leo molestie. Nunc eu feugiat arcu, ut pellentesque justo. Quisque convallis aliquam purus, sed malesuada risus malesuada feugiat. Ut bibendum enim est, eget lacinia mi suscipit vitae. Pellentesque sollicitudin fringilla lorem vel aliquam. Praesent dapibus elit sed metus tincidunt malesuada. Quisque suscipit risus nec nibh varius, sed dictum dolor tempor. 36 | 37 | Aliquam magna arcu, tincidunt vel tristique vel, feugiat eget dui. Sed aliquam sagittis nisi in tempor. Ut vitae leo malesuada, fermentum nisl quis, porttitor dui. Suspendisse elementum, lacus ac hendrerit dictum, sapien dui placerat magna, in egestas felis leo et ante. Curabitur ac molestie est. Sed dapibus neque eget lorem gravida, eu vulputate turpis tempus. Sed fringilla a dui accumsan viverra. Quisque id odio mi. Curabitur facilisis vehicula ipsum, ut vehicula nisi mattis sit amet. Nunc in nisl vitae est eleifend molestie sit amet ac dolor. 38 | 39 | Nullam rutrum massa vitae leo molestie tempus. Duis laoreet turpis dui, eget placerat purus suscipit id. Fusce in dolor hendrerit, rutrum tortor sed, egestas quam. Vestibulum sed felis a turpis mollis dapibus. Nullam facilisis gravida vulputate. Sed sollicitudin id tellus in faucibus. Maecenas convallis est leo, a laoreet dolor venenatis in. 40 | 41 | In sagittis augue varius eros eleifend, sit amet interdum nisi tincidunt. Sed dapibus vulputate ligula, sed consequat metus vulputate in. Sed facilisis justo at turpis aliquam dictum. Mauris hendrerit arcu in nisl auctor viverra. Vivamus orci nunc, commodo non maximus ac, sagittis dignissim dui. Aenean magna magna, iaculis quis odio a, semper accumsan ipsum. Mauris condimentum diam ac posuere venenatis. Aliquam erat volutpat. Vestibulum nec eros a odio venenatis cursus. Vivamus iaculis nisi vel nunc elementum sagittis. Phasellus mollis felis tellus, sed finibus arcu vestibulum id. Nulla laoreet, orci non scelerisque luctus, justo elit auctor ligula, quis accumsan purus mauris et felis. 42 | 43 | Quisque sed ex suscipit, venenatis mauris quis, consectetur lectus. Pellentesque pellentesque ante dui, vel bibendum augue sollicitudin vitae. Ut faucibus nisi in convallis finibus. Maecenas quis diam diam. Sed quis aliquam augue. Integer egestas purus elit, in efficitur sem pellentesque semper. Phasellus convallis quis turpis eu varius. Etiam eu diam at ante dignissim interdum ac eu ante. 44 | 45 | Duis dolor risus, tempus sed ipsum eget, sodales accumsan ligula. Aenean varius euismod libero, sed semper dolor commodo ac. Donec at blandit elit. Nunc et vestibulum orci, ac placerat justo. Sed nec est mattis, efficitur tellus in, imperdiet nisi. Nam fermentum felis urna. Ut consectetur dui quis fermentum tempor. Cras ultricies efficitur justo vitae mollis. Donec sodales felis quis sapien semper commodo. Etiam cursus tempus sapien in interdum. Donec non nisl feugiat, congue massa vel, auctor tellus. Morbi varius, magna vel sodales rutrum, tellus dolor auctor ligula, fermentum sagittis dolor nisi vitae diam. Mauris sollicitudin tempus nisi, at finibus nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 46 | 47 | Suspendisse lorem mi, iaculis a odio nec, porttitor pharetra ex. Sed pretium lectus id lectus dictum suscipit. In hac habitasse platea dictumst. Aliquam a felis in sapien bibendum pellentesque. Cras ligula enim, congue vel dapibus non, condimentum ut odio. Nam eget consectetur lectus, eget aliquam dolor. Phasellus interdum nisl sit amet orci dignissim dapibus. Nam auctor varius nisl eu pulvinar. Curabitur aliquam nibh vitae ultrices mattis. Donec auctor sem eget aliquam molestie. 48 | 49 | Proin mollis a libero vel suscipit. Praesent ullamcorper varius sollicitudin. Quisque vel viverra orci. Mauris quis viverra leo, quis finibus lacus. In hac habitasse platea dictumst. Fusce iaculis porta ex ut suscipit. Proin ipsum eros, lacinia a sem eget, tincidunt auctor urna. Aliquam quis fringilla sem. 50 | 51 | Nulla dapibus commodo efficitur. In erat erat, malesuada et ullamcorper in, eleifend eu magna. In hac habitasse platea dictumst. Morbi in lectus at augue maximus sagittis ac in ex. Nullam vitae neque nec tellus mattis mollis eu in felis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus sed blandit diam. Phasellus eget mi vel justo egestas venenatis. Etiam aliquet est purus, nec dictum dolor varius at. Ut ex augue, pretium eget dictum ut, tempus at turpis. Nulla hendrerit iaculis congue. Etiam commodo cursus viverra. Phasellus fermentum purus ut maximus hendrerit. Sed feugiat ipsum justo, posuere feugiat est semper nec. Nunc cursus, libero vel finibus vulputate, erat urna vestibulum mi, pretium suscipit massa lectus ut mi. Ut nec tristique lacus, ultricies volutpat odio. 52 | 53 | Donec fermentum, enim ac hendrerit semper, magna magna rutrum velit, vestibulum imperdiet eros ex a est. Ut dapibus quis erat at vestibulum. Aenean non massa ac arcu consectetur semper. Mauris nec odio porta, lobortis elit at, dictum justo. Aenean porttitor accumsan nulla, vitae laoreet velit interdum ut. Maecenas hendrerit porta neque ac commodo. Aenean eget pulvinar nisl, vel finibus lectus. Maecenas fringilla pellentesque velit, vel mollis dolor pellentesque sed. Cras ac dignissim massa. Maecenas lobortis leo id felis dapibus, volutpat faucibus metus vulputate. Maecenas dictum enim turpis, ac tincidunt augue imperdiet et. Nullam consequat sapien in nisi tincidunt volutpat. Cras posuere imperdiet felis, auctor ullamcorper nunc luctus id. Sed eget dapibus lorem. Nam sit amet sagittis augue. 54 | 55 | Nulla vitae metus nec quam eleifend finibus. Etiam nisi orci, faucibus sed enim id, fringilla volutpat ipsum. Sed consectetur nulla elementum aliquam venenatis. Donec pretium elit sed mi molestie, in placerat risus tincidunt. Vivamus vulputate nunc dolor, non facilisis sapien fringilla id. Nullam fermentum ipsum sit amet ligula semper, a mollis urna laoreet. Vivamus non sodales lorem, in mattis erat. Praesent dapibus quis sapien vitae porta. Ut accumsan, diam vitae suscipit ullamcorper, nisl metus rhoncus sem, congue lobortis quam metus nec mauris. In consequat egestas libero a ultrices. Nulla consectetur nibh felis, nec finibus odio mollis id. 56 | 57 | Vivamus eleifend orci eget sapien elementum iaculis. Quisque ullamcorper, arcu id vestibulum cursus, mauris risus dignissim augue, ut vehicula nisl nisi ut felis. Suspendisse sit amet sodales nunc. Nam accumsan dignissim cursus. Suspendisse eget porta felis. Praesent aliquet, nisi sed semper molestie, nulla lorem rutrum elit, a aliquet velit neque nec lacus. Sed nec malesuada magna, at cursus justo. Aenean non libero mauris. 58 | 59 | Curabitur in aliquet enim, sit amet rhoncus sapien. Phasellus blandit lorem eu tortor venenatis vestibulum. Nunc sodales sem est, nec iaculis magna tristique ac. Mauris suscipit, nibh vitae facilisis facilisis, urna sem porttitor purus, vitae commodo turpis massa quis eros. Quisque et neque purus. Duis non sodales odio. Aliquam sed tortor porttitor, congue dui vel, fringilla leo. Suspendisse molestie tempus est cursus imperdiet. Donec non convallis dolor. 60 | 61 | Proin elementum ultrices efficitur. Cras mi turpis, porta id mi quis, imperdiet imperdiet purus. Duis sit amet orci egestas, dictum elit nec, feugiat nulla. Sed sollicitudin ligula vitae vulputate lacinia. Fusce bibendum odio sit amet mauris interdum, gravida pellentesque orci iaculis. In hac habitasse platea dictumst. Fusce molestie luctus purus, sed porttitor augue bibendum nec. Integer faucibus augue vitae dictum placerat. Cras dui massa, commodo quis blandit eget, dictum in diam. Donec feugiat massa ut tempus posuere. Praesent semper faucibus scelerisque. Phasellus nec viverra metus, volutpat fermentum lectus. Vestibulum non orci quis sapien tempor sollicitudin. Pellentesque id metus vel diam efficitur ultricies. 62 | -------------------------------------------------------------------------------- /samples/invented_server_configuration/configuration.eno: -------------------------------------------------------------------------------- 1 | # production 2 | ## server-a 3 | conf: 4 | ruby=yes 5 | python=no 6 | clean: yes 7 | steps: 8 | - npm 9 | - bundle 10 | - audit 11 | ## server-b 12 | conf: 13 | ruby=yes 14 | python=yes 15 | clean: no 16 | steps: 17 | - npm 18 | - bundle 19 | - audit 20 | # staging < production 21 | -------------------------------------------------------------------------------- /samples/invented_server_configuration/configuration.toml: -------------------------------------------------------------------------------- 1 | [production] 2 | [production.server-a] 3 | steps = [ 4 | "npm", 5 | "bundle", 6 | "audit" 7 | ] 8 | [production.server-a.conf] 9 | ruby = true 10 | python = false 11 | clean = true 12 | [production.server-b] 13 | steps = [ 14 | "npm", 15 | "bundle", 16 | "audit" 17 | ] 18 | [production.server-b.conf] 19 | ruby = true 20 | python = true 21 | clean = false 22 | [staging] 23 | [staging.server-a] 24 | steps = [ 25 | "npm", 26 | "bundle", 27 | "audit" 28 | ] 29 | [staging.server-a.conf] 30 | ruby = true 31 | python = false 32 | clean = true 33 | [staging.server-b] 34 | steps = [ 35 | "npm", 36 | "bundle", 37 | "audit" 38 | ] 39 | [staging.server-b.conf] 40 | ruby = true 41 | python = true 42 | clean = false 43 | -------------------------------------------------------------------------------- /samples/invented_server_configuration/configuration.yaml: -------------------------------------------------------------------------------- 1 | production: &default 2 | server-a: 3 | conf: 4 | ruby: yes 5 | python: no 6 | clean: yes 7 | steps: 8 | - npm 9 | - bundle 10 | - audit 11 | server-b: 12 | conf: 13 | ruby: yes 14 | python: yes 15 | clean: no 16 | steps: 17 | - npm 18 | - bundle 19 | - audit 20 | staging: 21 | <<: *default 22 | -------------------------------------------------------------------------------- /samples/jekyll_post_example/post.eno: -------------------------------------------------------------------------------- 1 | layout: post 2 | title: Welcome to Jekyll! 3 | date: 2015-11-17T16:16:01-06:00 4 | categories: jekyll update 5 | 6 | -- markdown 7 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bundle exec jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. 8 | 9 | To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. 10 | -- markdown 11 | -------------------------------------------------------------------------------- /samples/jekyll_post_example/post.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Welcome to Jekyll!" 4 | date: 2015-11-17 16:16:01 -0600 5 | categories: jekyll update 6 | --- 7 | 8 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bundle exec jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. 9 | 10 | To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. 11 | -------------------------------------------------------------------------------- /samples/jekyll_post_example/post.toml: -------------------------------------------------------------------------------- 1 | layout = "post" 2 | title = "Welcome to Jekyll!" 3 | date = 2015-11-17T16:16:01Z 4 | categories = "jekyll update" 5 | 6 | markdown = """ 7 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bundle exec jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. 8 | 9 | To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. 10 | """ 11 | -------------------------------------------------------------------------------- /samples/jekyll_post_example/post.yaml: -------------------------------------------------------------------------------- 1 | layout: post 2 | title: "Welcome to Jekyll!" 3 | date: 2015-11-17 16:16:01 -0600 4 | categories: jekyll update 5 | markdown: | 6 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bundle exec jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. 7 | 8 | To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. 9 | -------------------------------------------------------------------------------- /samples/jekyll_post_example/source.txt: -------------------------------------------------------------------------------- 1 | Post example taken from https://jekyllrb.com/docs/posts/ 2 | -------------------------------------------------------------------------------- /samples/journey_route_data/journey.eno: -------------------------------------------------------------------------------- 1 | title: Journey to the End of the Night Vienna 2009 2 | date: 2009-08-07 3 | time: 18:30 4 | abstract: Prater Hauptallee - Metalab 5 | # checkpoint 6 | special: start 7 | location: Hauptallee A 8 | coordinates: 48.205870, 16.413690 9 | # checkpoint 10 | location: Ilgplatz 11 | hint: Scientists / Indian Burial Ground 12 | coordinates: 48.219534, 16.405041 13 | ## safezone 14 | shape: circle 15 | center: 48.219513, 16.405041 16 | radius: 20 17 | # checkpoint 18 | location: Krakauerstrasse 27 19 | hint: Fortune Tellers / Playground something 20 | coordinates: 48.226835, 16.396787 21 | # checkpoint 22 | location: Wallensteinplatz 23 | hint: Puzzle / Riddle 24 | coordinates: 48.229600, 16.371639 25 | # checkpoint 26 | location: Bindergasse 3 27 | hint: Bathtub / Childhood memories 28 | coordinates: 48.225857, 16.355580 29 | # checkpoint 30 | location: Servittenkirche Vorplatz 31 | hint: Wohnzimmer setting 32 | coordinates: 48.220560, 16.364078 33 | # checkpoint 34 | special: finish 35 | location: Friedrich-Schmidt-Platz 1 36 | coordinates: 48.211004, 16.356364 37 | -------------------------------------------------------------------------------- /samples/journey_route_data/journey.toml: -------------------------------------------------------------------------------- 1 | title = "Journey to the End of the Night Vienna 2009" 2 | date = 2009-08-07T00:00:00Z 3 | time = "18:30" 4 | abstract = "Prater Hauptallee - Metalab" 5 | [[checkpoint]] 6 | special = "start" 7 | location = "Hauptallee A" 8 | coordinates = "48.205870, 16.413690" 9 | [[checkpoint]] 10 | location = "Ilgplatz" 11 | hint = "Scientists / Indian Burial Ground" 12 | coordinates = "48.219534, 16.405041" 13 | [checkpoint.safezone] 14 | shape = "circle" 15 | center = "48.219513, 16.405041" 16 | radius = 20 17 | [[checkpoint]] 18 | location = "Krakauerstrasse 27" 19 | hint = "Fortune Tellers / Playground something" 20 | coordinates = "48.226835, 16.396787" 21 | [[checkpoint]] 22 | location = "Wallensteinplatz" 23 | hint = "Puzzle / Riddle" 24 | coordinates = "48.229600, 16.371639" 25 | [[checkpoint]] 26 | location = "Bindergasse 3" 27 | hint = "Bathtub / Childhood memories" 28 | coordinates = "48.225857, 16.355580" 29 | [[checkpoint]] 30 | location = "Servittenkirche Vorplatz" 31 | hint = "Wohnzimmer setting" 32 | coordinates = "48.220560, 16.364078" 33 | [[checkpoint]] 34 | special = "finish" 35 | location = "Friedrich-Schmidt-Platz 1" 36 | coordinates = "48.211004, 16.356364" 37 | -------------------------------------------------------------------------------- /samples/journey_route_data/journey.yaml: -------------------------------------------------------------------------------- 1 | title: Journey to the End of the Night Vienna 2009 2 | date: 2009-08-07 3 | time: '18:30' 4 | abstract: Prater Hauptallee - Metalab 5 | checkpoints: 6 | - special: start 7 | location: Hauptallee A 8 | coordinates: 48.205870, 16.413690 9 | - location: Ilgplatz 10 | hint: Scientists / Indian Burial Ground 11 | coordinates: 48.219534, 16.405041 12 | safezone: 13 | shape: circle 14 | center: 48.219513, 16.405041 15 | radius: 20 16 | - location: Krakauerstrasse 27 17 | hint: Fortune Tellers / Playground something 18 | coordinates: 48.226835, 16.396787 19 | - location: Wallensteinplatz 20 | hint: Puzzle / Riddle 21 | coordinates: 48.229600, 16.371639 22 | - location: Bindergasse 3 23 | hint: Bathtub / Childhood memories 24 | coordinates: 48.225857, 16.355580 25 | - location: Servittenkirche Vorplatz 26 | hint: Wohnzimmer setting 27 | coordinates: 48.220560, 16.364078 28 | - special: finish 29 | location: Friedrich-Schmidt-Platz 1 30 | coordinates: 48.211004, 16.356364 31 | -------------------------------------------------------------------------------- /samples/yaml_invoice_example/invoice.eno: -------------------------------------------------------------------------------- 1 | invoice: 34843 2 | date: 2001-01-23 3 | tax: 251.42 4 | total: 4443.52 5 | 6 | -- comments 7 | Late afternoon is best. 8 | Backup contact is Nancy 9 | Billsmer @ 338-4338. 10 | -- comments 11 | 12 | # bill-to 13 | 14 | given: Chris 15 | family: Dumars 16 | 17 | ## address 18 | 19 | -- lines 20 | 458 Walkman Dr. 21 | Suite #292 22 | -- lines 23 | 24 | city: Royal Oak 25 | state: MI 26 | postal: 48046 27 | 28 | # ship-to 29 | 30 | given: Chris 31 | family: Dumars 32 | 33 | ## address 34 | 35 | -- lines 36 | 458 Walkman Dr. 37 | Suite #292 38 | -- lines 39 | 40 | city: Royal Oak 41 | state: MI 42 | postal: 48046 43 | 44 | # product 45 | 46 | sku: BL394D 47 | quantity: 4 48 | description: Basketball 49 | price: 450.00 50 | 51 | # product 52 | 53 | sku: BL4438H 54 | quantity: 1 55 | description: Super Hoop 56 | price : 2392.00 57 | -------------------------------------------------------------------------------- /samples/yaml_invoice_example/invoice.toml: -------------------------------------------------------------------------------- 1 | invoice = 34843 2 | date = 2001-01-23T00:00:00Z 3 | tax = 251.42 4 | total = 4443.52 5 | 6 | comments = ''' 7 | Late afternoon is best. 8 | Backup contact is Nancy 9 | Billsmer @ 338-4338. 10 | ''' 11 | 12 | [bill-to] 13 | 14 | given = "Chris" 15 | family = "Dumars" 16 | 17 | [bill-to.address] 18 | 19 | lines = ''' 20 | 458 Walkman Dr. 21 | Suite #292 22 | ''' 23 | 24 | city = "Royal Oak" 25 | state = "MI" 26 | postal = "48046" 27 | 28 | [ship-to] 29 | 30 | given = "Chris" 31 | family = "Dumars" 32 | 33 | [ship-to.address] 34 | 35 | lines = ''' 36 | 458 Walkman Dr. 37 | Suite #292 38 | ''' 39 | 40 | city = "Royal Oak" 41 | state = "MI" 42 | postal = "48046" 43 | 44 | [[product]] 45 | 46 | sku = "BL394D" 47 | quantity = 4 48 | description = "Basketball" 49 | price = 450.00 50 | 51 | [[product]] 52 | 53 | sku = "BL4438H" 54 | quantity = 1 55 | description = "Super Hoop" 56 | price = 2392.00 57 | -------------------------------------------------------------------------------- /samples/yaml_invoice_example/invoice.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | invoice: 34843 3 | date : 2001-01-23 4 | bill-to: &id001 5 | given : Chris 6 | family : Dumars 7 | address: 8 | lines: | 9 | 458 Walkman Dr. 10 | Suite #292 11 | city : Royal Oak 12 | state : MI 13 | postal : 48046 14 | ship-to: *id001 15 | product: 16 | - sku : BL394D 17 | quantity : 4 18 | description : Basketball 19 | price : 450.00 20 | - sku : BL4438H 21 | quantity : 1 22 | description : Super Hoop 23 | price : 2392.00 24 | tax : 251.42 25 | total: 4443.52 26 | comments: > 27 | Late afternoon is best. 28 | Backup contact is Nancy 29 | Billsmer @ 338-4338. 30 | -------------------------------------------------------------------------------- /samples/yaml_invoice_example/source.txt: -------------------------------------------------------------------------------- 1 | Invoice example taken from http://yaml.org/start.html 2 | --------------------------------------------------------------------------------