mirror of https://github.com/mpastell/Weave.jl
Compare commits
847 Commits
Author | SHA1 | Date |
---|---|---|
Sebastian Pfitzner | 77793c775c | |
Sheehan Olver | ad0885ce00 | |
Sebastian Pfitzner | e10aaefd94 | |
Sebastian Pfitzner | 8ad4e876d3 | |
Sebastian Pfitzner | af2a6e14c9 | |
Sebastian Pfitzner | 20aaefec0a | |
Gerhard Aigner | 2a78676d41 | |
Gerhard Aigner | 59332c1768 | |
Sebastian Pfitzner | db28a69d94 | |
Sheehan Olver | 0b96591f39 | |
Sebastian Pfitzner | a38cec95db | |
Sebastian Pfitzner | 562f8e4ab3 | |
Sebastian Pfitzner | 9f666b3bb5 | |
KristofferC | a63577f69c | |
Xing Shi Cai | 7e0f5641c2 | |
Nicholas W. M. Ritchie | b022a54458 | |
Nicholas W. M. Ritchie | b669a14038 | |
Sebastian Pfitzner | b7941c2811 | |
ExpandingMan | d40e95a4bb | |
xgdgsc | df47ea191f | |
Sebastian Pfitzner | 381de22c7d | |
github-actions[bot] | 06b259a7b0 | |
Sebastian Pfitzner | 749c0c262c | |
Sebastian Pfitzner | 696db1d82b | |
Mike | d4c65729e4 | |
Mike | 1dfb8d76d6 | |
Sebastian Pfitzner | 48c99c791f | |
Sebastian Pfitzner | ec3f464c37 | |
Mike | 4c60bd8d64 | |
Sebastian Pfitzner | e1d31c2ef6 | |
Shuhei Kadowaki | 99916dd70c | |
Sebastian Pfitzner | 6b6f82bed4 | |
Shuhei Kadowaki | b1de7efede | |
Nathan Hattersley | 849cc20e88 | |
Shuhei Kadowaki | 10de1057a3 | |
Shuhei Kadowaki | e753f70f7a | |
PGunnink | 8dc0441b90 | |
Shuhei Kadowaki | c9fc740d72 | |
Shuhei Kadowaki | cc5913e812 | |
JonasIsensee | e02d5ce2fd | |
Shuhei Kadowaki | b583ac2e40 | |
Shuhei Kadowaki | 955675d89a | |
Shuhei Kadowaki | 196d4ca7ce | |
Shuhei Kadowaki | d3a7f2aea7 | |
Shuhei Kadowaki | 7d361bb40d | |
Shuhei Kadowaki | e927495a62 | |
Shuhei Kadowaki | 78befc61b5 | |
Shuhei Kadowaki | c24a262135 | |
Shuhei Kadowaki | 3e8200c2f8 | |
Shuhei Kadowaki | 8f23084471 | |
Shuhei Kadowaki | a1830e0502 | |
Shuhei Kadowaki | 0e662ecdec | |
Fredrik Bagge Carlson | fa71830479 | |
Shuhei Kadowaki | 21d7fbdbea | |
Shuhei Kadowaki | fe3711074b | |
Tor Erlend Fjelde | 766847ec65 | |
Shuhei Kadowaki | 46a0f8bff4 | |
Oscar Dowson | 51f905ca83 | |
Sebastian Pfitzner | b5ba227e75 | |
Sebastian Pfitzner | 74768a7e0f | |
Jonas Isensee | 90d8c8430f | |
Jonas Isensee | a61ade7778 | |
Jonas Isensee | 8ac94989f1 | |
Jonas Isensee | 191282c1e5 | |
Shuhei Kadowaki | d8eca00fd8 | |
Shuhei Kadowaki | 957d12e751 | |
Shuhei Kadowaki | 82c7c2a8c6 | |
Shuhei Kadowaki | ba5bc9ca08 | |
Shuhei Kadowaki | 5f0d9d4627 | |
Shuhei Kadowaki | 676ecc64f9 | |
Shuhei Kadowaki | 2a509d8f96 | |
Shuhei Kadowaki | 9b2a1228cd | |
Shuhei Kadowaki | 785768c728 | |
Shuhei Kadowaki | 7e9c4fb99d | |
Shuhei Kadowaki | 29546b7716 | |
Shuhei Kadowaki | db5308b286 | |
Shuhei Kadowaki | 174585e504 | |
Shuhei Kadowaki | 8206ca2d14 | |
Shuhei Kadowaki | 092adb6805 | |
Shuhei Kadowaki | 872f7c7153 | |
Shuhei Kadowaki | 5ae1fd5cf1 | |
Shuhei Kadowaki | bd447ec8e3 | |
Jonas Isensee | 3dfe817584 | |
Jonas Isensee | 12e148af18 | |
Shuhei Kadowaki | 03079a5dac | |
Shuhei Kadowaki | e179bd098e | |
Shuhei Kadowaki | 4a96f2c19a | |
Shuhei Kadowaki | 7955308a0a | |
Shuhei Kadowaki | 21835644a0 | |
Shuhei Kadowaki | 5a585f845a | |
Shuhei Kadowaki | f077609798 | |
Shuhei Kadowaki | 46a0da597d | |
Shuhei Kadowaki | 2070610a58 | |
Shuhei Kadowaki | 7d6fddc749 | |
Shuhei Kadowaki | dadce5110c | |
Shuhei Kadowaki | 5d3dd15733 | |
Shuhei Kadowaki | 608bb3df4a | |
Shuhei Kadowaki | b569740915 | |
Shuhei Kadowaki | 972869da47 | |
Shuhei Kadowaki | e0a9d044cd | |
Shuhei Kadowaki | 912387c331 | |
Jonas Isensee | 1135c5ddfa | |
Shuhei Kadowaki | c1bc2fd5c5 | |
Shuhei Kadowaki | d586c24792 | |
Shuhei Kadowaki | d468912332 | |
Shuhei Kadowaki | 753afe24d7 | |
Shuhei Kadowaki | c0e7e66ec3 | |
Shuhei Kadowaki | fd07d2db3f | |
Shuhei Kadowaki | 8d95e159e2 | |
Shuhei Kadowaki | 9fac56f681 | |
Shuhei Kadowaki | b709ce8aef | |
Shuhei Kadowaki | 4a89b04759 | |
Shuhei Kadowaki | ec986b387b | |
Jonas Isensee | 5c853150c8 | |
Shuhei Kadowaki | f8b1c5104b | |
Shuhei Kadowaki | d88675d521 | |
Shuhei Kadowaki | e52c30f72e | |
Shuhei Kadowaki | 66c33e6679 | |
Shuhei Kadowaki | cdd653e028 | |
Shuhei Kadowaki | 8515c0dcde | |
Shuhei Kadowaki | 3a7cb360af | |
Shuhei Kadowaki | c7b566aaaa | |
Jonas Isensee | 630ac466e7 | |
Shuhei Kadowaki | 3e6cda8950 | |
Shuhei Kadowaki | f1d8838bc5 | |
Shuhei Kadowaki | 3faa8e2d95 | |
Shuhei Kadowaki | 3ddb1375eb | |
Shuhei Kadowaki | 73bf7fe77f | |
Shuhei Kadowaki | 533667b9ad | |
Shuhei Kadowaki | aa7fd311d8 | |
Shuhei Kadowaki | 0760591021 | |
Shuhei Kadowaki | 04b24ea83b | |
Shuhei Kadowaki | 4b12f3da99 | |
Shuhei Kadowaki | c6b23d4541 | |
Shuhei Kadowaki | ae48729cff | |
Shuhei Kadowaki | 19b4a7974f | |
Shuhei Kadowaki | 0bdab33630 | |
Shuhei Kadowaki | 55d2c975cd | |
Shuhei Kadowaki | ae0dc70ffa | |
Jonas Isensee | 543f99a915 | |
Jonas Isensee | b5477d27ff | |
Jonas Isensee | 9875bc10f7 | |
Jonas Isensee | 45adb8992f | |
Jonas Isensee | 3eba5de7f4 | |
Jonas Isensee | 62d56846f4 | |
Jonas Isensee | 770496b3af | |
Jonas Isensee | 6e99822905 | |
Jonas Isensee | 119b3332aa | |
Shuhei Kadowaki | 9ccf3a2c5e | |
Shuhei Kadowaki | db89118b4c | |
Shuhei Kadowaki | e7637de643 | |
Shuhei Kadowaki | e0e9ae8753 | |
Shuhei Kadowaki | 5b959a972c | |
Shuhei Kadowaki | 788f926067 | |
Fredrik Bagge Carlson | c87782f451 | |
Shuhei Kadowaki | 96de887308 | |
Shuhei Kadowaki | aa63b20e7c | |
Shuhei Kadowaki | cc936f5377 | |
Shuhei Kadowaki | f4ed10b625 | |
Shuhei Kadowaki | 2fdd09b585 | |
Jonas Isensee | e20042848d | |
Shuhei Kadowaki | 1e9ba19db4 | |
Shuhei Kadowaki | 14b56f1667 | |
Shuhei Kadowaki | 227ab2cbf8 | |
Shuhei Kadowaki | 84e91104d5 | |
Shuhei Kadowaki | 44ed8788d5 | |
Shuhei Kadowaki | 022bb216eb | |
Shuhei Kadowaki | e43a2843af | |
Shuhei Kadowaki | bb4ebb105e | |
Shuhei Kadowaki | b0db8b991c | |
Shuhei Kadowaki | dd0c51b6e5 | |
Shuhei Kadowaki | 3d4f04902c | |
Shuhei Kadowaki | e9c9274896 | |
Shuhei Kadowaki | 542f3e3225 | |
Shuhei Kadowaki | 976d822f58 | |
Shuhei Kadowaki | 819079c0f6 | |
Shuhei Kadowaki | b62a744dfe | |
Shuhei Kadowaki | eca4ed2559 | |
Shuhei Kadowaki | 9b55d7e924 | |
Shuhei Kadowaki | 0fc915b748 | |
Shuhei Kadowaki | 39d3d8d91c | |
Shuhei Kadowaki | 125d73982e | |
Shuhei Kadowaki | 0bc0d3b510 | |
Shuhei Kadowaki | b8b9b095b7 | |
Shuhei Kadowaki | 48adeff932 | |
Shuhei Kadowaki | a7de8f5f58 | |
Shuhei Kadowaki | 60fc450c88 | |
Shuhei Kadowaki | 1fb40645ed | |
Shuhei Kadowaki | 9ca328f468 | |
Shuhei Kadowaki | d84504267b | |
Shuhei Kadowaki | 29ff436a00 | |
Shuhei Kadowaki | c24920870d | |
Shuhei Kadowaki | f4caba1561 | |
Shuhei Kadowaki | 3c76b804dc | |
Shuhei Kadowaki | f71a491847 | |
Shuhei Kadowaki | af45cc01ab | |
Shuhei Kadowaki | 31f670b74c | |
Shuhei Kadowaki | 0cdcc72bfb | |
Shuhei Kadowaki | 3ee7dec864 | |
Shuhei Kadowaki | 0f94c7b49c | |
Shuhei Kadowaki | 54ccd9b1ed | |
Shuhei Kadowaki | 3f4ba672b3 | |
Shuhei Kadowaki | 745abe176c | |
Shuhei Kadowaki | 301f9b2f27 | |
Shuhei Kadowaki | ef295e9a24 | |
Shuhei Kadowaki | a03a1d4c34 | |
Shuhei Kadowaki | daec0e618f | |
Shuhei Kadowaki | 129a654b1d | |
Shuhei Kadowaki | 500d77c9ca | |
Shuhei Kadowaki | 8aa8f0c4df | |
Shuhei Kadowaki | ec0c0a327f | |
Shuhei Kadowaki | b4c2bbea45 | |
Shuhei Kadowaki | 5e5cb875cf | |
Shuhei Kadowaki | 576ca2b6c9 | |
Shuhei Kadowaki | 4113402908 | |
Shuhei Kadowaki | 249c94a5c1 | |
Shuhei Kadowaki | 101b170ea6 | |
Shuhei Kadowaki | 6d1732247a | |
Shuhei Kadowaki | b7233b468e | |
Shuhei Kadowaki | 405deb3681 | |
Shuhei Kadowaki | 87ba87d2d1 | |
Shuhei Kadowaki | cec388e94f | |
Shuhei Kadowaki | 0831144393 | |
Shuhei Kadowaki | e60f066d31 | |
Shuhei Kadowaki | f86f5a7bd0 | |
Shuhei Kadowaki | f9daa3a289 | |
Shuhei Kadowaki | 91403b4ec0 | |
Shuhei Kadowaki | 5fb3fae741 | |
Shuhei Kadowaki | 7b53eb8e9e | |
Shuhei Kadowaki | 58bc741b7f | |
Shuhei Kadowaki | a740ba3556 | |
Shuhei Kadowaki | bca3ee7dd1 | |
Shuhei Kadowaki | ba8e9f4724 | |
Shuhei Kadowaki | 6121d21bfb | |
Shuhei Kadowaki | 99a50ad86f | |
Shuhei Kadowaki | 2a6ee38850 | |
Shuhei Kadowaki | 11c720ad7f | |
Shuhei Kadowaki | c1cf566c53 | |
Shuhei Kadowaki | 0d3d3a8c19 | |
Shuhei Kadowaki | 6d91ab6512 | |
Shuhei Kadowaki | 98abd5e92e | |
Shuhei Kadowaki | 6100083c9e | |
Shuhei Kadowaki | 6955ca6be2 | |
Shuhei Kadowaki | 17c2151d86 | |
Shuhei Kadowaki | 492d1f330b | |
Shuhei Kadowaki | 95c3dac962 | |
Shuhei Kadowaki | 42115e7d52 | |
Shuhei Kadowaki | 094ebea6cf | |
Shuhei Kadowaki | 7c2eb23bcd | |
Shuhei Kadowaki | 589e1ce3d1 | |
Shuhei Kadowaki | 1ddff9a1b7 | |
Shuhei Kadowaki | 636e3540c7 | |
Shuhei Kadowaki | bc0f687352 | |
Shuhei Kadowaki | 2c7f3da7cc | |
Shuhei Kadowaki | 423146f981 | |
Shuhei Kadowaki | 2e19930565 | |
Shuhei Kadowaki | de2a6657ea | |
Shuhei Kadowaki | 867ad7c954 | |
Shuhei Kadowaki | 54e50a54cb | |
Shuhei Kadowaki | d809ddf703 | |
Shuhei Kadowaki | e459bfb87d | |
Shuhei Kadowaki | 98e44db659 | |
Shuhei Kadowaki | ede31bcf74 | |
Shuhei Kadowaki | e89d5da250 | |
Shuhei Kadowaki | 4b6fc2d913 | |
Shuhei Kadowaki | c825076e36 | |
Shuhei Kadowaki | 68f72bdfb3 | |
Shuhei Kadowaki | ca42e09f8d | |
Shuhei Kadowaki | a526cb8f15 | |
Shuhei Kadowaki | f1df02c2b7 | |
Shuhei Kadowaki | 4dae2a0816 | |
Shuhei Kadowaki | 8303311d59 | |
Shuhei Kadowaki | 36bdd4f82b | |
Shuhei Kadowaki | 5f7cf529b9 | |
Shuhei Kadowaki | 66d32fabe8 | |
Shuhei Kadowaki | 750b7624e0 | |
Shuhei Kadowaki | 8b910c0d70 | |
Shuhei Kadowaki | 3b8201df04 | |
Shuhei Kadowaki | 79579053f1 | |
Shuhei Kadowaki | d4413a1d78 | |
Shuhei Kadowaki | 5dbe54316b | |
Shuhei Kadowaki | e41202d3ff | |
Shuhei Kadowaki | 14e7635458 | |
Shuhei Kadowaki | ac486c5e1d | |
Shuhei Kadowaki | 9a1b81a026 | |
Shuhei Kadowaki | 4e7fda212d | |
Shuhei Kadowaki | b25300b269 | |
Shuhei Kadowaki | 0c59e92fd7 | |
Shuhei Kadowaki | 2376a9dae9 | |
Shuhei Kadowaki | 020b4353a4 | |
Shuhei Kadowaki | 36bce9cf1f | |
Shuhei Kadowaki | db13be44e3 | |
Shuhei Kadowaki | 95e32c4908 | |
Shuhei Kadowaki | 8bbe31324f | |
Fredrik Bagge Carlson | f126e1c7a9 | |
Fredrik Bagge Carlson | 7e88052db3 | |
Shuhei Kadowaki | 67126a515a | |
Shuhei Kadowaki | 3a3385471b | |
Shuhei Kadowaki | 20fd22ec75 | |
Shuhei Kadowaki | f1e87123f4 | |
Shuhei Kadowaki | d40e21ea35 | |
Shuhei Kadowaki | a759dc10bd | |
Shuhei Kadowaki | b6b4082977 | |
Shuhei Kadowaki | 840f1b3b8f | |
Shuhei Kadowaki | efccb5c7f1 | |
Shuhei Kadowaki | dfb9e63d0e | |
Shuhei Kadowaki | 9e9fe45231 | |
Shuhei Kadowaki | 7a7d8f3dde | |
Shuhei Kadowaki | f8c32c865b | |
Shuhei Kadowaki | 529edaf94e | |
Shuhei Kadowaki | e1365ba9b5 | |
Shuhei Kadowaki | 16bc2d7be9 | |
Shuhei Kadowaki | 545baecdaa | |
Shuhei Kadowaki | 6339303569 | |
Shuhei Kadowaki | 62ae84d32d | |
Shuhei Kadowaki | 1f8514a737 | |
Shuhei Kadowaki | 5fd0bcb9ee | |
Shuhei Kadowaki | 47323b37f7 | |
Shuhei Kadowaki | d8595e266f | |
Shuhei Kadowaki | 230a8c5454 | |
Shuhei Kadowaki | db0aa06f38 | |
Shuhei Kadowaki | 32bddc543f | |
Shuhei Kadowaki | 0f5e3df9aa | |
Shuhei Kadowaki | deeb54dc7c | |
Shuhei Kadowaki | 372974e1ad | |
Sebastian Pfitzner | 7c58a284ee | |
Sebastian Pfitzner | 04ed58102d | |
github-actions[bot] | a250a48499 | |
github-actions[bot] | ae8812de51 | |
Dave Kleinschmidt | 9ae54c80d6 | |
Dave Kleinschmidt | 048603ffe6 | |
Sebastian Pfitzner | ab5db9aa24 | |
Shuhei Kadowaki | c020fea642 | |
Shuhei Kadowaki | 2aa7cb7ca5 | |
Shuhei Kadowaki | 4dfa7da71f | |
Shuhei Kadowaki | 4cfcc61fb6 | |
Shuhei Kadowaki | d9b37f8244 | |
Sebastian Pfitzner | 79a3d73882 | |
Shuhei Kadowaki | d4ce8cdb6b | |
Sebastian Pfitzner | d108e4a1dc | |
Julia TagBot | fd216ca1f5 | |
aviatesk | e18c5f35e3 | |
aviatesk | d0ecc30f52 | |
aviatesk | 6ca6c51ea6 | |
aviatesk | 652b19cd0f | |
Sebastian Pfitzner | 72e7ccfe8a | |
Amin Yahyaabadi | a64fccbf2c | |
Sebastian Pfitzner | 585c4111b6 | |
Sebastian Pech | 05c93b8607 | |
Sebastian Pfitzner | 3d673d0338 | |
Sebastian Pech | c9e26d5638 | |
Sebastian Pech | 0018f0e24c | |
Sebastian Pech | da66a8f272 | |
Sebastian Pfitzner | d31d16581b | |
evalparse | 31d3c2da56 | |
Sebastian Pfitzner | b01b18ea2f | |
Sebastian Pech | bd5ff7031c | |
Sebastian Pfitzner | 9fa28726ed | |
MatFi | 4fcee4d0e2 | |
Sebastian Pfitzner | 3be6245820 | |
Sebastian Pech | fa4a1a629d | |
Sebastian Pech | 1b450b9e3d | |
Sebastian Pech | eeb723981d | |
Sebastian Pech | 474cb6e4b2 | |
Tamas Nagy | 51903c3df3 | |
Sebastian Pech | 4d7a444246 | |
Tamas Nagy | e7e5bd7c7f | |
David Widmann | 18cce8472b | |
Kevin Bonham | 36464be927 | |
ilia-kats | 02134d29d5 | |
Viral B. Shah | 59edca786d | |
Sebastian Pfitzner | ed41be610a | |
Tommy Hofmann | 1c0506342e | |
Sebastian Pfitzner | 9f664ba5a6 | |
Tamas Nagy | 9e462a480b | |
Tamas Nagy | df7f0d1f3c | |
Arnav Sood | 5d3e05511e | |
Tamas Nagy | 6621920bec | |
David Anthoff | 975a67ad44 | |
Konstantinos Samaras-Tsakiris | ea1de0fb9e | |
tshort | bd69ef1f59 | |
Matti Pastell | c9a814759d | |
Matti Pastell | 95e860816c | |
Matti Pastell | 99db6a9406 | |
Matti Pastell | 8194c8a1b8 | |
Matti Pastell | 83e2e0ae20 | |
Matti Pastell | 35addd2b50 | |
Matti Pastell | c33309abf6 | |
Matti Pastell | 4338fc4b07 | |
Matti Pastell | 6f83f1abf5 | |
Matti Pastell | 3488af5534 | |
Matti Pastell | 4ab1c09b8c | |
Matti Pastell | e7a10eacdc | |
Matti Pastell | 37aa0237a8 | |
Matti Pastell | 371cec474f | |
Matti Pastell | 1de36fd1f5 | |
Matti Pastell | 4e70d32901 | |
Matti Pastell | 700e00b329 | |
Matti Pastell | 6082786f92 | |
Matti Pastell | 52f3a23d28 | |
Matti Pastell | d62172ad88 | |
Matti Pastell | 6510ea0556 | |
Matti Pastell | efec59cdbf | |
Matti Pastell | ecb66471a3 | |
Matti Pastell | e9ea54bc1b | |
Matti Pastell | a14b7a8f80 | |
Matti Pastell | 0332137000 | |
Matti Pastell | edd558de0e | |
Matti Pastell | badaaa7dea | |
Matti Pastell | 710b67ca45 | |
Matti Pastell | f2773376d9 | |
Matti Pastell | 6a30aa20f2 | |
Matti Pastell | 73584edd34 | |
Matti Pastell | 8d1bb63b0a | |
Matti Pastell | e52083c42a | |
Matti Pastell | 73536707dc | |
Matti Pastell | 056db5141a | |
Matti Pastell | bad5650027 | |
Matti Pastell | 12f829a0ca | |
Toby Driscoll | 26cf943d25 | |
Matti Pastell | 6e0daf9335 | |
Matti Pastell | 7587b4f9cf | |
Matti Pastell | cb791e8b69 | |
Christopher Rackauckas | 73f0e1e998 | |
schrimpf | adf7338f34 | |
Matti Pastell | 1e630ed825 | |
Matti Pastell | f1a85d3726 | |
Matti Pastell | 972937e4a0 | |
Matti Pastell | 4a7d63bc7e | |
Tamas Nagy | caf64b2407 | |
Dave Kleinschmidt | 4bf8e0e209 | |
Matti Pastell | 0a21a2ec90 | |
Matti Pastell | 36339a07ff | |
Dave Kleinschmidt | d0c71ba556 | |
Matti Pastell | 921b9ec2ba | |
schrimpf | ab09bddcd8 | |
Matti Pastell | bf57bf8a07 | |
Matti Pastell | 6d0779ca4d | |
Matti Pastell | 246f7eef62 | |
Matti Pastell | 73e9e71c3a | |
Matti Pastell | aa4ba7ed52 | |
Matti Pastell | b41b4b4d41 | |
Matti Pastell | af7a6779a5 | |
Matti Pastell | ecc02dcd55 | |
Matti Pastell | d0a2291aa8 | |
Matti Pastell | 9aa01e4b89 | |
Matti Pastell | 2508268500 | |
Matti Pastell | 6217f4fb72 | |
Matti Pastell | c72b7e7668 | |
Matti Pastell | 2dbb5cc696 | |
Matti Pastell | 341edd3784 | |
Matti Pastell | 4cd0b92792 | |
Matti Pastell | 3fc3e3c6e0 | |
Matti Pastell | 3c81cd5bf2 | |
Matti Pastell | 28428e0832 | |
Matti Pastell | a5ba74dcd1 | |
Matti Pastell | 347ddbc45c | |
Matti Pastell | 89e990b1dd | |
Matti Pastell | 5c803db6ae | |
Matti Pastell | bb350ab334 | |
Matti Pastell | bd5e1d9a3b | |
Matti Pastell | 160017b6e8 | |
Matti Pastell | 44455a1fda | |
Matti Pastell | 973274bf22 | |
Matti Pastell | 93bb9ced2d | |
Matti Pastell | f90547cee6 | |
Matti Pastell | b136fa615d | |
Matti Pastell | b5e02cad36 | |
Matti Pastell | e5d2045350 | |
Matti Pastell | 373f5e9d37 | |
Matti Pastell | d72734a828 | |
Matti Pastell | ac26ffe271 | |
Matti Pastell | 7c091ed034 | |
Matti Pastell | 4523b3a58e | |
Matti Pastell | 57724aff67 | |
Matti Pastell | e6cea19d5e | |
Matti Pastell | 0956ce6dff | |
Matti Pastell | 83c506252d | |
Matti Pastell | 7a2150430d | |
Matti Pastell | 01f8810bc3 | |
Matti Pastell | f8978eb560 | |
Matti Pastell | fb854a1d63 | |
femtocleaner[bot] | f04b67f69b | |
Matti Pastell | 53d76a61bb | |
Dave Kleinschmidt | 6ff3bee3e8 | |
Tom Short | 5e1d8c1976 | |
Matti Pastell | 53c2a337f3 | |
Dave Kleinschmidt | b4ebf0cd16 | |
Matti Pastell | ce43dea594 | |
Matti Pastell | 8ab0d66dda | |
Matti Pastell | 1341aed3d0 | |
Matti Pastell | b2b143c22e | |
Matti Pastell | 88d8665e03 | |
Matti Pastell | d19d6b6d81 | |
Matti Pastell | eead8f24a8 | |
Matti Pastell | 51ea08ca88 | |
Matti Pastell | 048b484d83 | |
Matti Pastell | 57c17e05a3 | |
Matti Pastell | 48327bd570 | |
Matti Pastell | 742f00bf6a | |
Matti Pastell | 965eb6dfe9 | |
Matti Pastell | be0ac321b3 | |
Matti Pastell | 5b6d50cf72 | |
Matti Pastell | 484b1fdf23 | |
Matti Pastell | 6dc482d997 | |
Matti Pastell | 15d4cdf512 | |
Matti Pastell | dc566fc69a | |
Matti Pastell | 6c149b383c | |
Matti Pastell | 51641124b5 | |
Matti Pastell | 83b5c8f276 | |
Matti Pastell | 2596670aa3 | |
Matti Pastell | 6ef6a0b739 | |
Matti Pastell | 65af831152 | |
Matti Pastell | e0cd57e6a9 | |
Matti Pastell | 0f0e190dd6 | |
Matti Pastell | 753402529e | |
Matti Pastell | 9e5ad966eb | |
Matti Pastell | 361f404f95 | |
Matti Pastell | c1795e7310 | |
Matti Pastell | eb87de143b | |
Matti Pastell | 8c5bc5633a | |
Matti Pastell | f8ffe9218d | |
Matti Pastell | c54032d99a | |
Matti Pastell | 165f6e71bb | |
Matti Pastell | 1536ad455a | |
Matti Pastell | 5bb5e8994c | |
Matti Pastell | c0ad60d138 | |
Matti Pastell | 6a81c53af3 | |
Matti Pastell | c2f581a31d | |
Matti Pastell | 45a3f46918 | |
Matti Pastell | ebd4f6dbed | |
femtocleaner[bot] | 2693389a3a | |
Matti Pastell | 8c22b41920 | |
Matti Pastell | 95008e5704 | |
Fredrik Bagge Carlson | 3f42023b42 | |
Matti Pastell | a35d57e1cb | |
Timothée Poisot | 6b7e88d465 | |
Matti Pastell | c4c5eb11e3 | |
Elliot Saba | b043542007 | |
Matti Pastell | 96bc072619 | |
Matti Pastell | aaabc2cd4f | |
Matti Pastell | 0213c2f774 | |
Matti Pastell | dffb554c8a | |
Matti Pastell | 4bc5435e6d | |
Matti Pastell | 2e65f08e0e | |
Matti Pastell | 5c83309aa3 | |
Chris Foster | da17ac2cc1 | |
Matti Pastell | 7edd8f8bc3 | |
Tamas K. Papp | 0682ca8c59 | |
Matti Pastell | 562968f9be | |
Matti Pastell | 93c2762653 | |
Maxim Grechkin | 1ab37ae48c | |
Matti Pastell | bdedf37e5b | |
Matti Pastell | 5b7ac28e3c | |
Tamas K. Papp | 3297d07102 | |
Tamas K. Papp | 3176ae88bf | |
Matti Pastell | 32f5728ad6 | |
Matti Pastell | ebcee727aa | |
Matti Pastell | 0131bae775 | |
Matti Pastell | 97f309af19 | |
Matti Pastell | 1915501026 | |
Matti Pastell | 9d4817007e | |
Matti Pastell | b4f5221e3a | |
Matti Pastell | c179d3082c | |
Matti Pastell | 5513656f35 | |
Matti Pastell | 1a54d6a557 | |
Matti Pastell | 38d3b04363 | |
Matti Pastell | bbad66d0b8 | |
Matti Pastell | 1b5c0f819c | |
Matti Pastell | d729d4f878 | |
Matti Pastell | b2ffefdb27 | |
Matti Pastell | 09ecdb6f2c | |
Matti Pastell | d3e0f31f9e | |
Matti Pastell | f39069e40a | |
Matti Pastell | 0ffa04b3fd | |
Matti Pastell | 2e6e83e467 | |
Matti Pastell | 70c850e79e | |
Matti Pastell | 888b732f86 | |
Matti Pastell | b0d2ccdba2 | |
Matti Pastell | 868efa8208 | |
Matti Pastell | c788f5f15e | |
Matti Pastell | b66ae83e37 | |
Matti Pastell | bc1e8738a7 | |
Matti Pastell | 1ec393dc05 | |
Matti Pastell | 6c2f0a7bb5 | |
Matti Pastell | f1b42156e1 | |
Matti Pastell | c5659c03bf | |
Matti Pastell | a984b46b5b | |
Matti Pastell | 090ad87ed9 | |
Matti Pastell | 9a1d655681 | |
Matti Pastell | 2715baa347 | |
Matti Pastell | b61a2a01b0 | |
Matti Pastell | de1e08e1ef | |
Matti Pastell | 3837142f9b | |
Matti Pastell | c7918241f2 | |
Matti Pastell | 9dc99ba602 | |
Matti Pastell | a7cd923e27 | |
Matti Pastell | e10f27b26f | |
Matti Pastell | a4cfebcc17 | |
Matti Pastell | f63fe62445 | |
Matti Pastell | 3da8865a15 | |
Matti Pastell | 7c5fcd24c6 | |
Matti Pastell | 458ef30e90 | |
Matti Pastell | 7c69ce9b0c | |
Matti Pastell | 4d499da343 | |
Matti Pastell | 68b9bfda08 | |
Matti Pastell | d75ae6d86b | |
Matti Pastell | ff79618182 | |
Matti Pastell | c0f3bac70a | |
Matti Pastell | 89859c0898 | |
Matti Pastell | b14cd13063 | |
Matti Pastell | a2b63b8f07 | |
Matti Pastell | 57629c1547 | |
Matti Pastell | 0f66b0cbae | |
David Anthoff | f8fff02777 | |
David Anthoff | 3542374d92 | |
Matti Pastell | d8ba7316fe | |
Matti Pastell | 360713458c | |
Matti Pastell | 832b87d92a | |
Matti Pastell | 0234b3d059 | |
David Anthoff | 2191794f38 | |
Matti Pastell | 33fb6db33c | |
Matti Pastell | 3cbc63b7c3 | |
Matti Pastell | a4891b01a8 | |
Matti Pastell | 96f4fd03b8 | |
Matti Pastell | ad08d4c4ae | |
Matti Pastell | 7222bfa9ab | |
Matti Pastell | c62fb709d1 | |
Matti Pastell | e2c40262dd | |
Matti Pastell | 82cc021f3c | |
Matti Pastell | e3051a7525 | |
Matti Pastell | 13e40cefa8 | |
Matti Pastell | 8a6aac0129 | |
Matti Pastell | db2de48133 | |
Matti Pastell | a6b74156f6 | |
Matti Pastell | 05b0c04b6d | |
Matti Pastell | b2932f1b86 | |
Matti Pastell | c11b390533 | |
Matti Pastell | 262589cfdc | |
Matti Pastell | 606bf9147f | |
Matti Pastell | 84dbf05b3e | |
Matti Pastell | 5fb5a7ab3f | |
Matti Pastell | 277c6f3e0f | |
Matti Pastell | d5bbf4f678 | |
Matti Pastell | 9664acbe85 | |
Matti Pastell | 50127eaa90 | |
Matti Pastell | 6de5ba342c | |
Matti Pastell | 2afd25fd09 | |
Matti Pastell | 1753da1016 | |
Matti Pastell | 434d5d4286 | |
Matti Pastell | d27ba7879c | |
Matti Pastell | 37787be647 | |
Matti Pastell | e0199b2e6e | |
Matti Pastell | daafd8e911 | |
Matti Pastell | ded6ce2c2a | |
Matti Pastell | 9b170349d1 | |
Matti Pastell | d683625444 | |
Matti Pastell | f0bcaf546a | |
Matti Pastell | 718cfc7338 | |
Matti Pastell | 975bd14635 | |
Matti Pastell | 7d556beb11 | |
Matti Pastell | 985b3b1972 | |
Matti Pastell | 76bec5c438 | |
Matti Pastell | 6a68be5161 | |
Matti Pastell | 15157a213a | |
Matti Pastell | 85b661f2cd | |
Matti Pastell | c61adf1230 | |
Matti Pastell | 99fbfeca90 | |
Matti Pastell | 9308081714 | |
Matti Pastell | 6b87fbeb90 | |
Matti Pastell | 7fad94eeb6 | |
Matti Pastell | 56e92c648c | |
Matti Pastell | afb9fabef3 | |
Matti Pastell | 43e850f113 | |
Matti Pastell | 544ae925e2 | |
Matti Pastell | 82e56aa9f3 | |
Matti Pastell | 901050a32f | |
Matti Pastell | 93f9e9ac02 | |
Matti Pastell | 3d30e4fcfc | |
Matti Pastell | 4bc881378b | |
Matti Pastell | 827934dfa6 | |
Matti Pastell | 7bccdd2ab1 | |
Matti Pastell | 10e089379b | |
Matti Pastell | 3bf251bc0d | |
Stephen Eglen | 60ba918a7a | |
Matti Pastell | 8922124d21 | |
Matti Pastell | cbdf0e2886 | |
Matti Pastell | bfd163e50f | |
Matti Pastell | 0ce73efeaa | |
Matti Pastell | 68a8fbdcf4 | |
Matti Pastell | d50770abe1 | |
Matti Pastell | b7908bc2ea | |
Matti Pastell | d2fe2a82e2 | |
Matti Pastell | 00b5829fe9 | |
Matti Pastell | fd1f13eb33 | |
Tony Kelman | 8324d32f01 | |
bramtayl | 7bd1dfa044 | |
Tony Kelman | e1dc9926e0 | |
Tony Kelman | 3ad6d7ae56 | |
Matti Pastell | f48b61c776 | |
Matti Pastell | a11c9eead0 | |
Matti Pastell | d5749ecd7d | |
Michael Hatherly | ef59d52698 | |
Giuseppe Ragusa | bec1cd08d3 | |
= | 0698165193 | |
Matti Pastell | 181869a663 | |
Giuseppe Ragusa | fd3e7e4c87 | |
Giuseppe Ragusa | bd300ed881 | |
Giuseppe Ragusa | 6ab484848d | |
= | e097c2c01e | |
= | 95cfdaf04d | |
= | da5ffa7794 | |
= | 5e929b7ef6 | |
Matti Pastell | 0dd0d3d8af | |
Giuseppe Ragusa | 1834b93cb3 | |
Giuseppe Ragusa | eecef35305 | |
Giuseppe Ragusa | 1d72309959 | |
Giuseppe Ragusa | 4a2062644b | |
Giuseppe Ragusa | cffbb7ff5c | |
Giuseppe Ragusa | 60a234a95d | |
Giuseppe Ragusa | 7a0958cf13 | |
= | a760def865 | |
Matti Pastell | 9caf014c07 | |
Giuseppe Ragusa | bc1d88c8d3 | |
Matti Pastell | 699f5b46e7 | |
Matti Pastell | 30a83667ee | |
Matti Pastell | d5f1fd4d19 | |
Matti Pastell | 3d8bccdb52 | |
Matti Pastell | 244cb9ab17 | |
Matti Pastell | 81bca0543f | |
= | 9f5a141701 | |
= | b6031cd111 | |
= | daa645ac58 | |
= | 2681f19c19 | |
Matti Pastell | e2da54fa54 | |
Matti Pastell | 9d4e68ca5c | |
Matti Pastell | dca852ed89 | |
Matti Pastell | 64fd4daa1d | |
Matti Pastell | 506f48f4dd | |
Matti Pastell | 31392a067f | |
Matti Pastell | da5001bd31 | |
Matti Pastell | 45f8871740 | |
Matti Pastell | 37f0c7f796 | |
Matti Pastell | f24b2157a6 | |
Matti Pastell | 87e7965627 | |
Matti Pastell | 4483f6f052 | |
Matti Pastell | 1ab5351461 | |
Matti Pastell | dcfc315c17 | |
Matti Pastell | 9cd17ca212 | |
Matti Pastell | 8ffef8ff7d | |
Matti Pastell | 6b1722b354 | |
Matti Pastell | 09bde0577d | |
Matti Pastell | 476619eb44 | |
Matti Pastell | 121ace9ec3 | |
Matti Pastell | 985d027939 | |
= | 13670b1620 | |
Matti Pastell | b5ac812ff4 | |
= | 01a235fd88 | |
= | 6ef016cc5f | |
= | 0132cdd33b | |
= | 47317b512b | |
Matti Pastell | d5aaae43fc | |
Matti Pastell | cc2e66e0b9 | |
Matti Pastell | ec00702fe0 | |
Matti Pastell | a9d0120c3d | |
Matti Pastell | 8292c17674 | |
Matti Pastell | 42faaae5de | |
Matti Pastell | 15f6f3b920 | |
Matti Pastell | d2a298a1d6 | |
Matti Pastell | 2b5e8ee968 | |
Matti Pastell | 680c089c1c | |
Matti Pastell | aa66a8d1d0 | |
Matti Pastell | 0c847f2378 | |
Matti Pastell | 50ead387bb | |
Matti Pastell | 54ada93bdd | |
Matti Pastell | 6f4fa68427 | |
Matti Pastell | 3df46a118a | |
Matti Pastell | bbe797fcc8 | |
Matti Pastell | 92a5a372c4 | |
Matti Pastell | 54a9a79e98 | |
Matti Pastell | f62a315dc0 | |
Matti Pastell | 589e0aaf61 | |
Matti Pastell | 1d2c108fa9 | |
Matti Pastell | 65a10335a3 | |
Matti Pastell | 9a7aebc98d | |
Matti Pastell | 34ea7f495e | |
Matti Pastell | bb613d1017 | |
Matti Pastell | d974134ee4 | |
Matti Pastell | 6bec8f19ea | |
Matti Pastell | dca8fa5bf4 | |
Matti Pastell | 9ad7493e1d | |
Matti Pastell | ffcccbb71c | |
Matti Pastell | 363fd98d24 | |
Matti Pastell | 57fdbe72f9 | |
Matti Pastell | a1de2c64e2 | |
Matti Pastell | f7e18f45a3 | |
Matti Pastell | 54663179cb | |
Matti Pastell | 1ede33365b | |
Matti Pastell | 526646bb79 | |
Matti Pastell | f50c94d0ed | |
Matti Pastell | 3c1e0e87a9 | |
Matti Pastell | 0399b57c0e | |
Matti Pastell | a0fbf826c0 | |
Matti Pastell | 8a35d741f6 | |
= | 6ab22417bf | |
= | 4fb521e219 | |
= | 0254a78e27 | |
= | dfd4f6dadd | |
= | 1250b4b0de | |
= | 5dc7be69a9 | |
= | 0e44f9683c | |
= | 178c295605 | |
Matti Pastell | 97fe1a43bd | |
Matti Pastell | 7ed8638658 | |
Matti Pastell | abb21a6d80 | |
Matti Pastell | bf3e88ace0 | |
Art Wild | 3a9388d063 | |
Matti Pastell | e3fd3833eb | |
Matti Pastell | bf69fb7d28 | |
Matti Pastell | e8b69bfa72 | |
Matti Pastell | c2f76c7190 | |
Matti Pastell | 00660a6332 | |
Matti Pastell | c5d91dd6c7 | |
Matti Pastell | 78f04cafbd | |
Matti Pastell | 4af0801afb | |
Matti Pastell | d19b374fe9 | |
Matti Pastell | 053829ca78 | |
Matti Pastell | 6635eb5c74 | |
Matti Pastell | ee262e81a4 | |
Matti Pastell | 91914d675a | |
Matti Pastell | 19304a4613 | |
Matti Pastell | c4dd999294 | |
Matti Pastell | 5d1f5ab4d7 | |
Matti Pastell | e76e823a3d | |
Matti Pastell | 3c4cc04e14 | |
Matti Pastell | 3407564589 | |
Matti Pastell | c4b1f58a28 | |
Matti Pastell | 5871978520 | |
Matti Pastell | 15252000d0 | |
Matti Pastell | c8185984c3 | |
Matti Pastell | 0b56046bb8 | |
Matti Pastell | 25fb2096d3 | |
Matti Pastell | f66e0e41aa | |
Matti Pastell | fb30b28c12 | |
Matti Pastell | 42108cb69d | |
Matti Pastell | fc8f5814f1 | |
Matti Pastell | 0e5468b7bf |
|
@ -0,0 +1 @@
|
|||
* text eol=lf
|
|
@ -0,0 +1 @@
|
|||
custom: https://numfocus.salsalabs.org/donate-to-julia/index.html
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
name: bug report
|
||||
about: create a bug report
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!-- Please search existing issues to avoid duplicates. -->
|
||||
|
||||
## description
|
||||
|
||||
|
||||
## versions
|
||||
|
||||
> `using InteractiveUtils; versioninfo()`:
|
||||
<!-- please paste the the output of `using InteractiveUtils; versioninfo()` in the backticks below -->
|
||||
```julia
|
||||
|
||||
```
|
||||
|
||||
> `using Pkg; Pkg.status()`:
|
||||
<!-- please paste the the output of `using Pkg; Pkg.status()` in the backticks below -->
|
||||
```julia
|
||||
|
||||
```
|
||||
|
||||
|
||||
## minimum reproducible steps
|
||||
|
||||
<!-- if possible, paste here a minimum reproducible example document and steps -->
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
name: enhancement
|
||||
about: suggest an enhancement idea
|
||||
title: "[FR]"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!-- Please search existing issues to avoid duplicates. -->
|
||||
|
||||
## description
|
|
@ -0,0 +1,19 @@
|
|||
name: CompatHelper
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '00 00 * * *'
|
||||
|
||||
jobs:
|
||||
CompatHelper:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: julia-actions/setup-julia@latest
|
||||
with:
|
||||
version: 1.3
|
||||
- name: Pkg.add("CompatHelper")
|
||||
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
|
||||
- name: CompatHelper.main()
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: julia -e 'using CompatHelper; CompatHelper.main()'
|
|
@ -0,0 +1,11 @@
|
|||
name: TagBot
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 * * * *
|
||||
jobs:
|
||||
TagBot:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: JuliaRegistries/TagBot@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -0,0 +1,67 @@
|
|||
# TODO: build docs via github-actions
|
||||
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
jobs:
|
||||
test:
|
||||
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.allow-failure }}
|
||||
strategy:
|
||||
fail-fast: false # don't stop CI even when one of them fails
|
||||
matrix:
|
||||
version:
|
||||
- '1.5'
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macOS-latest
|
||||
# - windows-latest # TODO: test on Windows
|
||||
arch:
|
||||
- x64
|
||||
- x86
|
||||
allow-failure: [false]
|
||||
include:
|
||||
# this is so verbose... any other way to simplify this ?
|
||||
- version: 'nightly'
|
||||
os: ubuntu-latest
|
||||
arch: x64
|
||||
allow-failure: true
|
||||
- version: 'nightly'
|
||||
os: ubuntu-latest
|
||||
arch: x86
|
||||
allow-failure: true
|
||||
- version: 'nightly'
|
||||
os: macOS-latest
|
||||
arch: x64
|
||||
allow-failure: true
|
||||
# - version: 'nightly'
|
||||
# os: windows-latest
|
||||
# arch: x64
|
||||
# allow-failure: true
|
||||
# - version: 'nightly'
|
||||
# os: windows-latest
|
||||
# arch: x86
|
||||
# allow-failure: true
|
||||
exclude:
|
||||
- os: macOS-latest
|
||||
arch: x86
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: julia-actions/setup-julia@v1
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
arch: ${{ matrix.arch }}
|
||||
- uses: julia-actions/julia-buildpkg@latest
|
||||
- uses: julia-actions/julia-runtest@latest
|
||||
- uses: julia-actions/julia-processcoverage@v1
|
||||
- uses: codecov/codecov-action@v1
|
||||
with:
|
||||
file: ./lcov.info
|
||||
flags: unittests
|
||||
name: codecov-umbrella
|
||||
fail_ci_if_error: false
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
@ -1,28 +1,29 @@
|
|||
|
||||
src/*.cov
|
||||
test.jl
|
||||
examples/figures/
|
||||
examples/*.md
|
||||
examples/*.pdf
|
||||
examples/*.html
|
||||
examples/*.rst
|
||||
examples/*.tex
|
||||
test/documents/figures
|
||||
test/documents/output/figures
|
||||
test/documents/output/gadfly_formats_test.txt
|
||||
test/documents/*.tex
|
||||
test/documents/*.md
|
||||
test/documents/*.rst
|
||||
test/documents/*.html
|
||||
test/documents/*.pdf
|
||||
test/documents/chunk_options.jl
|
||||
!test/documents/*ref.*
|
||||
|
||||
|
||||
|
||||
tmp/
|
||||
.idea
|
||||
*.*~
|
||||
*.aux
|
||||
*.log
|
||||
*.out
|
||||
Manifest.toml
|
||||
|
||||
examples/figures/
|
||||
examples/*.md
|
||||
examples/*.pdf
|
||||
examples/*.html
|
||||
examples/*.rst
|
||||
examples/*.tex
|
||||
test/**/cache
|
||||
test/**/figures
|
||||
test/documents/output/gadfly_formats_test.txt
|
||||
test/**/*.tex
|
||||
test/**/*.md
|
||||
test/**/*.rst
|
||||
test/**/*.html
|
||||
test/**/*.pdf
|
||||
test/**/*.png
|
||||
test/**/chunk_options.jl
|
||||
test/**/*.ipynb
|
||||
!test/**/*ref.*
|
||||
|
||||
doc/build
|
||||
doc/site
|
||||
|
||||
.idea
|
||||
*.*~
|
||||
*.aux
|
||||
*.log
|
||||
*.out
|
||||
|
|
30
.travis.yml
30
.travis.yml
|
@ -1,20 +1,14 @@
|
|||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
language: julia
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: "Documentation"
|
||||
julia: 1.5
|
||||
os: linux
|
||||
script:
|
||||
- julia --project=doc/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
|
||||
- julia --project=doc/ doc/make.jl
|
||||
after_success: skip
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
env:
|
||||
matrix:
|
||||
# - JULIAVERSION="juliareleases"
|
||||
- JULIAVERSION="julianightlies"
|
||||
before_install:
|
||||
- sudo add-apt-repository ppa:staticfloat/julia-deps -y
|
||||
- sudo add-apt-repository ppa:staticfloat/${JULIAVERSION} -y
|
||||
- sudo apt-get update -qq -y
|
||||
- sudo apt-get install libpcre3-dev julia python-matplotlib -y
|
||||
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
|
||||
script:
|
||||
- julia -e 'Pkg.init(); Pkg.clone(pwd()); Pkg.resolve();'
|
||||
- xvfb-run julia -e 'Pkg.test("Weave", coverage=true)'
|
||||
after_success:
|
||||
- julia -e 'cd(Pkg.dir("Weave")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
|
||||
|
|
40
LICENSE.md
40
LICENSE.md
|
@ -1,22 +1,20 @@
|
|||
The Weave.jl package is licensed under the MIT "Expat" License:
|
||||
Copyright (c) 2020: Contributors
|
||||
|
||||
> Copyright (c) 2014: Matti Pastell.
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining
|
||||
> a copy of this software and associated documentation files (the
|
||||
> "Software"), to deal in the Software without restriction, including
|
||||
> without limitation the rights to use, copy, modify, merge, publish,
|
||||
> distribute, sublicense, and/or sell copies of the Software, and to
|
||||
> permit persons to whom the Software is furnished to do so, subject to
|
||||
> the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be
|
||||
> included in all copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
## Release notes for Weave.jl
|
||||
|
||||
### v0.10.6 – 2020/10/03
|
||||
|
||||
improvements:
|
||||
- cleaned up chunk rendering (removed unnecessary extra newlines): #401
|
||||
- `WEAVE_ARGS` now can take arbitrary objects: https://github.com/JunoLab/Weave.jl/commit/c24a2621359b5d0af1bb6825f488e58cc11b8a9e
|
||||
- improved docs: #397 by @baggepinnen
|
||||
|
||||
bug fixes
|
||||
- fixed #398: #399
|
||||
- removed unnecessary quote for markdown output: https://github.com/JunoLab/Weave.jl/commit/a1830e05029f33195627ec5dedbacb30af23947e
|
||||
- fixed #386: #396 by @torfjelde
|
||||
|
||||
|
||||
### v0.10 – 2020/05/18
|
||||
|
||||
improvements:
|
||||
- `weave` is now integrated with Juno's progress bar; just call `weave` function inside Juno or use `julia-client: weave-to-html(pdf)` command (#331)
|
||||
- document metadata in YAML header can be given dynamically (#329)
|
||||
- headers are now striped more gracefully; only Weave.jl related header is stripped when weaving to `github` or `hugo` document (#329, #305)
|
||||
- `WeavePlots`/`GadflyPlots` won't be loaded into `Main` module (#322)
|
||||
- un`const` bindings in a sandbox module are correctly cleared, helping GC free as much memory usage as possible (#317)
|
||||
- keep latex figures even if weaving failed (#302)
|
||||
- bunch of documentation improvements (#297, #295)
|
||||
- code size in HTML header is now not hardcoded, leading to more readable font size (#281)
|
||||
|
||||
bug fixes:
|
||||
- display of "big" object is fixed and limited (#311)
|
||||
- fix dependencies issues
|
||||
|
||||
internal:
|
||||
- bunch of internal refactors, code clean up (#330, #327, #325, #321, #320, #319, #318, #313)
|
||||
- internal error now doesn't mess up display system (#316)
|
||||
- format code base (#312)
|
||||
|
||||
breaking change:
|
||||
- `options` YAML key is deprecated, use `weave_options` key instead (#334)
|
||||
- `set_chunk_defaults` is now renamed to `set_chunk_defaults!` (#323)
|
||||
- `restore_chunk_defaults` is now renamed to `restore_chunk_defaults!` (#323)
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### v0.4.1
|
||||
|
||||
* Disable precompilation due to warnings from dependencies
|
||||
* Fix deprecation warnings for Julia 0.6
|
||||
* Fix PyPlot for Julia 0.6
|
||||
* Support citations in `pandoc2html` and `pandoc2pdf` output
|
||||
* Fix extra whitespace when `term=true`
|
||||
* Fix mime type priority for `md2html`
|
||||
|
||||
|
||||
### V0.4.0
|
||||
|
||||
* Support passing arguments to document using `args` option
|
||||
* Add `include_weave` for including code from Weave documents
|
||||
* Add support for inline code chunks
|
||||
* Remove generated figure files when publishing to html and pdf
|
||||
|
||||
|
||||
### v0.3.0
|
||||
|
||||
* Add support for YAML title block
|
||||
* Use Julia markdown for publishing to pdf and html
|
||||
* Add `template`, `highlight_theme`, `latex_cmd` and `css` option to `weave` for customizing html and pdf output
|
||||
* Bug fixes
|
||||
* Fix plotting on Windows
|
||||
* Fix extra whitespace from code chunk output
|
||||
* Improved GR and GLVisualize support with Plots
|
||||
|
||||
|
||||
### v0.2.2
|
||||
|
||||
* Add IJulia notebook as input format
|
||||
* Add `convert_doc` method to convert between input formats
|
||||
|
||||
|
||||
### v0.2.1
|
||||
|
||||
* Fix critical hanging on Windows using proper handling of redirect_stdout
|
||||
* Add support for Plots.jl plotly and plotlyjs backends for including javascipt
|
||||
output in published HTML documents.
|
||||
* Fix semicolons for `term=true`
|
||||
|
||||
|
||||
### v0.2
|
||||
|
||||
* Move to Julia 0.5 only
|
||||
* New `display` and `prompt` chunk options by @gragusa
|
||||
* Implemented fig_width and fig_height chunk option for Plots.jl
|
||||
* Added pre and post chunk hooks, only used internally for now
|
||||
* Automatic detection of plotting library, `:auto` is the new default options
|
||||
* Support for displaying general multimedia objects e.g. Plots.jl and Images.jl
|
||||
now work with weave.
|
||||
* Support for including html, latex and markdown output from objects
|
||||
* New logic for displaying output in script chunks, output is shown by default for:
|
||||
- Writing to stdout
|
||||
- Calling display
|
||||
- Gadfly plots
|
||||
- Variables on their own
|
||||
- If the last line of a chunk is a function call that returns output e.g. plot(1:10)
|
||||
* Bug fixes
|
||||
- Fix parsing of lone variables from chunks
|
||||
- Fix error with md2html formatter and dates #38
|
||||
|
||||
|
||||
### v0.1.2
|
||||
|
||||
27th April 2016
|
||||
|
||||
* Fix a bug with `out_path` for md2html and md2pdf
|
||||
* Fix md2html and md2pdf on Windows
|
||||
* Improve doctype autodetection
|
||||
* Improved regex for parsing markdown input format
|
||||
|
||||
|
||||
### v0.1.1
|
||||
|
||||
* Change pandoc output to use inline images if there is no caption.
|
||||
* Use Documenter.jl for documentation.
|
||||
* Add chunk option `hold`, replaces results = "hold". This way you can use e.g. `hold = true, results=raw`.
|
||||
* Methods for setting and restoring default chunk options for documents.
|
||||
* New output options `md2pdf` and `md2html`, both use pandoc to output pdf
|
||||
and html files directly with own templates.
|
||||
* Restored and improved Winston support.
|
||||
* New input format: scripts with markup in comments
|
||||
* New output format: MultiMarkdown
|
||||
* Added support for figure width in Pandoc
|
||||
* Autodetect input and output formats based on filename
|
||||
* Allow `out_path` be a file or directory.
|
||||
|
||||
|
||||
### v0.1.0
|
||||
|
||||
19th April 2016
|
||||
|
||||
* Updated for Julia 0.4x, drop 0.3x support
|
||||
* Each document is executed in separate sandbox module instead of redefining the same one. Fixes warnings and occasional segfaults.
|
||||
* Change the output of chunks:
|
||||
- Output will be added to the output directly where they are created (default).
|
||||
- Use results = "hold" to push all output after the chunk.
|
||||
* New chunk option: `line_width`.
|
||||
* Winston support is not implemented yet for this version.
|
||||
* Bug fix in wrapping output lines.
|
||||
* Internal changes
|
||||
- Chunks are now represented with their own type. Allows multiple dispatch
|
||||
and easier implementation of new chunks.
|
||||
|
||||
|
||||
### 0.0.4
|
||||
|
||||
4th January 2015
|
||||
|
||||
* Added AsciiDoc formatter
|
||||
* Default plotting library changed to Gadfly
|
||||
* New option: `out_path` for controlling where weaved documents and figures are saved
|
||||
* Command line script `bin/weave.jl` for calling weave from command line
|
||||
|
||||
|
||||
### 0.0.3
|
||||
|
||||
9th December 2014
|
||||
|
||||
* Sandbox module for running code is cleared between documents
|
||||
* Fixed Latex figure handling (with contributions from @wildart)
|
||||
* Changed "tex" format: separate environment for term chunks
|
||||
* Improved test coverage
|
||||
* Fixed a bug with eval=false chunk option.
|
||||
|
||||
|
||||
### 0.0.2
|
||||
|
||||
7th December 2014
|
||||
|
||||
First release:
|
||||
- Noweb and markdown input formats
|
||||
- Support for Gadfly, Winston and PyPlot figures
|
||||
- Term and script chunks
|
||||
- Support for markdown, tex and rst output
|
|
@ -0,0 +1,37 @@
|
|||
name = "Weave"
|
||||
uuid = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"
|
||||
version = "0.10.12"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
Highlights = "eafb193a-b7ab-5a9e-9068-77385905fa72"
|
||||
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||
Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
|
||||
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
||||
RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00"
|
||||
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
|
||||
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
|
||||
|
||||
[compat]
|
||||
Highlights = "0.3.1, 0.4, 0.5"
|
||||
JSON = "0.21"
|
||||
Mustache = "0.4.1, 0.5, 1"
|
||||
Plots = "0.28, 0.29, 1.0"
|
||||
RelocatableFolders = "0.1,0.2,0.3,1"
|
||||
Requires = "1.0"
|
||||
YAML = "0.3, 0.4"
|
||||
julia = "1.2"
|
||||
|
||||
[extras]
|
||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004"
|
||||
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[targets]
|
||||
test = ["DataFrames", "Test"]
|
142
README.md
142
README.md
|
@ -1,38 +1,104 @@
|
|||
# Weave
|
||||
|
||||
[![Build Status](https://travis-ci.org/mpastell/Weave.jl.svg?branch=master)](https://travis-ci.org/mpastell/Weave.jl)[![Coverage Status](https://img.shields.io/coveralls/mpastell/Weave.jl.svg)](https://coveralls.io/r/mpastell/Weave.jl?branch=master)
|
||||
|
||||
Weave is a scientific report generator/literate programming tool
|
||||
for Julia. It resembles [Pweave](http://mpastell.com/pweave) and, Knitr
|
||||
and Sweave.
|
||||
|
||||
You can write your documentation and code in input document using Nowed or Markdown syntax and use `weave` function to execute to document to capture results and figures.
|
||||
|
||||
**Current features**
|
||||
|
||||
* Noweb or markdown syntax for input documents.
|
||||
* Execute code as terminal or "script" chunks.
|
||||
* Capture PyPlot, Gadfly or Winston figures.
|
||||
* Supports LaTex, Pandoc and Github markdown and reStructuredText output
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Run from julia using Gadfly for plots:
|
||||
|
||||
````julia
|
||||
using Weave
|
||||
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"))
|
||||
````
|
||||
|
||||
## Documentation
|
||||
|
||||
Lexicon.jl generated documentation for [master](http://mpastell.github.io/Weave.jl/master/).
|
||||
|
||||
## Contributing
|
||||
|
||||
I will probably add new features to Weave when I need them myself or if they are requested and not too difficult to implement. You can contribute by opening issues on Github or implementing things yourself and making a pull request. I'd also appreciate example documents written using Weave to add to examples.
|
||||
|
||||
## Contributors
|
||||
|
||||
You can see the list of contributors on Github: https://github.com/mpastell/Weave.jl/graphs/contributors. Thanks for the important additions, fixes and comments.
|
||||
# Weave
|
||||
|
||||
![CI](https://github.com/JunoLab/Weave.jl/workflows/CI/badge.svg)
|
||||
[![codecov](https://codecov.io/gh/JunoLab/Weave.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JunoLab/Weave.jl)
|
||||
[![](https://img.shields.io/badge/docs-stable-blue.svg)](http://weavejl.mpastell.com/stable/)
|
||||
[![](https://img.shields.io/badge/docs-dev-blue.svg)](http://weavejl.mpastell.com/dev/)
|
||||
[![](http://joss.theoj.org/papers/10.21105/joss.00204/status.svg)](http://dx.doi.org/10.21105/joss.00204)
|
||||
|
||||
Weave is a scientific report generator/literate programming tool for the [Julia programming language](https://julialang.org/).
|
||||
It resembles
|
||||
[Pweave](http://mpastell.com/pweave),
|
||||
[knitr](https://yihui.org/knitr/),
|
||||
[R Markdown](https://rmarkdown.rstudio.com/),
|
||||
and [Sweave](https://stat.ethz.ch/R-manual/R-patched/library/utils/doc/Sweave.pdf).
|
||||
|
||||
You can write your documentation and code in input document using Markdown, Noweb or ordinal Julia script syntax,
|
||||
and then use `weave` function to execute code and generate an output document while capturing results and figures.
|
||||
|
||||
**Current features**
|
||||
|
||||
- Publish markdown directly to HTML and PDF using Julia or [Pandoc](https://pandoc.org/MANUAL.html)
|
||||
- Execute code as in terminal or in a unit of code chunk
|
||||
- Capture [Plots.jl](https://github.com/JuliaPlots/Plots.jl) or [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl) figures
|
||||
- Supports various input format: Markdown, [Noweb](https://www.cs.tufts.edu/~nr/noweb/), [Jupyter Notebook](https://jupyter.org/), and ordinal Julia script
|
||||
- Conversions between those input formats
|
||||
- Supports various output document formats: HTML, PDF, GitHub markdown, Jupyter Notebook, MultiMarkdown, Asciidoc and reStructuredText
|
||||
- Simple caching of results
|
||||
|
||||
**Citing Weave:** *Pastell, Matti. 2017. Weave.jl: Scientific Reports Using Julia. The Journal of Open Source Software. http://dx.doi.org/10.21105/joss.00204*
|
||||
|
||||
![Weave in Juno demo](https://user-images.githubusercontent.com/40514306/76081328-32f41900-5fec-11ea-958a-375f77f642a2.png)
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
You can install the latest release using Julia package manager:
|
||||
|
||||
```julia
|
||||
using Pkg
|
||||
Pkg.add("Weave")
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```julia
|
||||
using Weave
|
||||
|
||||
# add depencies for the example
|
||||
using Pkg; Pkg.add(["Plots", "DSP"])
|
||||
|
||||
filename = normpath(Weave.EXAMPLE_FOLDER, "FIR_design.jmd")
|
||||
weave(filename, out_path = :pwd)
|
||||
```
|
||||
|
||||
If you have LaTeX installed you can also weave directly to pdf.
|
||||
|
||||
```julia
|
||||
filename = normpath(Weave.EXAMPLE_FOLDER, "FIR_design.jmd")
|
||||
weave(filename, out_path = :pwd, doctype = "md2pdf")
|
||||
```
|
||||
|
||||
NOTE: `Weave.EXAMPLE_FOLDER` just points to [`examples` directory](./examples).
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
Documenter.jl with MKDocs generated documentation:
|
||||
|
||||
[![](https://img.shields.io/badge/docs-stable-blue.svg)](http://weavejl.mpastell.com/stable/)
|
||||
[![](https://img.shields.io/badge/docs-dev-blue.svg)](http://weavejl.mpastell.com/dev/)
|
||||
|
||||
|
||||
## Editor support
|
||||
|
||||
Install [language-weave](https://atom.io/packages/language-weave) to add Weave support to Juno.
|
||||
It allows running code from Weave documents with usual keybindings and allows preview of
|
||||
html and pdf output.
|
||||
|
||||
The [Julia extension for Visual Studio Code](https://www.julia-vscode.org/)
|
||||
adds Weave support to [Visual Studio Code](https://code.visualstudio.com/).
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
You can contribute to this package by opening issues on GitHub or implementing things yourself and making a pull request.
|
||||
We'd also appreciate more example documents written using Weave.
|
||||
|
||||
|
||||
## Contributors
|
||||
|
||||
You can see the list of contributors on GitHub: https://github.com/JunoLab/Weave.jl/graphs/contributors .
|
||||
Thanks for the important additions, fixes and comments.
|
||||
|
||||
|
||||
## Example projects using Weave
|
||||
|
||||
- [DiffEqTutorials.jl](https://github.com/JuliaDiffEq/DiffEqTutorials.jl) uses Weave to output tutorials (`.jmd` documents) to html, pdf and Jupyter notebooks.
|
||||
- [TuringTutorials](https://github.com/TuringLang/TuringTutorials) uses Weave to convert notebooks to html.
|
||||
|
||||
## Related packages
|
||||
|
||||
- [Literate.jl](https://github.com/fredrikekre/Literate.jl) can be used to generate Markdown and Jupyter notebooks directly from Julia source files with markdown in comments.
|
||||
- [Quarto](https://quarto.org) can generate Jupyter notebooks, HTML, or PDF directly from a Markdown format containing Julia code blocks, and also works with R and Python.
|
||||
|
|
30
RELEASE.md
30
RELEASE.md
|
@ -1,30 +0,0 @@
|
|||
|
||||
# Release notes for Weave.jl
|
||||
|
||||
### Changes in master
|
||||
|
||||
* Added AsciiDoc formatter
|
||||
* Default plotting library changed to Gadfly
|
||||
* New option: `out_path` for controlling where weaved documents and figures are saved
|
||||
* Command line script `bin/weave.jl` for calling weave from command line
|
||||
|
||||
### 0.0.3
|
||||
|
||||
9th December 2014
|
||||
|
||||
* Sandbox module for running code is cleared between documents
|
||||
* Fixed Latex figure handling (with contributions from @wildart)
|
||||
* Changed "tex" format: separate environment for term chunks
|
||||
* Improved test coverage
|
||||
* Fixed a bug with eval=false chunk option.
|
||||
|
||||
|
||||
### 0.0.2
|
||||
|
||||
7th December 2014
|
||||
|
||||
* First release
|
||||
* Noweb and markdown input formats
|
||||
* Support for Gadfly, Winston and PyPlot figures
|
||||
* Term and script chunks
|
||||
* Support for markdown, tex and rst output
|
11
bin/weave.jl
11
bin/weave.jl
|
@ -14,16 +14,14 @@ ap = ArgParseSettings("Weave Julia documents using Weave.jl",
|
|||
help = "source document(s)"
|
||||
required = true
|
||||
"--doctype"
|
||||
arg_type = String
|
||||
default = "pandoc"
|
||||
default = nothing
|
||||
help = "output format"
|
||||
"--plotlib"
|
||||
arg_type = String
|
||||
default = "Gadfly"
|
||||
help = "output format"
|
||||
"--informat"
|
||||
arg_type = String
|
||||
default = "noweb"
|
||||
default = nothing
|
||||
help = "output format"
|
||||
"--out_path"
|
||||
arg_type = String
|
||||
|
@ -41,9 +39,10 @@ end
|
|||
args = ArgParse.parse_args(ap)
|
||||
source = args["source"]
|
||||
delete!(args, "source")
|
||||
args_col = {}
|
||||
args_col = []
|
||||
|
||||
#Check for special values of out_path
|
||||
|
||||
if args["out_path"] == ":doc"
|
||||
args["out_path"] = :doc
|
||||
elseif args["out_path"] == ":pwd"
|
||||
|
@ -51,7 +50,7 @@ elseif args["out_path"] == ":pwd"
|
|||
end
|
||||
|
||||
for (key, val) in args
|
||||
push!(args_col, (parse(key), val))
|
||||
push!(args_col, (Meta.parse(key), val))
|
||||
end
|
||||
|
||||
for s=source
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[deps]
|
||||
DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2"
|
||||
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
|
||||
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,29 @@
|
|||
using Documenter, Weave
|
||||
|
||||
CI_FLG = get(ENV, "CI", nothing) == "true"
|
||||
|
||||
makedocs(
|
||||
modules = [Weave],
|
||||
format = Documenter.HTML(
|
||||
prettyurls = CI_FLG,
|
||||
canonical = "http://weavejl.mpastell.com/stable/",
|
||||
),
|
||||
sitename = "Weave.jl",
|
||||
pages = [
|
||||
"index.md",
|
||||
"getting_started.md",
|
||||
"usage.md",
|
||||
"publish.md",
|
||||
"chunk_options.md",
|
||||
"header.md",
|
||||
"notebooks.md",
|
||||
"function_index.md",
|
||||
],
|
||||
)
|
||||
|
||||
CI_FLG && include("make_examples.jl")
|
||||
|
||||
deploydocs(
|
||||
repo = "github.com/JunoLab/Weave.jl.git",
|
||||
push_preview = true,
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
using Weave
|
||||
|
||||
let start_dir = pwd()
|
||||
cd(@__DIR__)
|
||||
|
||||
weave("../examples/FIR_design.jmd", doctype = "pandoc", out_path = "build/examples")
|
||||
weave("../examples/FIR_design.jmd", doctype = "md2html", out_path = "build/examples")
|
||||
weave("../examples/FIR_design_plots.jl", doctype = "md2html", out_path = "build/examples")
|
||||
|
||||
# PDF outputs
|
||||
if haskey(ENV, "TRAVIS")
|
||||
# in Travis, just cp already generated PDFs
|
||||
cp("assets/FIR_design.pdf", "build/examples/FIR_design.pdf", force = true)
|
||||
cp("assets/FIR_design_plots.pdf", "build/examples/FIR_design_plots.pdf", force = true)
|
||||
else
|
||||
# otherwise try to generate them
|
||||
try
|
||||
weave("../examples/FIR_design.jmd", doctype = "md2pdf", out_path = "assets")
|
||||
weave("../examples/FIR_design_plots.jl", doctype = "md2pdf", out_path = "assets")
|
||||
catch err
|
||||
@error err
|
||||
end
|
||||
end
|
||||
|
||||
cp("../examples/FIR_design.jmd", "build/examples/FIR_design.jmd", force = true)
|
||||
cp("build/examples/FIR_design.md", "build/examples/FIR_design.txt", force = true)
|
||||
cp("../examples/FIR_design_plots.jl", "build/examples/FIR_design_plots.jl", force = true)
|
||||
|
||||
cd(start_dir)
|
||||
end
|
108
doc/manual.md
108
doc/manual.md
|
@ -1,108 +0,0 @@
|
|||
|
||||
This is the documentation of [Weave.jl](http://github.com/mpastell/weave.jl). Weave is a scientific report generator/literate programming tool
|
||||
for Julia. It resembles [Pweave](http://mpastell.com/pweave) and, Knitr
|
||||
and Sweave.
|
||||
|
||||
You can write your documentation and code in input document using Nowed or Markdown syntax and use `weave` function to execute to document to capture results and figures.
|
||||
|
||||
**Current features**
|
||||
|
||||
* Noweb or markdown syntax for input documents.
|
||||
* Execute code as terminal or "script" chunks.
|
||||
* Capture PyPlot, Gadfly or Winston figures.
|
||||
* Supports LaTex, Pandoc and Github markdown and reStructuredText output
|
||||
|
||||
# Document syntax
|
||||
|
||||
Weave uses noweb or markdown syntax for defining the code chunks and documentation chunks.
|
||||
|
||||
## Noweb
|
||||
|
||||
### Code chunks
|
||||
start with a line marked with `<<>>=` or `<<options>>=` and end with line marked with `@`. The code between the start and end markers is executed and the output is captured to the output document. See for options below.
|
||||
|
||||
|
||||
|
||||
### Documentation chunks
|
||||
|
||||
Are the rest of the document (between `@` and `<<>>=` lines and the first chunk be default) and can be written with several different markup languages.
|
||||
|
||||
[Sample document]( https://github.com/mpastell/Weave.jl/blob/master/examples/julia_sample.mdw)
|
||||
|
||||
## Markdown
|
||||
|
||||
Markdown code chunks are defined using fenced code blocks. [See sample document:](https://github.com/mpastell/Weave.jl/blob/master/examples/gadfly_sample.jmd)
|
||||
|
||||
# Chunk options
|
||||
|
||||
I've tried to follow [Knitr](http://yihui.name/knitr/options)'s naming for chunk options, but not all options are implemented.
|
||||
|
||||
Options are separated using ";" and need to be valid Julia expressions. Example: A code chunk that saves and displays a 12 cm wide image and hides the source code:
|
||||
|
||||
```julia
|
||||
<<fig_width=5; echo=false >>=
|
||||
using Gadfly
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
@
|
||||
```
|
||||
|
||||
Weave currently supports the following chunk options with the following defaults:
|
||||
|
||||
|
||||
**Options for code**
|
||||
|
||||
* `echo = true`. Echo the code in the output document. If `false` the source code will be hidden.
|
||||
* `results = "markup"`. The output format of the printed results. "markup" for literal block, "hidden" for hidden results or anything else for raw output (I tend to use ‘tex’ for Latex and ‘rst’ for rest. Raw output is useful if you wan’t to e.g. create tables from code chunks.
|
||||
* `eval = true`. Evaluate the code chunk. If false the chunk won’t be executed.
|
||||
* `term=false`. If true the output emulates a REPL session. Otherwise only stdout and figures will be included in output.
|
||||
* `label`. Chunk label, will be used for figure labels in Latex as fig:label
|
||||
* `wrap=true`. Wrap long lines from output.
|
||||
|
||||
**Options for figures**
|
||||
|
||||
* `fig_width`. Figure width defined in markup, default depends on the output format.
|
||||
* `out_width`. Width of saved figure.
|
||||
* `out_height`. Height of saved figure.
|
||||
* `dpi`=96. Resolution of saved figures.
|
||||
* `fig_cap`. Figure caption.
|
||||
* `label`. Chunk label, will be used for figure labels in Latex as fig:label
|
||||
* `fig_ext`. File extension (format) of saved figures.
|
||||
* `fig_pos="htpb"`. Figure position in Latex.
|
||||
* `fig_env="figure"`. Figure environment in Latex.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
Run from julia using Gadfly for plots:
|
||||
|
||||
```julia
|
||||
using Weave
|
||||
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"))
|
||||
```
|
||||
|
||||
Using Winston for plots (Julia 0.3 only):
|
||||
|
||||
```julia
|
||||
weave(Pkg.dir("Weave","examples","winston_sample.mdw"),
|
||||
plotlib="Winston", doctype="pandoc")
|
||||
```
|
||||
|
||||
Using PyPlot:
|
||||
|
||||
```julia
|
||||
weave(Pkg.dir("Weave","examples","julia_sample.mdw"), plotlib="PyPlot")
|
||||
```
|
||||
|
||||
## File formats
|
||||
|
||||
You can get a list of supported output formats:
|
||||
|
||||
```julia
|
||||
julia> list_out_formats()
|
||||
pandoc: Pandoc markdown
|
||||
rst: reStructuredText and Sphinx
|
||||
texminted: Latex using minted for highlighting
|
||||
github: Github markdown
|
||||
tex: Latex with custom code environments
|
||||
```
|
|
@ -0,0 +1,81 @@
|
|||
# [Chunk Options](@id chunk-options)
|
||||
|
||||
You can use chunk options to configure how each chunk is evaluated, rendered, etc.
|
||||
Most of the ideas came from [chunk options in RMarkdown](http://yihui.name/knitr/options).
|
||||
|
||||
|
||||
## Syntax
|
||||
|
||||
Chunk options come after [code chunk](@ref code-chunks) header.
|
||||
There are two (slightly) different syntax to write them:
|
||||
- (Julia's toplevel expression) options are separated by semicolon (`;`)
|
||||
- (RMarkdown style) options are separated by comma (`,`)
|
||||
|
||||
Let's take a look at examples. All the following code chunk header are valid,
|
||||
and so configured to hide the source code from generated output (`echo = false`)
|
||||
and displays figures with 12cm width (`out_width = "12cm"`):
|
||||
```md
|
||||
```julia; echo = false; out_width = "12cm"
|
||||
|
||||
```{julia; echo = false; out_width = "12cm"}
|
||||
|
||||
```julia, echo = false, out_width = "12cm"
|
||||
|
||||
```{julia, echo = false, out_width = "12cm"}
|
||||
```
|
||||
|
||||
|
||||
## Weave Chunk Options
|
||||
|
||||
Weave currently supports the following chunk options:
|
||||
we've mostly followed [RMarkdown's namings](http://yihui.name/knitr/options), but not all options are implemented.
|
||||
|
||||
### Evaluation
|
||||
|
||||
- `eval = true`: Evaluate the code chunk. If `false` the chunk won’t be executed.
|
||||
- `error = true`: If `true` [`weave`](@ref) won't stop on errors and rather they will be included in output document. If `false`, [`weave`](@ref) will halt on any of un-caught errors.
|
||||
- `cache = false`: Cache results, depending on `cache` parameter on [`weave`](@ref) function.
|
||||
- `tangle = true`: Set tangle to `false` to exclude chunk from tangled code.
|
||||
|
||||
### Rendering
|
||||
|
||||
- `echo = true`: Echo the code in the output document. If `false` the source code will be hidden.
|
||||
- `results = "markup"`: The output format of the printed results. `"markup"` for literal block, `"hidden"` for hidden results, or anything else for raw output (I tend to use `"tex"` for Latex and `"rst"` for rest). Raw output is useful if you want to e.g. create tables from code chunks.
|
||||
- `term = false`: If `true` the output emulates a REPL session. Otherwise only stdout and figures will be included in output.
|
||||
- `wrap = true`: Wrap long lines from output.
|
||||
- `line_width = 75`: Line width for wrapped lines.
|
||||
- `hold = false`: Hold all results until the end of the chunk.
|
||||
|
||||
### Figures
|
||||
|
||||
- `label = nothing`: Chunk label, will be used for figure labels in Latex as `fig:label`.
|
||||
- `fig_width = 6`: Figure width passed to plotting library.
|
||||
- `fig_height = 4`: Figure height passed to plotting library.
|
||||
- `out_width`: Width of saved figure in output markup e.g. `"50%"`, `"12cm"`, `0.5\linewidth`
|
||||
- `out_height`: Height of saved figure in output markup
|
||||
- `dpi = 96`: Resolution of saved figures.
|
||||
- `fig_cap`: Figure caption.
|
||||
- `fig_ext`: File extension (format) of saved figures.
|
||||
- `fig_pos = "!h"`: Figure position in Latex, e.g.: `"ht"`.
|
||||
- `fig_env = "figure"`: Figure environment in Latex.
|
||||
|
||||
|
||||
## Default Chunk Options
|
||||
|
||||
You can set the default chunk options (and `weave` arguments) for a document using `weave_options` key in YAML [Header Configuration](@ref).
|
||||
E.g. to set the default `out_width` of all figures you can use:
|
||||
|
||||
```yaml
|
||||
---
|
||||
weave_options:
|
||||
out_width : 50%
|
||||
---
|
||||
```
|
||||
|
||||
You can also set or change the default chunk options for a document either before weave using the `set_chunk_defaults` function.
|
||||
|
||||
```@docs
|
||||
set_chunk_defaults!
|
||||
get_chunk_defaults
|
||||
restore_chunk_defaults!
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
# Function index
|
||||
|
||||
```@index
|
||||
```
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
# Getting started
|
||||
|
||||
The best way to get started using Weave.jl is to look at the example input and output documents.
|
||||
Examples for different formats are included in the package's [`examples`](https://github.com/JunoLab/Weave.jl/tree/master/examples) directory.
|
||||
|
||||
First have a look at source document using markdown code chunks and [Plots.jl](https://github.com/JuliaPlots/Plots.jl) for figures:
|
||||
|
||||
All the different format documents below are generated from a single Weave document [`FIR_design.jmd`](../examples/FIR_design.jmd):
|
||||
- HTML: [`FIR_design.html`](../examples/FIR_design.html)
|
||||
- PDF: [`FIR_design.pdf`](../examples/FIR_design.pdf)
|
||||
- Pandoc markdown: [`FIR_design.txt`](../examples/FIR_design.txt)
|
||||
|
||||
!!! note
|
||||
Producing PDF output requires that you have XeLateX installed.
|
||||
|
||||
Add dependencies for the example if needed:
|
||||
|
||||
```julia
|
||||
using Pkg; Pkg.add.(["Plots", "DSP"])
|
||||
```
|
||||
|
||||
Weave the files to your working directory:
|
||||
|
||||
```julia
|
||||
using Weave
|
||||
|
||||
filename = normpath(Weave.EXAMPLE_FOLDER, "FIR_design.jmd")
|
||||
|
||||
# Julia markdown to HTML
|
||||
weave(filename; doctype = "md2html", out_path = :pwd)
|
||||
|
||||
# Julia markdown to PDF
|
||||
weave(filename; doctype = "md2pdf", out_path = :pwd)
|
||||
|
||||
# Julia markdown to Pandoc markdown
|
||||
weave(filename; doctype = "pandoc", out_path = :pwd)
|
||||
```
|
||||
|
||||
!!! tips
|
||||
`Weave.EXAMPLE_FOLDER` points to [the `examples` directory](https://github.com/JunoLab/Weave.jl/tree/master/examples).
|
|
@ -0,0 +1,101 @@
|
|||
# Header Configuration
|
||||
|
||||
When `weave`ing a markdown document, you use YAML header to provide additional metadata and configuration options.
|
||||
A YAML header should be in the beginning of the input document delimited with `---`.
|
||||
|
||||
|
||||
!!! warning
|
||||
YAML header configuration is only supported when `weave`ing [markdown or Noweb syntax documents](@ref document-syntax).
|
||||
|
||||
|
||||
## Document Metadata
|
||||
|
||||
You can set additional document metadata in YAML header.
|
||||
When `weave`ing to Julia markdown documents to HTML or PDF, Weave respects the following metadata specification:
|
||||
- `title`
|
||||
- `author`
|
||||
- `date`
|
||||
|
||||
An example:
|
||||
```yaml
|
||||
---
|
||||
title : Header Example
|
||||
author : Shuhei Kadowaki
|
||||
date: 16th May 2020
|
||||
---
|
||||
```
|
||||
|
||||
!!! note
|
||||
You can also have other metadata, but they won't appear in the resulting HTML and PDF.
|
||||
If you weave to Julia markdown to GitHub/Hugo markdown, all the metadata will be preserved.
|
||||
|
||||
### Dynamic Metadata
|
||||
|
||||
The metadata can be given "dynamically"; if you have [inline code](@ref) within YAML header, they will be evaluated _after_ evaluating all the chunks and replaced with the results.
|
||||
|
||||
The example document below will set `date` metadata dynamically.
|
||||
Note that `Date` is available since the chunk is evaluated first.
|
||||
```md
|
||||
---
|
||||
title : Header Example
|
||||
author : Shuhei Kadowaki
|
||||
date: `j import Dates; Dates.Date(Dates.now())`
|
||||
---
|
||||
|
||||
```julia; echo = false
|
||||
using Dates
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Each of keyword arguments of [`weave`](@ref) can be set in the YAML header under `options` field.
|
||||
You can also set [Chunks Options](@ref) there that will be applied globally.
|
||||
|
||||
The example below sets `out_path` and `doctype` options and overwrites `term` and `wrap` chunk options:
|
||||
```yaml
|
||||
---
|
||||
title : Header Example
|
||||
author : Shuhei Kadowaki
|
||||
date: 16th May 2020
|
||||
weave_options:
|
||||
out_path: relative/path/to/this/document
|
||||
doctype: github
|
||||
term: true
|
||||
wrap: false
|
||||
---
|
||||
```
|
||||
|
||||
!!! note
|
||||
- configurations specified within the YAML header have higher precedence than those specified via `weave` keyword arguments
|
||||
- chunk options specified within each chunk have higher precedence than the global global chunk options specified within the YAML header
|
||||
|
||||
!!! warning
|
||||
As opposed to metadata, _most_ of those configuration options can't be given dynamically (i.e. can't be via inline code),
|
||||
since they are needed for evaluation of chunks themselves.
|
||||
But some configuration options that are needed "formatting" document can still be given dynamically:
|
||||
- `template`
|
||||
- `css`
|
||||
- `highlight_theme`
|
||||
- `pandoc_options`
|
||||
- `latex_cmd`
|
||||
- `keep_unicode`
|
||||
|
||||
See also: [`weave`](@ref)
|
||||
|
||||
|
||||
## Format Specific Options
|
||||
|
||||
The header configurations can be format specific.
|
||||
Here is how to set different `out_path` for `md2html` and `md2pdf` and set `fig_ext` globally:
|
||||
```yaml
|
||||
---
|
||||
weave_options:
|
||||
md2html:
|
||||
out_path : html
|
||||
md2pdf:
|
||||
out_path : pdf
|
||||
fig_ext : .png
|
||||
---
|
||||
```
|
|
@ -0,0 +1,38 @@
|
|||
# Weave.jl - Scientific Reports Using Julia
|
||||
|
||||
This is the documentation of [Weave.jl](http://github.com/mpastell/weave.jl).
|
||||
Weave is a scientific report generator/literate programming tool for Julia.
|
||||
It resembles
|
||||
[Pweave](http://mpastell.com/pweave),
|
||||
[knitr](https://yihui.org/knitr/),
|
||||
[R Markdown](https://rmarkdown.rstudio.com/),
|
||||
and [Sweave](https://stat.ethz.ch/R-manual/R-patched/library/utils/doc/Sweave.pdf).
|
||||
|
||||
|
||||
**Current features**
|
||||
|
||||
- Publish markdown directly to HTML and PDF using Julia or [Pandoc](https://pandoc.org/MANUAL.html)
|
||||
- Execute code as in terminal or in a unit of code chunk
|
||||
- Capture [Plots.jl](https://github.com/JuliaPlots/Plots.jl) or [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl) figures
|
||||
- Supports various input format: Markdown, [Noweb](https://www.cs.tufts.edu/~nr/noweb/), [Jupyter Notebook](https://jupyter.org/), and ordinal Julia script
|
||||
- Conversions between those input formats
|
||||
- Supports various output document formats: HTML, PDF, GitHub markdown, Jupyter Notebook, MultiMarkdown, Asciidoc and reStructuredText
|
||||
- Simple caching of results
|
||||
|
||||
![Weave in Juno demo](https://user-images.githubusercontent.com/40514306/76081328-32f41900-5fec-11ea-958a-375f77f642a2.png)
|
||||
|
||||
|
||||
## Index
|
||||
|
||||
```@contents
|
||||
Pages = [
|
||||
"index.md",
|
||||
"getting_started.md",
|
||||
"usage.md",
|
||||
"publish.md",
|
||||
"chunk_options.md",
|
||||
"header.md",
|
||||
"notebooks.md",
|
||||
"function_index.md",
|
||||
]
|
||||
```
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
# Working with Jupyter notebooks
|
||||
|
||||
## Weaving from Jupyter notebooks
|
||||
|
||||
Weave supports using [Jupyter Notebook](https://jupyter.org/)s as input format.
|
||||
This means you can [`weave`](@ref) notebooks to any supported formats;
|
||||
by default, it will be weaved to HTML.
|
||||
|
||||
```julia
|
||||
weave("notebook.ipynb") # will be weaved to HTML
|
||||
```
|
||||
|
||||
!!! warning
|
||||
You can't use chunk options with notebooks.
|
||||
|
||||
## Output to Jupyter notebooks
|
||||
|
||||
As of Weave 0.5.1. there is new [`notebook`](@ref) method to convert Weave documents to Jupyter notebooks using
|
||||
[nbconvert](http://nbconvert.readthedocs.io/en/latest/execute_api.html).
|
||||
|
||||
```@docs
|
||||
notebook
|
||||
```
|
||||
|
||||
You can specify `jupyter` used to execute the notebook with the `jupyter_path` keyword argument
|
||||
(this defaults to the `"jupyter"`, i.e. whatever you have linked to that location).
|
||||
|
||||
Instead, you might want to use the [`convert_doc`](@ref) method below and run the code in Jupyter.
|
||||
|
||||
## Converting between formats
|
||||
|
||||
You can convert between all supported input formats using the [`convert_doc`](@ref) function.
|
||||
|
||||
To convert from script to notebook:
|
||||
|
||||
```julia
|
||||
convert_doc("examples/FIR_design.jl", "FIR_design.ipynb")
|
||||
```
|
||||
|
||||
and from notebook to Markdown use:
|
||||
|
||||
```julia
|
||||
convert_doc("FIR_design.ipynb", "FIR_design.jmd")
|
||||
```
|
||||
|
||||
```@docs
|
||||
convert_doc
|
||||
```
|
|
@ -0,0 +1,67 @@
|
|||
# Publishing to HTML and PDF
|
||||
|
||||
You can also publish any supported input format to HTML and PDF documents.
|
||||
|
||||
!!! note
|
||||
Producing PDF output requires that you have XeLaTex installed and in your path.
|
||||
|
||||
You can use a YAML header in the beginning of the input document delimited with `---`
|
||||
to set the document title, author and date, e.g.:
|
||||
```
|
||||
---
|
||||
title : Weave example
|
||||
author : Matti Pastell
|
||||
date: 15th December 2016
|
||||
---
|
||||
```
|
||||
|
||||
Here are sample input and outputs:
|
||||
- input (Julia markdown format): [`FIR_design_plots.jl`](../examples/FIR_design_plots.jl) (its path is bound to `Weave.SAMPLE_JL_DOC`)
|
||||
- HTML output: [`FIR_design_plots.html`](../examples/FIR_design_plots.html)
|
||||
- PDF output: [`FIR_design_plots.pdf`](../examples/FIR_design_plots.pdf)
|
||||
|
||||
They are generated as follows:
|
||||
```julia
|
||||
weave(Weave.SAMPLE_JL_DOC)) # default to md2html output format
|
||||
weave(Weave.SAMPLE_JL_DOC; doctype = "md2pdf")
|
||||
```
|
||||
|
||||
!!! tips
|
||||
`Weave.SAMPLE_JL_DOC` is the path of [FIR_design.jl](../examples/FIR_design.jl).
|
||||
|
||||
!!! note
|
||||
`"md2html"` and `"md2pdf"` assume Julia markdown format as an input,
|
||||
while `pandoc2pdf` and `pandoc2html` assume Noweb input format (i.e. Pandoc markdown).
|
||||
|
||||
|
||||
## Templates
|
||||
|
||||
You can use a custom template with `md2html` and `md2pdf` formats with `template` keyword option,
|
||||
e.g.: `weave("FIR_design_plots.jl", template = "custom.tpl"`.
|
||||
|
||||
As starting point, you can use the existing templates:
|
||||
|
||||
- HTML (`md2html`): [`md2html.tpl`](https://github.com/JunoLab/Weave.jl/blob/master/templates/md2html.tpl)
|
||||
- LaTex (`md2pdf`): [`md2pdf.tpl`](https://github.com/JunoLab/Weave.jl/blob/master/templates/md2pdf.tpl)
|
||||
|
||||
Templates are rendered using [Mustache.jl](https://github.com/jverzani/Mustache.jl).
|
||||
|
||||
|
||||
## Supported Markdown syntax
|
||||
|
||||
The markdown variant used by Weave is [Julia markdown](https://docs.julialang.org/en/v1/stdlib/Markdown/#).
|
||||
In addition Weave supports few additional Markdown features:
|
||||
|
||||
### Comments
|
||||
|
||||
You can add comments using html syntax: `<!-- -->`
|
||||
|
||||
### Multiline equations
|
||||
|
||||
You can add multiline equations using:
|
||||
|
||||
```
|
||||
$$
|
||||
x^2 = x*x
|
||||
$$
|
||||
```
|
|
@ -0,0 +1,182 @@
|
|||
# Using Weave
|
||||
|
||||
You can write your documentation and code in input document using Markdown, Noweb or script
|
||||
syntax and use [`weave`](@ref) function to execute to document to capture results and figures.
|
||||
|
||||
## `weave`
|
||||
|
||||
Weave document with markup and julia code using `Plots.jl` for plots,
|
||||
`out_path = :pwd` makes the results appear in the current working directory.
|
||||
|
||||
> A prepared example: [`Weave.SAMPLE_JL_DOC`](../examples/FIR_design.jmd)
|
||||
|
||||
```julia
|
||||
# First add depencies for the example
|
||||
using Pkg; Pkg.add.(["Plots", "DSP"])
|
||||
using Weave
|
||||
weave(Weave.SAMPLE_JL_DOC; out_path=:pwd)
|
||||
```
|
||||
|
||||
```@docs
|
||||
weave
|
||||
```
|
||||
|
||||
## `tangle`
|
||||
|
||||
Tangling extracts the code from document:
|
||||
|
||||
```@docs
|
||||
tangle
|
||||
```
|
||||
|
||||
## Supported Output Formats
|
||||
|
||||
Weave automatically detects the output format based on the file extension.
|
||||
The auto output format detection is handled by `detect_doctype(path::AbstractString)`:
|
||||
|
||||
```julia
|
||||
function detect_doctype(path::AbstractString)
|
||||
_, ext = lowercase.(splitext(path))
|
||||
|
||||
match(r"^\.(jl|.?md|ipynb)", ext) !== nothing && return "md2html"
|
||||
ext == ".rst" && return "rst"
|
||||
ext == ".tex" && return "texminted"
|
||||
ext == ".txt" && return "asciidoc"
|
||||
|
||||
return "pandoc"
|
||||
end
|
||||
```
|
||||
|
||||
You can also manually specify it using the `doctype` keyword option.
|
||||
You can get a list of supported output formats:
|
||||
|
||||
```@docs
|
||||
list_out_formats
|
||||
```
|
||||
|
||||
```@example
|
||||
using Weave # hide
|
||||
list_out_formats()
|
||||
```
|
||||
|
||||
## [Document Syntax](@id document-syntax)
|
||||
|
||||
Weave uses markdown, Noweb or script syntax for defining the code chunks and
|
||||
documentation chunks. You can also weave Jupyter notebooks. The format is detected based on the file extension, but you can also set it manually using the `informat` parameter.
|
||||
|
||||
The rules for autodetection are:
|
||||
|
||||
```julia
|
||||
ext == ".jl" && return "script"
|
||||
ext == ".jmd" && return "markdown"
|
||||
ext == ".ipynb" && return "notebook"
|
||||
return "noweb"
|
||||
```
|
||||
|
||||
|
||||
### Documentation Chunks
|
||||
|
||||
In markdown and Noweb input formats documentation chunks are the parts that aren't inside code delimiters. Documentation chunks can be written with several different markup languages.
|
||||
|
||||
|
||||
### [Code Chunks](@id code-chunks)
|
||||
|
||||
Code chunks are written in different ways in different formats.
|
||||
|
||||
#### Markdown Format
|
||||
|
||||
Weave code chunks are defined using fenced code blocks, same as with [common markdown](https://spec.commonmark.org/0.29/#fenced-code-blocks):
|
||||
```markdown
|
||||
```julia
|
||||
code
|
||||
...
|
||||
```
|
||||
```
|
||||
|
||||
Weave code chunks can optionally be followed by [chunk options](@ref) on the same line.
|
||||
E.g. the chunk below will hide code itself from generated output:
|
||||
```markdown
|
||||
```julia, echo = false
|
||||
code
|
||||
...
|
||||
```
|
||||
```
|
||||
|
||||
#### Noweb Format
|
||||
|
||||
Code chunks start with a line marked with `<<>>=` or `<<options>>=` and end with line marked with `@`.
|
||||
The code between the start and end markers is executed and the output is captured to the output document.
|
||||
|
||||
### [Inline Code](@id inline-code)
|
||||
|
||||
You can also add inline code to your documents using
|
||||
```
|
||||
`j juliacode`
|
||||
```
|
||||
or
|
||||
```
|
||||
! juliacode
|
||||
```
|
||||
syntax.
|
||||
|
||||
The former syntax allows you to insert code _anywhere_ in a line
|
||||
while the `!` syntax treats the whole line as code,
|
||||
and the code will be replaced with captured output in the weaved document.
|
||||
|
||||
If the code produces figures, the filename or base64 encoded string will be added to output,
|
||||
e.g. to include a Plots figure in markdown you can use:
|
||||
```
|
||||
![A plot](`j plot(1:10)`)
|
||||
```
|
||||
or to produce any HTML output:
|
||||
```
|
||||
! display("text/html", HTML("Header from julia"));
|
||||
```
|
||||
|
||||
### Script Format
|
||||
|
||||
Weave also supports script input format with a markup in comments.
|
||||
These scripts can be executed normally using Julia or published with Weave.
|
||||
|
||||
Lines starting with `#'`, `#%%` or `# %%` are treated as document.
|
||||
|
||||
All non-document lines are treated as code.
|
||||
You can set chunk options using lines starting with `#+` just before code e.g:
|
||||
```julia
|
||||
#+ term=true
|
||||
hoge # some code comes here
|
||||
```
|
||||
|
||||
The format is identical to [Pweave](http://mpastell.com/pweave/pypublish.html) and the concept is similar to publishing documents with MATLAB or using Knitr's [spin](http://yihui.name/knitr/demo/stitch/).
|
||||
Weave will remove the first empty space from each line of documentation.
|
||||
|
||||
!!! tip
|
||||
- Here are sample documents:
|
||||
+ [markdown format](https://github.com/JunoLab/Weave.jl/blob/master/examples/FIR_design.jmd)
|
||||
+ [script format](https://github.com/JunoLab/Weave.jl/blob/master/examples/FIR_design.jl)
|
||||
- [Details about chunk options](@ref chunk-options)
|
||||
|
||||
|
||||
## Configuration via YAML Header
|
||||
|
||||
When `weave`ing markdown files, you can use YAML header to provide additional metadata and configuration options.
|
||||
See [Header Configuration](@ref) section for more details.
|
||||
|
||||
|
||||
## Passing Runtime Arguments to Documents
|
||||
|
||||
You can pass arbitrary object to the weaved document using [`weave`](@ref)'s optional argument `args`.
|
||||
It will be available as `WEAVE_ARGS` variable in the `weave`d document.
|
||||
|
||||
This makes it possible to create the same report easily for e.g. different date ranges of input data from a database or from files with similar format giving the filename as input.
|
||||
|
||||
E.g. if you call `weave("weavefile.jmd", args = (datalocation = "somedata.h5",))`, and then you can retrieve the `datalocation` in `weavefile.jmd` as follows: `WEAVE_ARGS.datalocation`
|
||||
|
||||
|
||||
## `include_weave`
|
||||
|
||||
You can call `include_weave` on a Weave document and run all code chunks within in the current session.
|
||||
|
||||
```@docs
|
||||
include_weave
|
||||
```
|
|
@ -0,0 +1,83 @@
|
|||
#' ---
|
||||
#' title : FIR filter design with Julia
|
||||
#' author : Matti Pastell
|
||||
#' date : 21th April 2016
|
||||
#' ---
|
||||
|
||||
#' # Introduction
|
||||
|
||||
#' This an example of a julia script that can be published using
|
||||
#' [Weave](http://weavejl.mpastell.com/dev/usage/).
|
||||
#' The script can be executed normally using Julia
|
||||
#' or published to HTML or pdf with Weave.
|
||||
#' Text is written in markdown in lines starting with "`#'` " and code
|
||||
#' is executed and results are included in the published document.
|
||||
|
||||
#' Notice that you don't need to define chunk options, but you can using
|
||||
#' `#+`. just before code e.g. `#+ term=True, caption='Fancy plots.'`.
|
||||
#' If you're viewing the published version have a look at the
|
||||
#' [source](FIR_design.jl) to see the markup.
|
||||
|
||||
|
||||
#' # FIR Filter Design
|
||||
|
||||
#' We'll implement lowpass, highpass and ' bandpass FIR filters. If
|
||||
#' you want to read more about DSP I highly recommend [The Scientist
|
||||
#' and Engineer's Guide to Digital Signal
|
||||
#' Processing](http://www.dspguide.com/) which is freely available
|
||||
#' online.
|
||||
|
||||
#' ## Calculating frequency response
|
||||
|
||||
#' DSP.jl package doesn't (yet) have a method to calculate the
|
||||
#' the frequency response of a FIR filter so we define it:
|
||||
|
||||
using Gadfly, DSP
|
||||
|
||||
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
|
||||
n = length(w)
|
||||
h = Array{ComplexF32}(n)
|
||||
sw = 0
|
||||
for i = 1:n
|
||||
for j = 1:length(b)
|
||||
sw += b[j]*exp(-im*w[i])^-j
|
||||
end
|
||||
h[i] = sw
|
||||
sw = 0
|
||||
end
|
||||
return h
|
||||
end
|
||||
|
||||
|
||||
#' ## Design Lowpass FIR filter
|
||||
|
||||
#' Designing a lowpass FIR filter is very simple to do with DSP.jl, all you
|
||||
#' need to do is to define the window length, cut off frequency and the
|
||||
#' window. We will define a lowpass filter with cut off frequency at 5Hz for a signal
|
||||
#' sampled at 20 Hz.
|
||||
#' We will use the Hamming window, which is defined as:
|
||||
#' $w(n) = \alpha - \beta\cos\frac{2\pi n}{N-1}$, where $\alpha=0.54$ and $\beta=0.46$
|
||||
|
||||
fs = 20
|
||||
f = digitalfilter(Lowpass(5, fs = fs), FIRWindow(hamming(61)))
|
||||
w = range(0, stop=pi, length=1024)
|
||||
h = FIRfreqz(f, w)
|
||||
|
||||
#' ## Plot the frequency and impulse response
|
||||
|
||||
#' The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
|
||||
#+ term=true
|
||||
|
||||
h_db = log10(abs.(h));
|
||||
ws = w/pi*(fs/2)
|
||||
|
||||
#+
|
||||
|
||||
plot(y = h_db, x = ws, Geom.line,
|
||||
Guide.xlabel("Frequency (Hz)"), Guide.ylabel("Magnitude (db)"))
|
||||
|
||||
#' And again with default options
|
||||
|
||||
h_phase = unwrap(-atan(imag(h),real(h)))
|
||||
plot(y = h_phase, x = ws, Geom.line,
|
||||
Guide.xlabel("Frequency (Hz)"), Guide.ylabel("Phase (radians)"))
|
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
title: FIR filter design with Julia
|
||||
author: Matti Pastell
|
||||
date: 21th April 2016
|
||||
---
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
|
||||
This an example of a julia script that can be published using
|
||||
[Weave](http://weavejl.mpastell.com/dev/usage/).
|
||||
The script can be executed normally using Julia
|
||||
or published to HTML or pdf with Weave.
|
||||
Text is written in markdown in lines starting with "`#'` " and code
|
||||
is executed and results are included in the published document.
|
||||
|
||||
|
||||
Notice that you don't need to define chunk options, but you can using
|
||||
`#+`. just before code e.g. `#+ term=True, caption='Fancy plots.'`.
|
||||
If you're viewing the published version have a look at the
|
||||
[source](FIR_design_plots.jl) to see the markup.
|
||||
|
||||
|
||||
<!-- this setup dependencies, but doesn't appear in the generated document -->
|
||||
```julia; echo = false; results = "hidden"
|
||||
using Pkg
|
||||
"Plots" ∉ keys(Pkg.project().dependencies) && Pkg.add("Plots")
|
||||
"DSP" ∉ keys(Pkg.project().dependencies) && Pkg.add("DSP")
|
||||
```
|
||||
|
||||
|
||||
# FIR Filter Design
|
||||
|
||||
|
||||
We'll implement lowpass, highpass and ' bandpass FIR filters. If
|
||||
you want to read more about DSP I highly recommend [The Scientist
|
||||
and Engineer's Guide to Digital Signal
|
||||
Processing](http://www.dspguide.com/) which is freely available
|
||||
online.
|
||||
|
||||
|
||||
## Calculating frequency response
|
||||
|
||||
|
||||
DSP.jl package doesn't (yet) have a method to calculate the
|
||||
the frequency response of a FIR filter so we define it:
|
||||
|
||||
```julia
|
||||
using Plots, DSP
|
||||
gr()
|
||||
|
||||
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
|
||||
n = length(w)
|
||||
h = Array{ComplexF32}(undef, n)
|
||||
sw = 0
|
||||
for i = 1:n
|
||||
for j = 1:length(b)
|
||||
sw += b[j]*exp(-im*w[i])^-j
|
||||
end
|
||||
h[i] = sw
|
||||
sw = 0
|
||||
end
|
||||
return h
|
||||
end
|
||||
```
|
||||
|
||||
## Design Lowpass FIR filter
|
||||
|
||||
|
||||
Designing a lowpass FIR filter is very simple to do with DSP.jl, all you
|
||||
need to do is to define the window length, cut off frequency and the
|
||||
window. We will define a lowpass filter with cut off frequency at 5Hz for a signal
|
||||
sampled at 20 Hz.
|
||||
We will use the Hamming window, which is defined as:
|
||||
$w(n) = \alpha - \beta\cos\frac{2\pi n}{N-1}$, where $\alpha=0.54$ and $\beta=0.46$
|
||||
|
||||
```julia
|
||||
fs = 20
|
||||
f = digitalfilter(Lowpass(5, fs = fs), FIRWindow(hamming(61)))
|
||||
w = range(0, stop=pi, length=1024)
|
||||
h = FIRfreqz(f, w)
|
||||
```
|
||||
|
||||
## Plot the frequency and impulse response
|
||||
|
||||
|
||||
The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
|
||||
|
||||
```julia; term=true
|
||||
h_db = log10.(abs.(h));
|
||||
ws = w/pi*(fs/2)
|
||||
```
|
||||
|
||||
```julia
|
||||
plot(ws, h_db,
|
||||
xlabel = "Frequency (Hz)", ylabel = "Magnitude (db)")
|
||||
```
|
||||
|
||||
And again with default options
|
||||
|
||||
```julia
|
||||
h_phase = unwrap(-atan.(imag.(h),real.(h)))
|
||||
plot(ws, h_phase,
|
||||
xlabel = "Frequency (Hz)", ylabel = "Phase (radians)")
|
||||
```
|
|
@ -0,0 +1,85 @@
|
|||
#' ---
|
||||
#' title: FIR filter design with Julia
|
||||
#' author: Matti Pastell
|
||||
#' date: 21th April 2016
|
||||
#' ---
|
||||
|
||||
#' # Introduction
|
||||
|
||||
#' This an example of a julia script that can be published using
|
||||
#' [Weave](http://weavejl.mpastell.com/dev/usage/).
|
||||
#' The script can be executed normally using Julia
|
||||
#' or published to HTML or pdf with Weave.
|
||||
#' Text is written in markdown in lines starting with "`#'` " and code
|
||||
#' is executed and results are included in the published document.
|
||||
|
||||
#' Notice that you don't need to define chunk options, but you can using
|
||||
#' `#+`. just before code e.g. `#+ term=True, caption='Fancy plots.'`.
|
||||
#' If you're viewing the published version have a look at the
|
||||
#' [source](FIR_design_plots.jl) to see the markup.
|
||||
|
||||
|
||||
#' # FIR Filter Design
|
||||
|
||||
#' We'll implement lowpass, highpass and ' bandpass FIR filters. If
|
||||
#' you want to read more about DSP I highly recommend [The Scientist
|
||||
#' and Engineer's Guide to Digital Signal
|
||||
#' Processing](http://www.dspguide.com/) which is freely available
|
||||
#' online.
|
||||
|
||||
#' ## Calculating frequency response
|
||||
|
||||
#' DSP.jl package doesn't (yet) have a method to calculate the
|
||||
#' the frequency response of a FIR filter so we define it:
|
||||
|
||||
using Plots, DSP
|
||||
gr()
|
||||
|
||||
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
|
||||
n = length(w)
|
||||
h = Array{ComplexF32}(undef, n)
|
||||
sw = 0
|
||||
for i = 1:n
|
||||
for j = 1:length(b)
|
||||
sw += b[j]*exp(-im*w[i])^-j
|
||||
end
|
||||
h[i] = sw
|
||||
sw = 0
|
||||
end
|
||||
return h
|
||||
end
|
||||
|
||||
|
||||
#' ## Design Lowpass FIR filter
|
||||
|
||||
#' Designing a lowpass FIR filter is very simple to do with DSP.jl, all you
|
||||
#' need to do is to define the window length, cut off frequency and the
|
||||
#' window. We will define a lowpass filter with cut off frequency at 5Hz for a signal
|
||||
#' sampled at 20 Hz.
|
||||
#' We will use the Hamming window, which is defined as:
|
||||
#' $w(n) = \alpha - \beta\cos\frac{2\pi n}{N-1}$, where $\alpha=0.54$ and $\beta=0.46$
|
||||
|
||||
|
||||
fs = 20
|
||||
f = digitalfilter(Lowpass(5, fs = fs), FIRWindow(hamming(61)))
|
||||
w = range(0, stop=pi, length=1024)
|
||||
h = FIRfreqz(f, w)
|
||||
|
||||
#' ## Plot the frequency and impulse response
|
||||
|
||||
#' The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
|
||||
#+ term=true
|
||||
|
||||
h_db = log10.(abs.(h));
|
||||
ws = w/pi*(fs/2)
|
||||
|
||||
#+
|
||||
|
||||
plot(ws, h_db,
|
||||
xlabel = "Frequency (Hz)", ylabel = "Magnitude (db)")
|
||||
|
||||
#' And again with default options
|
||||
|
||||
h_phase = unwrap(-atan.(imag.(h),real.(h)))
|
||||
plot(ws, h_phase,
|
||||
xlabel = "Frequency (Hz)", ylabel = "Phase (radians)")
|
|
@ -0,0 +1,46 @@
|
|||
\documentclass{beamer}
|
||||
|
||||
\usepackage{lmodern}
|
||||
\usepackage{amssymb,amsmath}
|
||||
\usepackage{bm}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{microtype}
|
||||
\usepackage{hyperref}
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{1.2ex}
|
||||
|
||||
\hypersetup
|
||||
{ pdfauthor = { {{{:author}}} },
|
||||
pdftitle={ {{{:title}}} },
|
||||
colorlinks=TRUE,
|
||||
linkcolor=black,
|
||||
citecolor=blue,
|
||||
urlcolor=blue
|
||||
}
|
||||
|
||||
|
||||
{{#:title}}
|
||||
\title{ {{{ :title }}} }
|
||||
{{/:title}}
|
||||
|
||||
{{#:author}}
|
||||
\author{ {{{ :author }}} }
|
||||
{{/:author}}
|
||||
|
||||
{{#:date}}
|
||||
\date{ {{{ :date }}} }
|
||||
{{/:date}}
|
||||
|
||||
{{ :highlight }}
|
||||
|
||||
\begin{document}
|
||||
|
||||
{{{#:title}}}
|
||||
\begin{frame}
|
||||
\titlepage
|
||||
\end{frame}
|
||||
{{{/:title}}}
|
||||
|
||||
{{{ :body }}}
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
title : Intro to Weave.jl with Gadfly
|
||||
author : Matti Pastell
|
||||
date : 13th December 2016
|
||||
---
|
||||
|
||||
# Intro
|
||||
|
||||
This a sample [Julia](http://julialang.org/) markdown document that can
|
||||
be executed using [Weave.jl](https://github.com/JunoLab/Weave.jl).
|
||||
|
||||
The code is delimited from docs using markdown fenced code blocks
|
||||
markup which can be seen looking at the source document
|
||||
[gadfly_md_sample.jmd](gadfly_md_sample.jmd)
|
||||
in the examples directory of the package. The source document can be executed
|
||||
and the results with Gadfly plots are captured in the resulting file.
|
||||
|
||||
You can create markdown output or pdf (with xelatex) and HTML directly using
|
||||
the weave command as follows:
|
||||
|
||||
```{julia; eval=false}
|
||||
using Weave
|
||||
#Markdown
|
||||
weave(Pkg.dir("Weave","examples","gadfly_md_sample.jmd"), informat="markdown",
|
||||
out_path = :pwd, doctype = "pandoc")
|
||||
#HTML
|
||||
weave(Pkg.dir("Weave","examples","gadfly_md_sample.jmd"), informat="markdown",
|
||||
out_path = :pwd, doctype = "md2html")
|
||||
#pdf
|
||||
weave(Pkg.dir("Weave","examples","gadfly_md_sample.jmd"), informat="markdown",
|
||||
out_path = :pwd, doctype = "md2pdf")
|
||||
```
|
||||
|
||||
*The markdown variant used for html and pdf output is Julia markdown.*
|
||||
|
||||
|
||||
The documents will be written to the Julia working directory when you
|
||||
use the `out_path = :pwd`.
|
||||
|
||||
# Capturing code
|
||||
|
||||
The basic code chunk will be run with default options and the code and
|
||||
output will be captured.
|
||||
|
||||
```julia
|
||||
using Gadfly
|
||||
x = linspace(0, 2*pi)
|
||||
println(x)
|
||||
plot(x = x, y = sin.(x))
|
||||
```
|
||||
|
||||
You can also control the way the results are captured, plot size etc.
|
||||
using chunk options. Here is an example of a chunk that behaves like a repl.
|
||||
|
||||
```{julia;term=true}
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
```
|
||||
|
||||
You can also for instance hide the code and show only the figure, add a
|
||||
caption to the figure and make it wider as follows (you can only see the
|
||||
syntax from the source document):
|
||||
|
||||
```{julia;echo=false; fig_cap="A random walk."; label="random"; fig_width=7; fig_height=4}
|
||||
plot(y = cumsum(randn(1000, 1)), Geom.line)
|
||||
```
|
||||
|
||||
# Whats next
|
||||
|
||||
Read the documentation:
|
||||
|
||||
- stable: [http://mpastell.github.io/Weave.jl/stable/](http://mpastell.github.io/Weave.jl/stable/)
|
||||
- latest: [http://weavejl.mpastell.com/dev/](http://weavejl.mpastell.com/dev/)
|
||||
|
||||
See other examples in the [GitHub repo](https://github.com/JunoLab/Weave.jl/tree/master/examples)
|
|
@ -0,0 +1,83 @@
|
|||
\documentclass{article}
|
||||
|
||||
%Minted for syntax hightlighting
|
||||
\usepackage{minted}
|
||||
|
||||
%These are for plots
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{fontspec}
|
||||
\setmainfont{TeX Gyre Pagella}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[active,tightpage]{preview}
|
||||
|
||||
%Hyperlinks
|
||||
\usepackage{hyperref}
|
||||
\hypersetup{colorlinks=true, urlcolor=blue}
|
||||
%Some style changes
|
||||
\setlength{\parindent}{0in}
|
||||
\setlength{\parskip}{12pt}
|
||||
|
||||
|
||||
\author{Matti Pastell}
|
||||
\title{Using PGF plots with Weave and Gadfly}
|
||||
|
||||
\begin{document}
|
||||
|
||||
|
||||
\maketitle
|
||||
|
||||
\section{Intro}
|
||||
|
||||
This is a minimal example on using PGF format with Gadfly plots in
|
||||
\href{https://github.com/JunoLab/Weave.jl}{Weave.jl} document.
|
||||
The source is in github:
|
||||
|
||||
\url{https://github.com/JunoLab/Weave.jl/blob/master/examples/gadfly_pgf.texw}.
|
||||
|
||||
You can run this example with first weaving it from Julia using:
|
||||
|
||||
<<eval=false>>=
|
||||
using Weave
|
||||
weave(Pkg.dir("Weave", "examples", "gadfly_pgf.texw"),
|
||||
doctype="texminted", out_path=:pwd, fig_ext=".tex")
|
||||
@
|
||||
|
||||
which will save the generated output in your working directory and use minted
|
||||
package for syntax hightlighting. You'll need to use either xetex or luatex with
|
||||
\texttt{-shell-escape} flag to get pdf e.g.
|
||||
|
||||
\begin{minted}{bash}
|
||||
lualatex -shell-escape gadfly_pgf.tex
|
||||
\end{minted}
|
||||
|
||||
\section{Sample code}
|
||||
|
||||
You can set the default font in Gadfly to match the font in the document.
|
||||
Use the \texttt{fontspec} latex package (see preamble) and define the
|
||||
defaults to Gadfly as follows.
|
||||
|
||||
If you want you can hide the chunk using the \texttt{echo=false} chunk option.
|
||||
|
||||
<<>>=
|
||||
using Gadfly
|
||||
Gadfly.default_theme.major_label_font = "Tex Gyre Pagella"
|
||||
Gadfly.default_theme.minor_label_font = "Tex Gyre Pagella"
|
||||
Gadfly.default_theme.major_label_color = colorant"black"
|
||||
Gadfly.default_theme.minor_label_color = colorant"black"
|
||||
@
|
||||
|
||||
Let's create a simple plot:
|
||||
|
||||
<<>>=
|
||||
x = 1:10
|
||||
plot(x=x, y=x)
|
||||
@
|
||||
|
||||
And a figure with a caption
|
||||
|
||||
<<fig_cap="Nice Gadfly figure">>=
|
||||
plot([sin, cos], 0, 25)
|
||||
@
|
||||
|
||||
|
||||
\end{document}
|
|
@ -1,30 +0,0 @@
|
|||
|
||||
# Gadfly
|
||||
|
||||
```{julia;term=true;fig_width=5}
|
||||
using Gadfly
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
y = 20
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
```
|
||||
|
||||
|
||||
```julia
|
||||
x = linspace(0, 200)
|
||||
println(x)
|
||||
```
|
||||
|
||||
|
||||
~~~{julia;term=true;fig_width=5}
|
||||
using Gadfly
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
y = 20
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
~~~
|
||||
|
||||
~~~julia
|
||||
x = linspace(0, 200)
|
||||
println(x)
|
||||
~~~
|
|
@ -1,14 +1,70 @@
|
|||
# Gadfly
|
||||
% Intro to Weave.jl with Gadfly
|
||||
% Matti Pastell
|
||||
% 20th April 2016
|
||||
|
||||
<<term=true>>=
|
||||
using Gadfly
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
y = 20
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
@
|
||||
# Introduction
|
||||
|
||||
This a sample [Julia](http://julialang.org/) noweb document that can
|
||||
be executed using [Weave.jl](https://github.com/JunoLab/Weave.jl).
|
||||
|
||||
The code is delimited from docs using `<<>>=` and `@` markup which can be seen
|
||||
looking at the source document `gadfly_sample.mdw` in the examples directory
|
||||
of the package. The source document can be executed and the results with Gadfly
|
||||
plots are captured in the resulting file.
|
||||
|
||||
You can create markdown output or pdf and HTML directly (with Pandoc) using
|
||||
the weave command as follows:
|
||||
|
||||
```julia
|
||||
using Weave
|
||||
#Markdown
|
||||
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"),
|
||||
out_path = :pwd, doctype = "pandoc")
|
||||
#HTML
|
||||
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"),
|
||||
out_path = :pwd, doctype = "md2html")
|
||||
#pdf
|
||||
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"),
|
||||
out_path = :pwd, doctype = "md2pdf")
|
||||
```
|
||||
|
||||
*The documents will be written to the Julia working directory when you
|
||||
use the `out_path = :pwd`.*
|
||||
|
||||
# Capturing code
|
||||
|
||||
The basic code chunk will be run with default options and the code and
|
||||
output will be captured.
|
||||
|
||||
<<>>=
|
||||
x = linspace(0, 200)
|
||||
using Gadfly
|
||||
x = linspace(0, 2*pi)
|
||||
println(x)
|
||||
plot(x = x, y = sin(x))
|
||||
@
|
||||
|
||||
You can also control the way the results are captured, plot size etc.
|
||||
using chunk options. Here is an example of a chunk that behaves like a repl.
|
||||
|
||||
<<term=true>>=
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
@
|
||||
|
||||
You can also for instance hide the code and show only the figure, add a
|
||||
caption to the figure and make it wider as follows (you can only see the
|
||||
syntax from the source document):
|
||||
|
||||
<<echo=false; fig_cap="A random walk."; label="random"; fig_width=8; fig_height=4>>=
|
||||
plot(y = cumsum(randn(1000, 1)), Geom.line)
|
||||
@
|
||||
|
||||
# Whats next
|
||||
|
||||
Read the documentation:
|
||||
|
||||
- stable: <http://mpastell.github.io/Weave.jl/stable/>
|
||||
- latest: <http://weavejl.mpastell.com/dev/>
|
||||
|
||||
See other examples in: <https://github.com/JunoLab/Weave.jl/tree/master/examples>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
This a sample [Julia](http://julialang.org/) noweb document that can
|
||||
be executed using Weave. Output from code chunks and PyPlot
|
||||
plots will be included in the weaved document. You also need to install Pweave from Github in order to use Weave.
|
||||
plots will be included in the weaved document. You also need to install Pweave from GitHub in order to use Weave.
|
||||
|
||||
This documented can be turned into Pandoc markdown with captured
|
||||
result from Julia prompt.
|
||||
|
@ -17,7 +17,7 @@ weave("examples/julia_sample.mdw")
|
|||
|
||||
<<term=true>>=
|
||||
x = 1:10
|
||||
d = {"Weave" => "testing"}
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
@
|
||||
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
title: A minimal beamer example using Weave markdown
|
||||
author: Matti Pastell
|
||||
weave_options:
|
||||
doctype : md2pdf
|
||||
out_path : pdf
|
||||
template : beamer.tpl
|
||||
---
|
||||
|
||||
```julia; echo=false
|
||||
struct Begin
|
||||
text
|
||||
title
|
||||
end
|
||||
|
||||
struct End
|
||||
text
|
||||
end
|
||||
Base.show(io::IO, m::MIME"text/latex", b::Begin) = write(io, "\\begin{$(b.text)}[fragile]\n\\frametitle{$(b.title)}\n")
|
||||
Base.show(io::IO, m::MIME"text/latex", e::End) = write(io, "\\end{$(e.text)}")
|
||||
```
|
||||
|
||||
! Begin("frame", "Random plot")
|
||||
|
||||
```julia; out_width="0.5\\textwidth"
|
||||
using Plots
|
||||
scatter(randn(1000), randn(1000))
|
||||
```
|
||||
! End("frame")
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
<<>>=
|
||||
using Plots
|
||||
pyplot()
|
||||
x = linspace(0, 2π, 2056)
|
||||
@
|
||||
|
||||
<<>>=
|
||||
plot(sinc(x))
|
||||
@
|
||||
|
||||
<<>>=
|
||||
plot(-sinc(x))
|
||||
@
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
<<>>=
|
||||
using Plots
|
||||
plotly()
|
||||
x = linspace(0, 2π, 2056)
|
||||
@
|
||||
|
||||
<<>>=
|
||||
plot(sinc(x))
|
||||
@
|
||||
|
||||
<<>>=
|
||||
plot(-sinc(x))
|
||||
@
|
|
@ -1,57 +0,0 @@
|
|||
|
||||
# Introducion to Weave
|
||||
|
||||
This a sample [Julia](http://julialang.org/) noweb document that can
|
||||
be executed using Weave. Output from code chunks and Winston
|
||||
plots will be included in the weaved document. You also need to install Pweave from Github in order to use Weave.
|
||||
|
||||
This documented can be turned into Pandoc markdown with captured
|
||||
result from Julia prompt.
|
||||
|
||||
~~~~{.julia}
|
||||
using Weave
|
||||
weave(Pkg.dir("Weave","examples","winston_sample.mdw"), plotlib="Winston")
|
||||
~~~~
|
||||
|
||||
## Terminal chunk
|
||||
|
||||
<<term=true>>=
|
||||
x = 1:10
|
||||
d = {"Weave" => "testing"}
|
||||
y = [2, 4 ,8]
|
||||
@
|
||||
|
||||
## Capturing figures
|
||||
|
||||
The figures and code can be included in the output.
|
||||
|
||||
<<term=true>>=
|
||||
using Winston
|
||||
t = linspace(0, 2*pi, 100)
|
||||
p = plot(t, sinc(t))
|
||||
@
|
||||
|
||||
You can also include a plot with caption and hide the code:
|
||||
|
||||
<<echo=false; fig_cap="Random walk."; label="random"; fig_width=8; fig_height=4>>=
|
||||
p = plot(cumsum(randn(1000, 1)))
|
||||
xlabel("x")
|
||||
ylabel("sinc(x)")
|
||||
display(p)
|
||||
@
|
||||
|
||||
<<>>=
|
||||
x = linspace(0, 3pi, 100)
|
||||
c = cos(x)
|
||||
s = sin(x)
|
||||
|
||||
p = FramedPlot(
|
||||
title="title!",
|
||||
xlabel="\\Sigma x^2_i",
|
||||
ylabel="\\Theta_i")
|
||||
|
||||
add(p, FillBetween(x, c, x, s))
|
||||
add(p, Curve(x, c, color="red"))
|
||||
add(p, Curve(x, s, color="blue"))
|
||||
display(p)
|
||||
@
|
|
@ -0,0 +1,21 @@
|
|||
@article{julia,
|
||||
author = {Jeff Bezanson and Alan Edelman and Stefan Karpinski and Viral B. Shah},
|
||||
title = {Julia: A Fresh Approach to Numerical Computing},
|
||||
journal = {SIAM Review},
|
||||
volume = {59},
|
||||
number = {1},
|
||||
pages = {65-98},
|
||||
year = {2017},
|
||||
doi = {10.1137/141000671},
|
||||
}
|
||||
|
||||
@Book{knitr,
|
||||
title = {Dynamic Documents with {R} and knitr},
|
||||
author = {Yihui Xie},
|
||||
publisher = {Chapman and Hall/CRC},
|
||||
address = {Boca Raton, Florida},
|
||||
year = {2015},
|
||||
edition = {2nd},
|
||||
note = {ISBN 978-1498716963},
|
||||
url = {http://yihui.name/knitr/},
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: 'Weave.jl: Scientific Reports Using Julia'
|
||||
tags:
|
||||
- Scientific reports
|
||||
- Julia
|
||||
authors:
|
||||
- name: Matti Pastell
|
||||
orcid: 0000-0002-5810-4801
|
||||
affiliation: 1
|
||||
affiliations:
|
||||
- name: Natural Resources Institute Finland (Luke)
|
||||
index: 1
|
||||
date: 6 March 2017
|
||||
bibliography: paper.bib
|
||||
---
|
||||
|
||||
# Summary
|
||||
|
||||
Weave is a tool for writing scientific reports using Julia
|
||||
[@julia]. It allows writing of text, mathematics and code in a single
|
||||
document which can be run capturing results into a rich report.
|
||||
Output can include text using several markup languages, plots
|
||||
generated using one of the several Julia plotting libraries and other
|
||||
objects displayed using Julia's multimedia output. The workflow is
|
||||
very similar to using Knitr [@knitr] R-package.
|
||||
|
||||
Weave supports noweb, markdown, script syntax for delimiting code from
|
||||
text in the source document and several output formats including
|
||||
Markdown and Latex. The output from code can be controlled using chunk
|
||||
options making it possible e.g. to hide code and only show output when
|
||||
needed as well as set a figure caption and figure size. The library
|
||||
also has methods for converting documents from all input formats to
|
||||
Jupyter notebooks and vice versa.
|
||||
|
||||
The package aims to support writing scientific papers and enable easy
|
||||
sharing of analysis in order to promote reproducible research. It also
|
||||
aims to enable simple writing of educational material, tutorials and
|
||||
blog posts.
|
||||
|
||||
# References
|
582
src/Weave.jl
582
src/Weave.jl
|
@ -1,346 +1,344 @@
|
|||
module Weave
|
||||
using Compat
|
||||
using Docile
|
||||
|
||||
@docstrings(manual = ["../doc/manual.md"])
|
||||
using Highlights, Mustache, Requires, Pkg, REPL, RelocatableFolders, Base64
|
||||
|
||||
#Contains report global properties
|
||||
type Report <: Display
|
||||
source::String
|
||||
documentationmode::Bool
|
||||
cwd::String
|
||||
basename::String
|
||||
formatdict
|
||||
pending_code::String
|
||||
cur_result::String
|
||||
fignum::Int
|
||||
figures::Array
|
||||
term_state::Symbol
|
||||
cur_chunk::Dict{Symbol, Any}
|
||||
# directories
|
||||
const PKG_DIR = normpath(@__DIR__, "..")
|
||||
const TEMPLATE_DIR = @path joinpath(PKG_DIR, "templates")
|
||||
const STYLESHEET_DIR = @path joinpath(PKG_DIR, "stylesheets")
|
||||
# keeps paths of sample documents for easy try
|
||||
const EXAMPLE_FOLDER = @path joinpath(PKG_DIR, "examples")
|
||||
|
||||
# constant names
|
||||
const WEAVE_OPTION_NAME = "weave_options"
|
||||
const WEAVE_OPTION_NAME_DEPRECATED = "options" # remove this when tagging v0.11
|
||||
const WEAVE_OPTION_DEPRECATE_ID = "weave_option_duplicate_id"
|
||||
const DEFAULT_FIG_PATH = "figures"
|
||||
|
||||
function Report()
|
||||
new("", false, "", "", Any[], "", "", 1, Any[], :text, @compat Dict{Symbol, Any}() )
|
||||
end
|
||||
const WEAVE_VERSION = try
|
||||
'v' * Pkg.TOML.parsefile(normpath(PKG_DIR, "Project.toml"))["version"]
|
||||
catch
|
||||
""
|
||||
end
|
||||
weave_info() = WEAVE_VERSION, string(Date(now()))
|
||||
|
||||
function __init__()
|
||||
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" include("plots.jl")
|
||||
@require Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" include("gadfly.jl")
|
||||
end
|
||||
|
||||
const report = Report()
|
||||
# utilitity functions
|
||||
take2string!(io) = String(take!(io))
|
||||
joinlines(lines) = join(lines, '\n')
|
||||
|
||||
const supported_mime_types =
|
||||
[MIME"image/png",
|
||||
MIME"text/plain"]
|
||||
|
||||
function Base.display(doc::Report, data)
|
||||
for m in supported_mime_types
|
||||
if mimewritable(m(), data)
|
||||
display(doc, m(), data)
|
||||
brea
|
||||
end
|
||||
end
|
||||
end
|
||||
include("types.jl")
|
||||
include("config.jl")
|
||||
include("WeaveMarkdown/markdown.jl")
|
||||
include("display_methods.jl")
|
||||
include("reader/reader.jl")
|
||||
include("run.jl")
|
||||
include("cache.jl")
|
||||
include("rendering/rendering.jl")
|
||||
include("writer/writer.jl")
|
||||
include("converter.jl")
|
||||
|
||||
@doc "List supported output formats" ->
|
||||
function list_out_formats()
|
||||
for format = keys(formats)
|
||||
println(string(format,": ", formats[format].description))
|
||||
end
|
||||
end
|
||||
|
||||
#module ReportSandBox
|
||||
#end
|
||||
get_format(doctype::AbstractString) = FORMATS[doctype]
|
||||
|
||||
"""
|
||||
list_out_formats()
|
||||
|
||||
List supported output formats with its description.
|
||||
"""
|
||||
list_out_formats() = [k => v.description for (k,v) in FORMATS]
|
||||
|
||||
"""
|
||||
tangle(source::AbstractString; kwargs...)
|
||||
|
||||
@doc md"""
|
||||
Tangle source code from input document to .jl file.
|
||||
|
||||
**parameters:**
|
||||
```julia
|
||||
tangle(source ; out_path=:doc, informat="noweb")
|
||||
```
|
||||
## Keyword options
|
||||
|
||||
* `informat`: `"noweb"` of `"markdown"`
|
||||
* `out_path`: Path where the output is generated. Can be: `:doc`: Path of the source document, `:pwd`: Julia working directory,
|
||||
`"somepath"`: Path as a string e.g `"/home/mpastell/weaveout"`
|
||||
"""->
|
||||
function tangle(source ; out_path=:doc, informat="noweb")
|
||||
cwd, fname = splitdir(abspath(source))
|
||||
basename = splitext(fname)[1]
|
||||
- `informat::Union{Nothing,AbstractString} = nothing`: Input document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
|
||||
- `out_path::Union{Symbol,AbstractString} = :doc`: Path where the output is generated can be either of:
|
||||
* `:doc`: Path of the source document (default)
|
||||
* `:pwd`: Julia working directory
|
||||
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
|
||||
"""
|
||||
function tangle(
|
||||
source::AbstractString;
|
||||
out_path::Union{Symbol,AbstractString} = :doc,
|
||||
informat::Union{Nothing,AbstractString} = nothing,
|
||||
)
|
||||
doc = WeaveDoc(source, informat)
|
||||
doc.cwd = get_cwd(doc, out_path)
|
||||
|
||||
#Set the output directory
|
||||
if out_path == :doc
|
||||
cwd = cwd
|
||||
elseif out_path == :pwd
|
||||
cwd = pwd()
|
||||
else
|
||||
cwd = out_path
|
||||
end
|
||||
out_path = get_out_path(doc, out_path, "jl")
|
||||
|
||||
|
||||
outname = "$(cwd)/$(basename).jl"
|
||||
open(outname, "w") do io
|
||||
for chunk in read_document(source, informat)
|
||||
if chunk[:type] == "code"
|
||||
write(io, chunk[:content]*"\n")
|
||||
open(out_path, "w") do io
|
||||
for chunk in doc.chunks
|
||||
if typeof(chunk) == CodeChunk
|
||||
options = merge(doc.chunk_defaults, chunk.options)
|
||||
options[:tangle] && write(io, chunk.content * "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
info("Writing to file $(basename).jl")
|
||||
@info "Tangled to $(out_path)"
|
||||
end
|
||||
|
||||
@doc md"""
|
||||
"""
|
||||
weave(source::AbstractString; kwargs...)
|
||||
|
||||
Weave an input document to output file.
|
||||
|
||||
**parameters:**
|
||||
```julia
|
||||
weave(source ; doctype = "pandoc", plotlib="Gadfly",
|
||||
informat="noweb", out_path=:doc, fig_path = "figures", fig_ext = nothing)
|
||||
```
|
||||
## Keyword options
|
||||
|
||||
* `doctype`: see `list_out_formats()`
|
||||
* `plotlib`: `"PyPlot"`, `"Gadfly"`, or `"Winston"`
|
||||
* `informat`: `"noweb"` of `"markdown"`
|
||||
* `out_path`: Path where the output is generated. Can be: `:doc`: Path of the source document, `:pwd`: Julia working directory,
|
||||
`"somepath"`: Path as a string e.g `"/home/mpastell/weaveout"`
|
||||
* `fig_path`: where figures will be generated, relative to out_path
|
||||
* `fig_ext`: Extension for saved figures e.g. `".pdf"`, `".png"`. Default setting depends on `doctype`.
|
||||
- `doctype::Union{Nothing,AbstractString} = nothing`: Output document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also manually specify it; see [`list_out_formats()`](@ref) for the supported formats
|
||||
- `informat::Union{Nothing,AbstractString} = nothing`: Input document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
|
||||
- `out_path::Union{Symbol,AbstractString} = :doc`: Path where the output is generated can be either of:
|
||||
* `:doc`: Path of the source document (default)
|
||||
* `:pwd`: Julia working directory
|
||||
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
|
||||
- `args::Any = Dict()`: A runtime object that is available as `WEAVE_ARGS` while `weave`ing
|
||||
- `mod::Union{Module,Nothing} = nothing`: Module where Weave `eval`s code. You can pass a `Module` object, otherwise create an new sandbox module.
|
||||
- `fig_path::Union{Nothing,AbstractString} = nothing`: Where figures will be generated, relative to `out_path`. By default (i.e. given `nothing`), Weave will automatically create `$(DEFAULT_FIG_PATH)` directory.
|
||||
- `fig_ext::Union{Nothing,AbstractString} = nothing`: Extension for saved figures e.g. `".pdf"`, `".png"`. Default setting depends on `doctype`
|
||||
- `cache_path::AbstractString = "cache"`: Where of cached output will be saved
|
||||
- `cache::Symbol = :off`: Controls caching of code:
|
||||
* `:off` means no caching (default)
|
||||
* `:all` caches everything
|
||||
* `:user` caches based on chunk options
|
||||
* `:refresh` runs all code chunks and save new cache
|
||||
- `template::Union{Nothing,AbstractString,Mustache.MustacheTokens} = nothing`: Template (file path) or `Mustache.MustacheTokens`s for `md2html` or `md2tex` formats
|
||||
- `css::Union{Nothing,AbstractString} = nothing`: Path of a CSS file used for md2html format
|
||||
- `highlight_theme::Union{Nothing,Type{<:Highlights.AbstractTheme}} = nothing`: Theme used for syntax highlighting (defaults to `Highlights.Themes.DefaultTheme`)
|
||||
- `pandoc_options::Vector{<:AbstractString} = $(DEFAULT_PANDOC_OPTIONS)`: `String`s of options to pass to pandoc for `pandoc2html` and `pandoc2pdf` formats, e.g. `["--toc", "-N"]`
|
||||
- `latex_cmd::Vector{<:AbstractString} = $(DEFAULT_LATEX_CMD)`: The command used to make PDF file from .tex
|
||||
- `keep_unicode::Bool = false`: If `true`, do not convert unicode characters to their respective latex representation. This is especially useful if a font and tex-engine with support for unicode characters are used
|
||||
|
||||
**Note:** Run Weave from terminal and not using IJulia, Juno or ESS, they tend to mess with capturing output.
|
||||
""" ->
|
||||
function weave(source ; doctype = "pandoc", plotlib="Gadfly", informat="noweb", out_path=:doc, fig_path = "figures", fig_ext = nothing)
|
||||
!!! note
|
||||
Run Weave from terminal and try to avoid weaving from IJulia or ESS; they tend to mess with capturing output.
|
||||
"""
|
||||
function weave(
|
||||
source::AbstractString;
|
||||
doctype::Union{Nothing,AbstractString} = nothing,
|
||||
informat::Union{Nothing,AbstractString} = nothing,
|
||||
out_path::Union{Symbol,AbstractString} = :doc,
|
||||
args::Any = Dict(),
|
||||
mod::Union{Module,Nothing} = nothing,
|
||||
fig_path::Union{Nothing,AbstractString} = nothing,
|
||||
fig_ext::Union{Nothing,AbstractString} = nothing,
|
||||
cache_path::AbstractString = "cache",
|
||||
cache::Symbol = :off,
|
||||
template::Union{Nothing,AbstractString,Mustache.MustacheTokens} = nothing,
|
||||
css::Union{Nothing,AbstractString} = nothing, # TODO: rename to `stylesheet`
|
||||
highlight_theme::Union{Nothing,Type{<:Highlights.AbstractTheme}} = nothing,
|
||||
pandoc_options::Vector{<:AbstractString} = DEFAULT_PANDOC_OPTIONS,
|
||||
latex_cmd::Vector{<:AbstractString} = DEFAULT_LATEX_CMD,
|
||||
keep_unicode::Bool = false,
|
||||
)
|
||||
doc = WeaveDoc(source, informat)
|
||||
|
||||
cwd, fname = splitdir(abspath(source))
|
||||
basename = splitext(fname)[1]
|
||||
formatdict = formats[doctype].formatdict
|
||||
if fig_ext == nothing
|
||||
rcParams[:chunk_defaults][:fig_ext] = formatdict[:fig_ext]
|
||||
else
|
||||
rcParams[:chunk_defaults][:fig_ext] = fig_ext
|
||||
# run document
|
||||
# ------------
|
||||
|
||||
# overwrites options with those specified in header, that are needed for running document
|
||||
# NOTE: these YAML options can NOT be given dynamically
|
||||
weave_options = get(doc.header, WEAVE_OPTION_NAME, nothing)
|
||||
if haskey(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
|
||||
@warn "Weave: `options` key is deprecated. Use `weave_options` key instead." _id = WEAVE_OPTION_DEPRECATE_ID maxlog = 1
|
||||
weave_options = get(doc.header, WEAVE_OPTION_NAME_DEPRECATED, nothing)
|
||||
end
|
||||
|
||||
#Set the output directory
|
||||
if out_path == :doc
|
||||
report.cwd = cwd
|
||||
elseif out_path == :pwd
|
||||
report.cwd = pwd()
|
||||
else
|
||||
report.cwd = out_path
|
||||
end
|
||||
|
||||
|
||||
|
||||
report.source = source
|
||||
report.basename = basename
|
||||
rcParams[:chunk_defaults][:fig_path] = fig_path
|
||||
report.formatdict = formatdict
|
||||
|
||||
|
||||
if plotlib == nothing
|
||||
rcParams[:chunk_defaults][:fig] = false
|
||||
else
|
||||
l_plotlib = lowercase(plotlib)
|
||||
rcParams[:chunk_defaults][:fig] = true
|
||||
if l_plotlib == "winston"
|
||||
eval(parse("""include(Pkg.dir("Weave","src","winston.jl"))"""))
|
||||
rcParams[:plotlib] = "Winston"
|
||||
elseif l_plotlib == "pyplot"
|
||||
eval(Expr(:using, :PyPlot))
|
||||
rcParams[:plotlib] = "PyPlot"
|
||||
elseif l_plotlib == "gadfly"
|
||||
eval(parse("""include(Pkg.dir("Weave","src","gadfly.jl"))"""))
|
||||
rcParams[:plotlib] = "Gadfly"
|
||||
if !isnothing(weave_options)
|
||||
doctype = get(weave_options, "doctype", doctype)
|
||||
specific_options!(weave_options, doctype)
|
||||
if haskey(weave_options, "out_path")
|
||||
out_path = let
|
||||
out_path = weave_options["out_path"]
|
||||
if out_path == ":doc" || out_path == ":pwd"
|
||||
Symbol(out_path)
|
||||
else
|
||||
normpath(dirname(source), out_path) # resolve relative to this document
|
||||
end
|
||||
end
|
||||
end
|
||||
mod = get(weave_options, "mod", mod)
|
||||
mod isa AbstractString && (mod = Main.eval(Meta.parse(mod)))
|
||||
fig_path = get(weave_options, "fig_path", fig_path)
|
||||
fig_ext = get(weave_options, "fig_ext", fig_ext)
|
||||
cache_path = get(weave_options, "cache_path", cache_path)
|
||||
cache = Symbol(get(weave_options, "cache", cache))
|
||||
end
|
||||
|
||||
pushdisplay(report)
|
||||
parsed = read_document(source, informat)
|
||||
executed = run(parsed)
|
||||
popdisplay(report)
|
||||
formatted = format(executed, doctype)
|
||||
outname = "$(report.cwd)/$(report.basename).$(formatdict[:extension])"
|
||||
open(outname, "w") do io
|
||||
write(io, join(formatted, "\n"))
|
||||
doc = run_doc(
|
||||
doc;
|
||||
doctype = doctype,
|
||||
mod = mod,
|
||||
out_path = out_path,
|
||||
args = args,
|
||||
fig_path = fig_path,
|
||||
fig_ext = fig_ext,
|
||||
cache_path = cache_path,
|
||||
cache = cache,
|
||||
)
|
||||
|
||||
# overwrites options with those specified in header, that are needed for rendering/writing document
|
||||
# NOTE: these YAML options can be given dynamically
|
||||
if !isnothing(weave_options)
|
||||
if haskey(weave_options, "template")
|
||||
template = weave_options["template"]
|
||||
# resolve relative to this document
|
||||
template isa AbstractString && (template = normpath(dirname(source), template))
|
||||
end
|
||||
if haskey(weave_options, "css")
|
||||
css = weave_options["css"]
|
||||
# resolve relative to this document
|
||||
css isa AbstractString && (css = normpath(dirname(source), css))
|
||||
end
|
||||
highlight_theme = get(weave_options, "highlight_theme", highlight_theme)
|
||||
keep_unicode = get(weave_options, "keep_unicode", keep_unicode)
|
||||
latex_cmd = get(weave_options, "latex_cmd", latex_cmd)
|
||||
pandoc_options = get(weave_options, "pandoc_options", pandoc_options)
|
||||
end
|
||||
|
||||
info("Report weaved to $(report.basename).$(formatdict[:extension])")
|
||||
set_format_options!(
|
||||
doc;
|
||||
# general
|
||||
template = template,
|
||||
highlight_theme = highlight_theme,
|
||||
css = css,
|
||||
# pandoc
|
||||
pandoc_options = pandoc_options,
|
||||
# latex
|
||||
keep_unicode = keep_unicode,
|
||||
latex_cmd = latex_cmd,
|
||||
)
|
||||
|
||||
# render document
|
||||
# ---------------
|
||||
rendered = render_doc(doc)
|
||||
|
||||
# write documents
|
||||
# ---------------
|
||||
out_path = write_doc(doc, rendered, get_out_path(doc, out_path))
|
||||
|
||||
@info "Weaved to $(out_path)"
|
||||
return out_path
|
||||
end
|
||||
|
||||
weave(doc::AbstractString, doctype::Union{Symbol,AbstractString}; kwargs...) =
|
||||
weave(doc; doctype = doctype, kwargs...)
|
||||
|
||||
function specific_options!(weave_options, doctype)
|
||||
fmts = keys(FORMATS)
|
||||
for (k,v) in weave_options
|
||||
if k in fmts
|
||||
k == doctype && merge!(weave_options, v)
|
||||
delete!(weave_options, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
get_out_path(doc, out_path, ext::Nothing = nothing) = get_out_path(doc, out_path, doc.format.extension)
|
||||
function get_out_path(doc, out_path, ext)
|
||||
if (out_path === :doc) || (out_path === :pwd)
|
||||
abspath(get_cwd(doc, out_path), string(doc.basename, '.', ext))
|
||||
elseif isempty(splitext(out_path)[2]) # directory given
|
||||
abspath(get_cwd(doc, out_path), string(doc.basename, '.', ext))
|
||||
else
|
||||
# out_path is given, but if extension is explitly provided override this will override the extension
|
||||
abspath(string(splitext(out_path)[1], '.', ext))
|
||||
end
|
||||
end
|
||||
"""
|
||||
notebook(source::AbstractString; kwargs...)
|
||||
|
||||
Convert Weave document `source` to Jupyter Notebook and execute the code
|
||||
using [`nbconvert`](https://nbconvert.readthedocs.io/en/latest/).
|
||||
**Ignores** all chunk options.
|
||||
|
||||
function run_block(code_str)
|
||||
oldSTDOUT = STDOUT
|
||||
result = ""
|
||||
## Keyword options
|
||||
|
||||
rw, wr = redirect_stdout()
|
||||
#If there is nothing to read code will hang
|
||||
println()
|
||||
- `out_path::Union{Symbol,AbstractString} = :pwd`: Path where the output is generated can be either of:
|
||||
* `:doc`: Path of the source document
|
||||
* `:pwd`: Julia working directory (default)
|
||||
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
|
||||
- `timeout = -1`: nbconvert cell timeout in seconds. Defaults to `-1` (no timeout)
|
||||
- `nbconvert_options::AbstractString = ""`: `String` of additional options to pass to nbconvert, such as `"--allow-errors"`
|
||||
- `jupyter_path::AbstractString = "jupyter"`: Path/command for the Jupyter you want to use. Defaults to `"jupyter"`, which runs whatever is linked/alias to that
|
||||
|
||||
!!! warning
|
||||
The code is _**not**_ executed by Weave, but by [`nbconvert`](https://nbconvert.readthedocs.io/en/latest/).
|
||||
This means that the output doesn't necessarily always work properly; see [#116](https://github.com/JunoLab/Weave.jl/issues/116).
|
||||
|
||||
!!! note
|
||||
In order to _just_ convert Weave document to Jupyter Notebook,
|
||||
use [`convert_doc`](@ref) instead.
|
||||
"""
|
||||
function notebook(
|
||||
source::AbstractString;
|
||||
out_path::Union{Symbol,AbstractString} = :pwd,
|
||||
timeout = -1,
|
||||
nbconvert_options::AbstractString = "",
|
||||
jupyter_path::AbstractString = "jupyter",
|
||||
)
|
||||
doc = WeaveDoc(source)
|
||||
converted = convert_to_notebook(doc)
|
||||
doc.cwd = get_cwd(doc, out_path)
|
||||
out_path = get_out_path(doc, out_path, "ipynb")
|
||||
|
||||
write(out_path, converted)
|
||||
|
||||
@info "Running nbconvert ..."
|
||||
return read(
|
||||
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $(out_path) $nbconvert_options --output $(out_path)`,
|
||||
String,
|
||||
)
|
||||
end
|
||||
|
||||
"""
|
||||
include_weave(source::AbstractString, informat::Union{Nothing,AbstractString} = nothing)
|
||||
include_weave(m::Module, source::AbstractString, informat::Union{Nothing,AbstractString} = nothing)
|
||||
|
||||
Include code from Weave document calling `include_string` on all code from doc.
|
||||
Code is run in the path of the include document.
|
||||
"""
|
||||
function include_weave(
|
||||
m::Module,
|
||||
source::AbstractString,
|
||||
informat::Union{Nothing,AbstractString} = nothing,
|
||||
)
|
||||
old_path = pwd()
|
||||
doc = WeaveDoc(source, informat)
|
||||
cd(dirname(doc.path))
|
||||
try
|
||||
n = length(code_str)
|
||||
pos = 1 #The first character is extra line end
|
||||
while pos < n
|
||||
oldpos = pos
|
||||
code, pos = parse(code_str, pos)
|
||||
s = eval(ReportSandBox, code)
|
||||
if rcParams[:plotlib] == "Gadfly"
|
||||
s != nothing && display(s)
|
||||
end
|
||||
end
|
||||
code = join(
|
||||
[x.content for x in filter(x -> isa(x, Weave.CodeChunk), doc.chunks)],
|
||||
"\n",
|
||||
)
|
||||
include_string(m, code)
|
||||
catch err
|
||||
throw(err)
|
||||
finally
|
||||
|
||||
redirect_stdout(oldSTDOUT)
|
||||
close(wr)
|
||||
result = readall(rw)
|
||||
close(rw)
|
||||
cd(old_path)
|
||||
end
|
||||
|
||||
return string("\n", result)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function run_term(code_str)
|
||||
prompt = "\njulia> "
|
||||
codestart = "\n\n"*report.formatdict[:codestart]
|
||||
include_weave(source, informat = nothing) = include_weave(Main, source, informat)
|
||||
|
||||
if haskey(report.formatdict, :indent)
|
||||
prompt = indent(prompt, report.formatdict[:indent])
|
||||
end
|
||||
|
||||
#Emulate terminal
|
||||
n = length(code_str)
|
||||
pos = 2 #The first character is extra line end
|
||||
while pos < n
|
||||
oldpos = pos
|
||||
code, pos = parse(code_str, pos)
|
||||
export weave,
|
||||
list_out_formats,
|
||||
tangle,
|
||||
convert_doc,
|
||||
notebook,
|
||||
set_chunk_defaults!,
|
||||
get_chunk_defaults,
|
||||
restore_chunk_defaults!,
|
||||
include_weave
|
||||
|
||||
report.term_state == :fig && (report.cur_result*= codestart)
|
||||
prompts = string(prompt, rstrip(code_str[oldpos:(pos-1)]), "\n")
|
||||
report.cur_result *= prompts
|
||||
report.term_state = :text
|
||||
s = eval(ReportSandBox, code)
|
||||
s != nothing && display(s)
|
||||
end
|
||||
|
||||
return string(report.cur_result)
|
||||
end
|
||||
|
||||
|
||||
function run(parsed)
|
||||
#Clear sandbox for each document
|
||||
#Raises a warning, couldn't find a "cleaner"
|
||||
#way to do it.
|
||||
eval(parse("module ReportSandBox\nend"))
|
||||
|
||||
i = 1
|
||||
for chunk in copy(parsed)
|
||||
if chunk[:type] == "code"
|
||||
#print(chunk["content"])
|
||||
info("Weaving chunk $(chunk[:number]) from line $(chunk[:start_line])")
|
||||
defaults = copy(rcParams[:chunk_defaults])
|
||||
options = copy(chunk[:options])
|
||||
try
|
||||
options = merge(rcParams[:chunk_defaults], options)
|
||||
catch
|
||||
options = rcParams[:chunk_defaults]
|
||||
warn("Invalid format for chunk options line: $(chunk[:start_line])")
|
||||
end
|
||||
|
||||
merge!(chunk, options)
|
||||
delete!(chunk, :options)
|
||||
|
||||
if !chunk[:eval]
|
||||
chunk[:result] = ""
|
||||
chunk[:fig] = false
|
||||
parsed[i] = copy(chunk)
|
||||
i += 1
|
||||
continue #Do nothing if eval is false
|
||||
end
|
||||
|
||||
report.fignum = 1
|
||||
report.cur_result = ""
|
||||
report.figures = String[]
|
||||
report.cur_chunk = chunk
|
||||
report.term_state = :text
|
||||
if haskey(report.formatdict, :out_width) && chunk[:out_width] == nothing
|
||||
chunk[:out_width] = report.formatdict[:out_width]
|
||||
end
|
||||
|
||||
if chunk[:term]
|
||||
chunk[:result] = run_term(chunk[:content])
|
||||
chunk[:term_state] = report.term_state
|
||||
else
|
||||
chunk[:result] = run_block(chunk[:content])
|
||||
end
|
||||
|
||||
if rcParams[:plotlib] == "PyPlot"
|
||||
chunk[:fig] && (chunk[:figure] = savefigs(chunk))
|
||||
else
|
||||
chunk[:fig] && (chunk[:figure] = copy(report.figures))
|
||||
end
|
||||
end
|
||||
parsed[i] = copy(chunk)
|
||||
i += 1
|
||||
end
|
||||
parsed
|
||||
end
|
||||
|
||||
function savefigs(chunk)
|
||||
l_plotlib = lowercase(rcParams[:plotlib])
|
||||
if l_plotlib == "pyplot"
|
||||
return savefigs_pyplot(chunk)
|
||||
end
|
||||
end
|
||||
|
||||
function savefigs_pyplot(chunk)
|
||||
fignames = String[]
|
||||
ext = report.formatdict[:fig_ext]
|
||||
figpath = joinpath(report.cwd, chunk[:fig_path])
|
||||
isdir(figpath) || mkdir(figpath)
|
||||
chunkid = (chunk[:name] == nothing) ? chunk[:number] : chunk[:name]
|
||||
#Iterate over all open figures, save them and store names
|
||||
for fig = plt.get_fignums()
|
||||
full_name, rel_name = get_figname(report, chunk, fignum=fig)
|
||||
savefig(full_name, dpi=chunk[:dpi])
|
||||
push!(fignames, rel_name)
|
||||
plt.draw()
|
||||
plt.close()
|
||||
end
|
||||
return fignames
|
||||
end
|
||||
|
||||
|
||||
function Base.display(report::Report, m::MIME"text/plain", data)
|
||||
if report.term_state == :fig #Catch Winston plot command output
|
||||
report.cur_result *= "\n" * report.formatdict[:codestart] * "\n"
|
||||
end
|
||||
|
||||
s = reprmime(m, data)
|
||||
haskey(report.formatdict, :indent) && (s = indent(s, report.formatdict[:indent]))
|
||||
|
||||
report.cur_result *= s * "\n"
|
||||
|
||||
if report.term_state == :fig #Catch Winston plot command output
|
||||
report.cur_result *= "\n" * report.formatdict[:codeend] * "\n"
|
||||
end
|
||||
end
|
||||
|
||||
function get_figname(report::Report, chunk; fignum = nothing)
|
||||
figpath = joinpath(report.cwd, chunk[:fig_path])
|
||||
isdir(figpath) || mkdir(figpath)
|
||||
ext = chunk[:fig_ext]
|
||||
fignum == nothing && (fignum = report.fignum)
|
||||
|
||||
chunkid = (chunk[:name] == nothing) ? chunk[:number] : chunk[:name]
|
||||
full_name = joinpath(report.cwd, chunk[:fig_path], "$(report.basename)_$(chunkid)_$(fignum)$ext")
|
||||
rel_name = "$(chunk[:fig_path])/$(report.basename)_$(chunkid)_$(fignum)$ext" #Relative path is used in output
|
||||
return full_name, rel_name
|
||||
end
|
||||
|
||||
export weave, list_out_formats, tangle
|
||||
|
||||
include("config.jl")
|
||||
include("readers.jl")
|
||||
include("formatters.jl")
|
||||
end
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
# Markdown to HTML writer, Modified from Julia Base.Markdown html writer
|
||||
|
||||
using Markdown:
|
||||
MD,
|
||||
Header,
|
||||
Code,
|
||||
Paragraph,
|
||||
BlockQuote,
|
||||
Footnote,
|
||||
Table,
|
||||
Admonition,
|
||||
List,
|
||||
HorizontalRule,
|
||||
Bold,
|
||||
Italic,
|
||||
Image,
|
||||
Link,
|
||||
LineBreak,
|
||||
LaTeX,
|
||||
isordered
|
||||
|
||||
|
||||
tohtml(io::IO, m::MIME"text/html", x) = show(io, m, x)
|
||||
|
||||
tohtml(io::IO, m::MIME"text/plain", x) = htmlesc(io, sprint(show, m, x))
|
||||
|
||||
function tohtml(io::IO, m::MIME"image/png", img)
|
||||
print(io, """<img src="data:image/png;base64,""")
|
||||
print(io, stringmime(m, img))
|
||||
print(io, "\" />")
|
||||
end
|
||||
|
||||
tohtml(m::MIME"image/svg+xml", img) = show(io, m, img)
|
||||
|
||||
# AbstractDisplay infrastructure
|
||||
|
||||
function bestmime(val)
|
||||
for mime in ("text/html", "image/svg+xml", "image/png", "text/plain")
|
||||
showable(mime, val) && return MIME(Symbol(mime))
|
||||
end
|
||||
error("Cannot render $val to Markdown.")
|
||||
end
|
||||
|
||||
tohtml(io::IO, x) = tohtml(io, bestmime(x), x)
|
||||
|
||||
# Utils
|
||||
|
||||
function withtag(f, io::IO, tag, attrs...)
|
||||
print(io, "<$tag")
|
||||
for (attr, value) in attrs
|
||||
print(io, " ")
|
||||
htmlesc(io, attr)
|
||||
print(io, "=\"")
|
||||
htmlesc(io, value)
|
||||
print(io, "\"")
|
||||
end
|
||||
f === nothing && return print(io, " />")
|
||||
|
||||
print(io, ">")
|
||||
f()
|
||||
print(io, "</$tag>")
|
||||
end
|
||||
|
||||
tag(io::IO, tag, attrs...) = withtag(nothing, io, tag, attrs...)
|
||||
|
||||
const _htmlescape_chars = Dict(
|
||||
'<' => "<",
|
||||
'>' => ">",
|
||||
'"' => """,
|
||||
'&' => "&",
|
||||
# ' '=>" ",
|
||||
)
|
||||
for ch in "'`!\$%()=+{}[]"
|
||||
_htmlescape_chars[ch] = "&#$(Int(ch));"
|
||||
end
|
||||
|
||||
function htmlesc(io::IO, s::AbstractString)
|
||||
# s1 = replace(s, r"&(?!(\w+|\#\d+);)" => "&")
|
||||
for ch in s
|
||||
print(io, get(_htmlescape_chars, ch, ch))
|
||||
end
|
||||
end
|
||||
function htmlesc(io::IO, s::Symbol)
|
||||
htmlesc(io, string(s))
|
||||
end
|
||||
function htmlesc(io::IO, xs::Union{AbstractString,Symbol}...)
|
||||
for s in xs
|
||||
htmlesc(io, s)
|
||||
end
|
||||
end
|
||||
function htmlesc(s::Union{AbstractString,Symbol})
|
||||
sprint(htmlesc, s)
|
||||
end
|
||||
|
||||
# Block elements
|
||||
|
||||
function html(io::IO, content::Vector)
|
||||
for md in content
|
||||
html(io, md)
|
||||
println(io)
|
||||
end
|
||||
end
|
||||
|
||||
html(io::IO, md::MD) = html(io, md.content)
|
||||
|
||||
function html(io::IO, header::Header{l}) where {l}
|
||||
withtag(io, "h$l") do
|
||||
htmlinline(io, header.text)
|
||||
end
|
||||
end
|
||||
|
||||
function html(io::IO, code::Code)
|
||||
withtag(io, :pre) do
|
||||
maybe_lang = !isempty(code.language) ? Any[:class=>"language-$(code.language)"] : []
|
||||
withtag(io, :code, maybe_lang...) do
|
||||
htmlesc(io, code.code)
|
||||
# TODO should print newline if this is longer than one line ?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function html(io::IO, md::Paragraph)
|
||||
withtag(io, :p) do
|
||||
htmlinline(io, md.content)
|
||||
end
|
||||
end
|
||||
|
||||
function html(io::IO, md::BlockQuote)
|
||||
withtag(io, :blockquote) do
|
||||
println(io)
|
||||
html(io, md.content)
|
||||
end
|
||||
end
|
||||
|
||||
function html(io::IO, f::Footnote)
|
||||
withtag(io, :div, :class => "footnote", :id => "footnote-$(f.id)") do
|
||||
withtag(io, :p, :class => "footnote-title") do
|
||||
print(io, f.id)
|
||||
end
|
||||
html(io, f.text)
|
||||
end
|
||||
end
|
||||
|
||||
function html(io::IO, md::Admonition)
|
||||
withtag(io, :div, :class => "admonition $(md.category)") do
|
||||
withtag(io, :p, :class => "admonition-title") do
|
||||
print(io, md.title)
|
||||
end
|
||||
html(io, md.content)
|
||||
end
|
||||
end
|
||||
|
||||
function html(io::IO, md::List)
|
||||
maybe_attr = md.ordered > 1 ? Any[:start=>string(md.ordered)] : []
|
||||
withtag(io, isordered(md) ? :ol : :ul, maybe_attr...) do
|
||||
for item in md.items
|
||||
println(io)
|
||||
withtag(io, :li) do
|
||||
html(io, item)
|
||||
end
|
||||
end
|
||||
println(io)
|
||||
end
|
||||
end
|
||||
|
||||
html(io::IO, md::HorizontalRule) = tag(io, :hr)
|
||||
|
||||
function html(io::IO, tex::LaTeX)
|
||||
withtag(io, :p, :class => "math") do
|
||||
write(io, string("\\[\n", tex.formula, "\n\\]"))
|
||||
end
|
||||
end
|
||||
|
||||
html(io::IO, comment::Comment) = write(io, "\n<!-- $(comment.text) -->\n")
|
||||
|
||||
function html(io::IO, md::Table)
|
||||
withtag(io, :table) do
|
||||
for (i, row) in enumerate(md.rows)
|
||||
withtag(io, :tr) do
|
||||
for c in md.rows[i]
|
||||
withtag(io, i == 1 ? :th : :td) do
|
||||
htmlinline(io, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
html(io::IO, x) = tohtml(io, x)
|
||||
|
||||
# Inline elements
|
||||
|
||||
function htmlinline(io::IO, content::Vector)
|
||||
for x in content
|
||||
htmlinline(io, x)
|
||||
end
|
||||
end
|
||||
|
||||
function htmlinline(io::IO, code::Code)
|
||||
withtag(io, :code) do
|
||||
htmlesc(io, code.code)
|
||||
end
|
||||
end
|
||||
|
||||
function htmlinline(io::IO, tex::LaTeX)
|
||||
withtag(io, :span, :class => "math") do
|
||||
write(io, string("\$", tex.formula, "\$"))
|
||||
end
|
||||
end
|
||||
|
||||
htmlinline(io::IO, md::Union{Symbol,AbstractString}) = htmlesc(io, md)
|
||||
|
||||
function htmlinline(io::IO, md::Bold)
|
||||
withtag(io, :strong) do
|
||||
htmlinline(io, md.text)
|
||||
end
|
||||
end
|
||||
|
||||
function htmlinline(io::IO, md::Italic)
|
||||
withtag(io, :em) do
|
||||
htmlinline(io, md.text)
|
||||
end
|
||||
end
|
||||
|
||||
htmlinline(io::IO, md::Image) = tag(io, :img, :src => md.url, :alt => md.alt)
|
||||
|
||||
function htmlinline(io::IO, f::Footnote)
|
||||
withtag(io, :a, :href => "#footnote-$(f.id)", :class => "footnote") do
|
||||
print(io, "[", f.id, "]")
|
||||
end
|
||||
end
|
||||
|
||||
function htmlinline(io::IO, link::Link)
|
||||
withtag(io, :a, :href => link.url) do
|
||||
htmlinline(io, link.text)
|
||||
end
|
||||
end
|
||||
|
||||
htmlinline(io::IO, br::LineBreak) = tag(io, :br)
|
||||
|
||||
htmlinline(io::IO, comment::Comment) = write(io, "<!-- $(comment.text) -->")
|
||||
|
||||
htmlinline(io::IO, x) = tohtml(io, x)
|
||||
|
||||
# API
|
||||
|
||||
html(md) = sprint(html, md)
|
|
@ -0,0 +1,9 @@
|
|||
import Markdown: latex, latexinline
|
||||
|
||||
function latex(io::IO, comment::Comment)
|
||||
for line in split(comment.text, r"\r\n|\n")
|
||||
write(io, "% $line\n")
|
||||
end
|
||||
end
|
||||
|
||||
latexinline(io, comment::Comment) = write(io, "")
|
|
@ -0,0 +1,92 @@
|
|||
# This module extends the julia markdown parser to improve compatibility with Jupyter, Pandoc etc.
|
||||
module WeaveMarkdown
|
||||
|
||||
using ..Weave: isnothing, take2string!
|
||||
using Markdown
|
||||
import Markdown: @trigger, @breaking, Code, MD, withstream, startswith, LaTeX
|
||||
|
||||
# HACK: that this definition is type-piracy. It is required since `Markdown`
|
||||
# does not have a built in system for contextual rendering by users. `io` here
|
||||
# should always be either `IOBuffer` or `IOContext` since it is reached via
|
||||
# `sprint` in all user-facing code paths in `Markdown`.
|
||||
function Markdown.latex(io::Union{IOBuffer,IOContext}, tex::Markdown.LaTeX)
|
||||
math_envs = ["align", "equation", "eqnarray"]
|
||||
use_dollars =
|
||||
!any([occursin("\\begin{$me", tex.formula) for me in math_envs])
|
||||
use_dollars && write(io, "\\[")
|
||||
write(io, string("\n", tex.formula, "\n"))
|
||||
use_dollars && write(io, "\\]\n")
|
||||
end
|
||||
|
||||
mutable struct Comment
|
||||
text::String
|
||||
end
|
||||
|
||||
@breaking true -> function dollarmath(stream::IO, block::MD)
|
||||
withstream(stream) do
|
||||
str = Markdown.startswith(stream, r"^\$\$$"m)
|
||||
isempty(str) && return false
|
||||
trailing = strip(readline(stream))
|
||||
buffer = IOBuffer()
|
||||
while !eof(stream)
|
||||
line_start = position(stream)
|
||||
estr = Markdown.startswith(stream, r"^\$\$$"m)
|
||||
if !isempty(estr)
|
||||
estr = Markdown.startswith(stream, r"^\$\$$"m)
|
||||
if isempty(estr)
|
||||
push!(block, LaTeX(take2string!(buffer) |> chomp))
|
||||
end
|
||||
return true
|
||||
else
|
||||
seek(stream, line_start)
|
||||
end
|
||||
write(buffer, readline(stream, keep = true))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
@breaking true -> function topcomment(stream::IO, block::MD)
|
||||
buffer = IOBuffer()
|
||||
withstream(stream) do
|
||||
str = Markdown.startswith(stream, r"^<!--")
|
||||
isempty(str) && return false
|
||||
while !eof(stream)
|
||||
line = readline(stream, keep = true)
|
||||
write(buffer, line)
|
||||
if occursin(r"-->$", line)
|
||||
s = replace(take2string!(buffer) |> chomp, r"-->$" => "")
|
||||
push!(block, Comment(s))
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
@trigger '<' -> function comment(stream::IO, md::MD)
|
||||
withstream(stream) do
|
||||
Markdown.startswith(stream, "<!--") || return
|
||||
text = Markdown.readuntil(stream, "-->")
|
||||
isnothing(text) && return
|
||||
return Comment(text)
|
||||
end
|
||||
end
|
||||
|
||||
# Create own flavor and copy all the features from julia flavor
|
||||
Markdown.@flavor weavemd [dollarmath, comment, topcomment]
|
||||
weavemd.breaking = [weavemd.breaking; Markdown.julia.breaking]
|
||||
weavemd.regular = [weavemd.regular; Markdown.julia.regular]
|
||||
for key in keys(Markdown.julia.inner)
|
||||
if haskey(weavemd.inner, key)
|
||||
weavemd.inner[key] = [weavemd.inner[key]; Markdown.julia.inner[key]]
|
||||
else
|
||||
weavemd.inner[key] = Markdown.julia.inner[key]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
include("html.jl")
|
||||
include("latex.jl")
|
||||
|
||||
end # module
|
|
@ -0,0 +1,64 @@
|
|||
# Serialization is imported only if cache is used
|
||||
|
||||
function write_cache(doc::WeaveDoc, cache_path)
|
||||
cache_dir = joinpath(doc.cwd, cache_path)
|
||||
isdir(cache_dir) || mkpath(cache_dir)
|
||||
open(joinpath(cache_dir, doc.basename * ".cache"), "w") do io
|
||||
Serialization.serialize(io, doc)
|
||||
end
|
||||
return nothing
|
||||
end
|
||||
|
||||
function read_cache(doc::WeaveDoc, cache_path)
|
||||
name = joinpath(doc.cwd, cache_path, doc.basename * ".cache")
|
||||
isfile(name) || return nothing
|
||||
open(name, "r") do io
|
||||
doc = Serialization.deserialize(io)
|
||||
end
|
||||
return doc
|
||||
end
|
||||
|
||||
function restore_chunk(chunk::CodeChunk, cached)
|
||||
chunks = filter(
|
||||
x -> x.number == chunk.number && string(typeof(x)) == "Weave.CodeChunk",
|
||||
cached.chunks,
|
||||
)
|
||||
|
||||
# Chunk types, don't match after loading. Fix by constructing chunks
|
||||
# from loaded content
|
||||
new_chunks = []
|
||||
for c in chunks
|
||||
newc = CodeChunk(c.content, c.number, c.start_line, c.optionstring, c.options)
|
||||
newc.figures = c.figures
|
||||
newc.result = c.result
|
||||
newc.output = c.output
|
||||
newc.rich_output = c.rich_output
|
||||
push!(new_chunks, newc)
|
||||
end
|
||||
return new_chunks
|
||||
end
|
||||
|
||||
# Restore inline code
|
||||
function restore_chunk(chunk::DocChunk, cached::WeaveDoc)
|
||||
# Get chunk from cached doc
|
||||
c_chunk = filter(x -> x.number == chunk.number && isa(x, DocChunk), cached.chunks)
|
||||
isempty(c_chunk) && return chunk
|
||||
c_chunk = c_chunk[1]
|
||||
|
||||
# Collect cached code
|
||||
c_inline = filter(x -> isa(x, InlineCode), c_chunk.content)
|
||||
isempty(c_inline) && return chunk
|
||||
|
||||
# Restore cached results for Inline code
|
||||
n = length(chunk.content)
|
||||
for i = 1:n
|
||||
if isa(chunk.content[i], InlineCode)
|
||||
ci = filter(x -> x.number == chunk.content[i].number, c_inline)
|
||||
isempty(ci) && continue
|
||||
chunk.content[i].output = ci[1].output
|
||||
chunk.content[i].rich_output = ci[1].rich_output
|
||||
chunk.content[i].figures = ci[1].figures
|
||||
end
|
||||
end
|
||||
return chunk
|
||||
end
|
135
src/config.jl
135
src/config.jl
|
@ -1,77 +1,58 @@
|
|||
const rcParams =
|
||||
@compat Dict{Symbol,Any}(:plotlib => "PyPlot",
|
||||
:storeresults => false,
|
||||
:chunk_defaults =>
|
||||
Dict{Symbol,Any}(
|
||||
:echo=> true,
|
||||
:results=> "markup",
|
||||
:fig=> true,
|
||||
:include=> true,
|
||||
:eval => true,
|
||||
:fig_cap=> nothing,
|
||||
#Size in inches
|
||||
:fig_width => 6,
|
||||
:fig_height => 4,
|
||||
:fig_path=> "figures",
|
||||
:dpi => 96,
|
||||
:term=> false,
|
||||
:name=> nothing,
|
||||
:wrap=> true,
|
||||
:engine=> "julia",
|
||||
:option_string=> "",
|
||||
#Defined in formats
|
||||
:fig_ext => nothing,
|
||||
:fig_pos=> nothing,
|
||||
:fig_env=> nothing,
|
||||
:out_width=> nothing,
|
||||
:out_height=> nothing,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Working towards Knitr compatible options, implemented options are
|
||||
# added to defaultoptions dictionary above and work in progress stays here,
|
||||
# options from https://github.com/yihui/knitr/blob/master/R/defaults.R
|
||||
# If you need a particular options, consider implementing it and making a
|
||||
# pull request.
|
||||
|
||||
#tidy = FALSE,
|
||||
#tidy.opts = NULL,
|
||||
#collapse = FALSE
|
||||
#prompt = FALSE
|
||||
#highlight = TRUE
|
||||
#strip.white = TRUE
|
||||
#size = 'normalsize'
|
||||
#background = '#F7F7F7',
|
||||
#cache = FALSE
|
||||
#cache.path = 'cache/'
|
||||
#cache.vars = NULL
|
||||
#cache.lazy = TRUE,
|
||||
#dependson = NULL
|
||||
#autodep = FALSE,
|
||||
#fig.keep = 'high'
|
||||
#fig.show = 'asis'
|
||||
#fig.align = 'default'
|
||||
#dev = NULL
|
||||
#dev.args = NULL
|
||||
#fig.ext = NULL
|
||||
#fig.scap = NULL
|
||||
#fig.lp = 'fig:'
|
||||
#fig.subcap = NULL,
|
||||
#out.extra = NULL
|
||||
#fig.retina = 1,
|
||||
#external = TRUE
|
||||
#sanitize = FALSE
|
||||
#interval = 1
|
||||
#aniopts = 'controls,loop',
|
||||
#warning = TRUE
|
||||
#error = TRUE
|
||||
#message = TRUE,
|
||||
#render = NULL,
|
||||
#ref.label = NULL
|
||||
#child = NULL
|
||||
#split = FALSE
|
||||
#purl = TRUE
|
||||
# TODO: follow RMarkdown convention more
|
||||
const _DEFAULT_PARAMS = Dict{Symbol,Any}(
|
||||
:echo => true,
|
||||
:results => "markup",
|
||||
:hold => false,
|
||||
:fig => true,
|
||||
:eval => true,
|
||||
:error => true,
|
||||
:tangle => true,
|
||||
:cache => false,
|
||||
:fig_cap => nothing,
|
||||
# NOTE: size in inches
|
||||
:fig_width => 6,
|
||||
:fig_height => 4,
|
||||
:fig_path => DEFAULT_FIG_PATH,
|
||||
:dpi => 96,
|
||||
:term => false,
|
||||
:prompt => "julia>",
|
||||
:label => nothing,
|
||||
:wrap => true,
|
||||
:line_width => 75,
|
||||
:fig_ext => nothing,
|
||||
:fig_pos => nothing,
|
||||
:fig_env => nothing,
|
||||
:out_width => nothing,
|
||||
:out_height => nothing,
|
||||
)
|
||||
const DEFAULT_PARAMS = deepcopy(_DEFAULT_PARAMS) # might be changed at runtime
|
||||
|
||||
"""
|
||||
set_chunk_defaults!(k, v)
|
||||
set_chunk_defaults!(kv::Pair...)
|
||||
set_chunk_defaults!(opts::AbstractDict)
|
||||
|
||||
Set default options for code chunks, use [`get_chunk_defaults`](@ref) to see the current values.
|
||||
|
||||
E.g.: all the three examples below will set default `dpi` to `200` and `fig_width` to `8`:
|
||||
- `set_chunk_defaults!(:dpi, 200); set_chunk_defaults!(:fig_width, 8)`
|
||||
- `set_chunk_defaults!(:dpi => 200, :fig_width => 8)`
|
||||
- `set_chunk_defaults!(Dict(:dpi => 200, :fig_width => 8))`
|
||||
"""
|
||||
set_chunk_defaults!(k, v) = DEFAULT_PARAMS[k]= v
|
||||
set_chunk_defaults!(kv::Pair...) = for (k,v) in kv; set_chunk_defaults!(k, v); end
|
||||
set_chunk_defaults!(opts::AbstractDict) = merge!(DEFAULT_PARAMS, opts)
|
||||
|
||||
"""
|
||||
get_chunk_defaults()
|
||||
|
||||
Get default options used for code chunks.
|
||||
"""
|
||||
get_chunk_defaults() = DEFAULT_PARAMS
|
||||
|
||||
"""
|
||||
restore_chunk_defaults!()
|
||||
|
||||
Restore Weave.jl default chunk options.
|
||||
"""
|
||||
restore_chunk_defaults!() = for (k,v) in _DEFAULT_PARAMS; DEFAULT_PARAMS[k] = v; end
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
using JSON, Mustache
|
||||
|
||||
"""
|
||||
convert_doc(infile::AbstractString, outfile::AbstractString; outformat::Union{Nothing,AbstractString} = nothing)
|
||||
|
||||
Convert Weave documents between different formats
|
||||
|
||||
- `infile`: Path of the input document
|
||||
- `outfile`: Path of the output document
|
||||
- `outformat = nothing`: Output document format (optional). By default (i.e. given `nothing`) Weave will try to automatically detect it from the `outfile`'s extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
|
||||
"""
|
||||
function convert_doc(
|
||||
infile::AbstractString,
|
||||
outfile::AbstractString;
|
||||
outformat::Union{Nothing,AbstractString} = nothing,
|
||||
)
|
||||
doc = WeaveDoc(infile)
|
||||
|
||||
if isnothing(outformat)
|
||||
ext = lowercase(splitext(outfile)[2])
|
||||
outformat =
|
||||
ext == ".jl" ? "script" :
|
||||
ext == ".jmd" ? "markdown" :
|
||||
ext == ".ipynb" ? "notebook" :
|
||||
"noweb" # fallback
|
||||
end
|
||||
|
||||
converted = _convert_doc(doc, outformat)
|
||||
|
||||
open(outfile, "w") do f
|
||||
write(f, converted)
|
||||
end
|
||||
return outfile
|
||||
end
|
||||
|
||||
function _convert_doc(doc, outformat)
|
||||
outformat == "script" ? convert_to_script(doc) :
|
||||
outformat == "markdown" ? convert_to_markdown(doc) :
|
||||
outformat == "notebook" ? convert_to_notebook(doc) :
|
||||
convert_to_noweb(doc)
|
||||
end
|
||||
|
||||
function convert_to_script(doc)
|
||||
output = ""
|
||||
for chunk in doc.chunks
|
||||
if typeof(chunk) == Weave.DocChunk
|
||||
content = join([repr(c) for c in chunk.content], "")
|
||||
output *= join(["#' " * s for s in split(content, "\n")], "\n")
|
||||
else
|
||||
output *= "\n#+ "
|
||||
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
|
||||
output *= "\n\n" * lstrip(chunk.content)
|
||||
output *= "\n"
|
||||
end
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function convert_to_markdown(doc)
|
||||
output = ""
|
||||
for chunk in doc.chunks
|
||||
if isa(chunk, DocChunk)
|
||||
output *= join([repr(c) for c in chunk.content], "")
|
||||
else
|
||||
output *= "\n" * "```julia"
|
||||
isempty(chunk.optionstring) || (output *= ";" * chunk.optionstring)
|
||||
output *= "\n" * lstrip(chunk.content)
|
||||
output *= "```\n"
|
||||
end
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function convert_to_notebook(doc)
|
||||
nb = Dict()
|
||||
nb["nbformat"] = 4
|
||||
nb["nbformat_minor"] = 2
|
||||
metadata = Dict()
|
||||
kernelspec = Dict()
|
||||
kernelspec["language"] = "julia"
|
||||
kernelspec["name"] = "julia-$(VERSION.major).$(VERSION.minor)"
|
||||
kernelspec["display_name"] = "Julia $(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
|
||||
metadata["kernelspec"] = kernelspec
|
||||
language_info = Dict()
|
||||
language_info["file_extension"] = ".jl"
|
||||
language_info["mimetype"] = "application/julia"
|
||||
language_info["name"] = "julia"
|
||||
language_info["version"] = "$(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
|
||||
metadata["language_info"] = language_info
|
||||
cells = []
|
||||
ex_count = 1
|
||||
|
||||
for chunk in doc.chunks
|
||||
if isa(chunk, DocChunk)
|
||||
push!(
|
||||
cells,
|
||||
Dict(
|
||||
"cell_type" => "markdown",
|
||||
"metadata" => Dict(),
|
||||
"source" => [strip(join([repr(c) for c in chunk.content], ""))],
|
||||
),
|
||||
)
|
||||
else
|
||||
push!(
|
||||
cells,
|
||||
Dict(
|
||||
"cell_type" => "code",
|
||||
"metadata" => Dict(),
|
||||
"source" => [strip(chunk.content)],
|
||||
"execution_count" => nothing,
|
||||
"outputs" => [],
|
||||
),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
nb["cells"] = cells
|
||||
nb["metadata"] = metadata
|
||||
|
||||
json_nb = JSON.json(nb, 2)
|
||||
return json_nb
|
||||
end
|
||||
|
||||
function convert_to_noweb(doc)
|
||||
output = ""
|
||||
for chunk in doc.chunks
|
||||
if isa(chunk, DocChunk)
|
||||
output *= join([repr(c) for c in chunk.content], "")
|
||||
else
|
||||
output *= "\n" * "<<"
|
||||
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
|
||||
output *= ">>="
|
||||
output *= "\n" * lstrip(chunk.content)
|
||||
output *= "@\n"
|
||||
end
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
Base.repr(c::InlineText) = c.content
|
||||
Base.repr(c::InlineCode) = "`j $(c.content)`"
|
|
@ -0,0 +1,133 @@
|
|||
using Markdown, .WeaveMarkdown
|
||||
|
||||
# Contains report global properties
|
||||
mutable struct Report <: AbstractDisplay
|
||||
cwd::String
|
||||
basename::String
|
||||
format::WeaveFormat
|
||||
rich_output::String
|
||||
fignum::Int
|
||||
figures::Vector{String}
|
||||
cur_chunk::Union{Nothing,CodeChunk}
|
||||
mimetypes::Vector{String}
|
||||
first_plot::Bool
|
||||
header_script::String
|
||||
end
|
||||
|
||||
Report(cwd, basename, format, mimetypes) =
|
||||
Report(cwd, basename, format, "", 1, String[], nothing, mimetypes, true, "")
|
||||
|
||||
# Default mimetypes in order, can be overridden for some inside `run method` formats
|
||||
const default_mime_types = ["image/svg+xml", "image/png", "text/html", "text/plain"]
|
||||
# const default_mime_types = ["image/png", "image/svg+xml", "text/html", "text/plain"]
|
||||
# From IJulia as a reminder
|
||||
# const supported_mime_types = [ "text/html", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "text/plain", "text/markdown" ]
|
||||
|
||||
const mimetype_ext = Dict(
|
||||
".png" => "image/png",
|
||||
".jpg" => "image/jpeg",
|
||||
".jpeg" => "image/jpeg",
|
||||
".svg" => "image/svg+xml",
|
||||
".js.svg" => "image/svg+xml",
|
||||
".pdf" => "application/pdf",
|
||||
".ps" => "application/postscript",
|
||||
".tex" => "text/latex",
|
||||
)
|
||||
|
||||
function Base.display(report::Report, data)
|
||||
# Set preferred mimetypes for report based on format
|
||||
fig_ext = report.cur_chunk.options[:fig_ext]
|
||||
for m in unique([mimetype_ext[fig_ext]; report.mimetypes])
|
||||
if Base.invokelatest(showable, m, data)
|
||||
try
|
||||
if !istextmime(m)
|
||||
Base.invokelatest(display, report, m, data)
|
||||
elseif report.cur_chunk.options[:term]
|
||||
Base.invokelatest(display, report, "text/plain", data)
|
||||
else
|
||||
Base.invokelatest(display, report, m, data)
|
||||
end
|
||||
catch e
|
||||
throw(e)
|
||||
@warn("Failed to display data in \"$m\" format")
|
||||
continue
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Base.display(report::Report, m::MIME"image/png", data) = add_figure(report, data, m, ".png")
|
||||
|
||||
Base.display(report::Report, m::MIME"image/svg+xml", data) = add_figure(report, data, m, ".svg")
|
||||
|
||||
Base.display(report::Report, m::MIME"application/pdf", data) = add_figure(report, data, m, ".pdf")
|
||||
|
||||
# Text is written to stdout, called from "term" mode chunks
|
||||
function Base.display(report::Report, m::MIME"text/plain", data)
|
||||
io = PipeBuffer()
|
||||
show(IOContext(io, :limit => true), m, data)
|
||||
flush(io)
|
||||
s = read(io, String)
|
||||
close(io)
|
||||
println(s)
|
||||
end
|
||||
|
||||
function Base.display(report::Report, m::MIME"text/plain", data::Exception)
|
||||
println("Error: " * sprint(showerror, data))
|
||||
end
|
||||
|
||||
function Base.display(report::Report, m::MIME"text/html", data::Exception)
|
||||
report.rich_output = sprint(show, m, data)
|
||||
end
|
||||
|
||||
function Base.show(io, m::MIME"text/html", data::Exception)
|
||||
println(io, "<pre class=\"julia-error\">")
|
||||
println(io, Markdown.htmlesc("ERROR: " * sprint(showerror, data)))
|
||||
println(io, "</pre>")
|
||||
end
|
||||
|
||||
# Catch "rich_output"
|
||||
function Base.display(report::Report, m::MIME"text/html", data)
|
||||
io = IOBuffer()
|
||||
show(IOContext(io, :limit => true), m, data)
|
||||
report.rich_output *= string('\n', take2string!(io))
|
||||
end
|
||||
|
||||
# Catch "rich_output"
|
||||
function Base.display(report::Report, m::MIME"text/markdown", data)
|
||||
s = repr(m, data)
|
||||
# Convert to "richer" type of possible
|
||||
for m in report.mimetypes
|
||||
if m == "text/html" || m == "text/latex"
|
||||
display(Markdown.parse(s, flavor = WeaveMarkdown.weavemd))
|
||||
break
|
||||
elseif m == "text/markdown"
|
||||
report.rich_output *= "\n" * s
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Base.display(report::Report, m::MIME"text/latex", data)
|
||||
s = repr(m, data)
|
||||
report.rich_output *= string('\n', s)
|
||||
end
|
||||
|
||||
"""Add saved figure name to results and return the name"""
|
||||
function add_figure(report::Report, data, m, ext)
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = get_figname(report, chunk, ext = ext)
|
||||
|
||||
open(full_name, "w") do io
|
||||
if ext == ".pdf"
|
||||
write(io, repr(m, data))
|
||||
else
|
||||
show(io, m, data)
|
||||
end
|
||||
end
|
||||
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
return full_name
|
||||
end
|
|
@ -1,335 +0,0 @@
|
|||
using TextWrap
|
||||
|
||||
#Format the executed document
|
||||
function format(executed, doctype)
|
||||
formatted = String[]
|
||||
docformat = formats[doctype]
|
||||
#@show docformat
|
||||
|
||||
#Complete format dictionaries with defaults
|
||||
formatdict = docformat.formatdict
|
||||
get!(formatdict, :termstart, formatdict[:codestart])
|
||||
get!(formatdict, :termend, formatdict[:codeend])
|
||||
get!(formatdict, :out_width, nothing)
|
||||
get!(formatdict, :out_height, nothing)
|
||||
get!(formatdict, :fig_pos, nothing)
|
||||
get!(formatdict, :fig_env, nothing)
|
||||
|
||||
|
||||
for chunk in copy(executed)
|
||||
|
||||
if chunk[:type] == "doc"
|
||||
push!(formatted, chunk[:content])
|
||||
else
|
||||
#Fill undefined options with format specific defaults
|
||||
chunk[:out_width] == nothing && (chunk[:out_width] = docformat.formatdict[:out_width])
|
||||
chunk[:fig_pos] == nothing && (chunk[:fig_pos] = docformat.formatdict[:fig_pos])
|
||||
|
||||
#Only use floats if chunk has caption or sets fig_env
|
||||
if chunk[:fig_cap] != nothing && chunk[:fig_env] == nothing
|
||||
(chunk[:fig_env] = docformat.formatdict[:fig_env])
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
#Format code
|
||||
result = format_codechunk(chunk, formatdict)
|
||||
#Handle figures
|
||||
if chunk[:fig] && length(chunk[:figure]) > 0
|
||||
if chunk[:include]
|
||||
result *= formatfigures(chunk, docformat)
|
||||
end
|
||||
end
|
||||
push!(formatted, result)
|
||||
end
|
||||
end
|
||||
|
||||
return formatted
|
||||
end
|
||||
|
||||
|
||||
function format_codechunk(chunk, formatdict)
|
||||
if haskey(formatdict, :indent)
|
||||
chunk[:content] = indent(chunk[:content], formatdict[:indent])
|
||||
end
|
||||
|
||||
if !chunk[:eval]
|
||||
if chunk[:echo]
|
||||
result = "$(formatdict[:codestart])$(chunk[:content])\n$(formatdict[:codeend])"
|
||||
return result
|
||||
else
|
||||
r = ""
|
||||
return r
|
||||
end
|
||||
end
|
||||
|
||||
if chunk[:term]
|
||||
result = format_termchunk(chunk, formatdict)
|
||||
else
|
||||
if chunk[:wrap]
|
||||
chunk[:result] = "\n" * wrap(chunk[:result], replace_whitespace=false)
|
||||
end
|
||||
|
||||
if chunk[:echo]
|
||||
result = "$(formatdict[:codestart])$(chunk[:content])\n$(formatdict[:codeend])\n"
|
||||
else
|
||||
result = ""
|
||||
end
|
||||
|
||||
if (strip(chunk[:result])!= "") && (chunk[:results] != "hidden")
|
||||
#@show chunk
|
||||
if chunk[:results] != "markup"
|
||||
result *= "$(chunk[:result])"
|
||||
elseif chunk[:results] == "markup"
|
||||
if haskey(formatdict, :indent)
|
||||
chunk[:result] = indent(chunk[:result], formatdict[:indent])
|
||||
end
|
||||
result *= "$(formatdict[:outputstart])$(chunk[:result])\n$(formatdict[:outputend])\n"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return result
|
||||
|
||||
end
|
||||
|
||||
function format_termchunk(chunk, formatdict)
|
||||
if chunk[:echo] && chunk[:results] != "hidden"
|
||||
result = "$(formatdict[:termstart])$(chunk[:result])\n"
|
||||
#@show chunk[:term_state]
|
||||
chunk[:term_state] == :text && (result*= "$(formatdict[:termend])\n")
|
||||
else
|
||||
result = ""
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function indent(text, nindent)
|
||||
return join(map(x->
|
||||
string(repeat(" ", nindent), x), split(text, "\n")), "\n")
|
||||
end
|
||||
|
||||
|
||||
type Tex
|
||||
description::String
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const tex = Tex("Latex with custom code environments",
|
||||
@compat Dict{Symbol,Any}(:codestart => "\\begin{juliacode}",
|
||||
:codeend => "\\end{juliacode}",
|
||||
:outputstart => "\\begin{juliaout}",
|
||||
:outputend => "\\end{juliaout}",
|
||||
:termstart => "\\begin{juliaterm}",
|
||||
:termend => "\\end{juliaterm}",
|
||||
:fig_ext => ".pdf",
|
||||
:extension =>"tex",
|
||||
:out_width=> "\\linewidth",
|
||||
:fig_env=> "figure",
|
||||
:fig_pos => "htpb",
|
||||
:doctype => "tex"
|
||||
))
|
||||
|
||||
const texminted = Tex("Latex using minted for highlighting",
|
||||
@compat Dict{Symbol,Any}(
|
||||
:codestart => "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}",
|
||||
:codeend => "\\end{minted}",
|
||||
:outputstart => "\\begin{minted}[fontsize=\\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}",
|
||||
:outputend => "\\end{minted}",
|
||||
:termstart=> "\\begin{minted}[fontsize=\\footnotesize, xleftmargin=0.5em, mathescape]{julia}",
|
||||
:termend => "\\end{minted}",
|
||||
:fig_ext => ".pdf",
|
||||
:extension =>"tex",
|
||||
:out_width => "\\linewidth",
|
||||
:fig_env=> "figure",
|
||||
:fig_pos => "htpb",
|
||||
:doctype => "texminted"
|
||||
))
|
||||
|
||||
type Markdown
|
||||
description::String
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const pandoc = Markdown("Pandoc markdown",
|
||||
@compat Dict{Symbol,Any}(
|
||||
:codestart => "~~~~{.julia}",
|
||||
:codeend=>"~~~~~~~~~~~~~\n\n",
|
||||
:outputstart=>"~~~~{.julia}",
|
||||
:outputend=>"~~~~~~~~~~~~~\n\n",
|
||||
:fig_ext=>".png",
|
||||
:extension=>"md",
|
||||
:doctype=>"pandoc"
|
||||
))
|
||||
|
||||
|
||||
const github = Markdown("Github markdown",
|
||||
@compat Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend=> "````\n\n",
|
||||
:outputstart=> "````julia",
|
||||
:outputend=> "````\n\n",
|
||||
:fig_ext=> ".png",
|
||||
:extension=> "md",
|
||||
:doctype=> "github"
|
||||
))
|
||||
|
||||
|
||||
type Rest
|
||||
description::String
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const rst = Rest("reStructuredText and Sphinx",
|
||||
@compat Dict{Symbol,Any}(
|
||||
:codestart => ".. code-block:: julia\n",
|
||||
:codeend => "\n\n",
|
||||
:outputstart => "::\n",
|
||||
:outputend => "\n\n",
|
||||
:indent=> 4,
|
||||
:fig_ext => ".png",
|
||||
:extension => "rst",
|
||||
:out_width => "15 cm",
|
||||
:doctype => "rst"
|
||||
))
|
||||
|
||||
type AsciiDoc
|
||||
description::String
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
#asciidoc -b html5 -a source-highlighter=pygments ...
|
||||
const adoc = AsciiDoc("AsciiDoc",
|
||||
@compat Dict{Symbol,Any}(
|
||||
:codestart => "[source,julia]\n--------------------------------------",
|
||||
:codeend => "--------------------------------------\n\n",
|
||||
:outputstart => "--------------------------------------",
|
||||
:outputend => "--------------------------------------\n\n",
|
||||
:fig_ext => ".png",
|
||||
:extension => "txt",
|
||||
:out_width => "600",
|
||||
:doctype => "asciidoc"
|
||||
))
|
||||
|
||||
|
||||
function formatfigures(chunk, docformat::Tex)
|
||||
fignames = chunk[:figure]
|
||||
caption = chunk[:fig_cap]
|
||||
width = chunk[:out_width]
|
||||
f_pos = chunk[:fig_pos]
|
||||
f_env = chunk[:fig_env]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
|
||||
|
||||
if f_env != nothing
|
||||
result *= """\\begin{$f_env}[$f_pos]\n"""
|
||||
end
|
||||
|
||||
|
||||
for fig = fignames
|
||||
figstring *= "\\includegraphics[width=$width]{$fig}\n"
|
||||
end
|
||||
|
||||
# Figure environment
|
||||
if caption != nothing
|
||||
result *= string("\\center\n",
|
||||
"$figstring",
|
||||
"\\caption{$caption}\n")
|
||||
else
|
||||
result *= figstring
|
||||
end
|
||||
|
||||
if chunk[:name] != nothing && f_env !=nothing
|
||||
label = chunk[:name]
|
||||
result *= "\\label{fig:$label}\n"
|
||||
end
|
||||
|
||||
|
||||
if f_env != nothing
|
||||
result *= "\\end{$f_env}\n"
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function formatfigures(chunk, docformat::Markdown)
|
||||
fignames = chunk[:figure]
|
||||
caption = chunk[:fig_cap]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
length(fignames) > 0 || (return "")
|
||||
|
||||
if caption != nothing
|
||||
result *= "![$caption]($(fignames[1]))\n"
|
||||
for fig = fignames[2:end]
|
||||
result *= "![]($fig)\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
end
|
||||
else
|
||||
for fig in fignames
|
||||
result *= "![]($fig)\n"
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
function formatfigures(chunk, docformat::Rest)
|
||||
fignames = chunk[:figure]
|
||||
caption = chunk[:fig_cap]
|
||||
width = chunk[:out_width]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
for fig=fignames
|
||||
figstring *= @sprintf(".. image:: %s\n :width: %s\n\n", fig, width)
|
||||
end
|
||||
|
||||
if caption != nothing
|
||||
result *= string(".. figure:: $(fignames[1])\n",
|
||||
" :width: $width\n\n",
|
||||
" $caption\n\n")
|
||||
else
|
||||
result *= figstring
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function formatfigures(chunk, docformat::AsciiDoc)
|
||||
fignames = chunk[:figure]
|
||||
caption = chunk[:fig_cap]
|
||||
width = chunk[:out_width]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
|
||||
for fig=fignames
|
||||
figstring *= @sprintf("image::%s[width=%s]\n", fig, width)
|
||||
end
|
||||
|
||||
|
||||
if caption != nothing
|
||||
result *= string("image::$(fignames[1])",
|
||||
"[width=$width,",
|
||||
"title=\"$caption\"]")
|
||||
else
|
||||
result *= figstring
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#Add new supported formats here
|
||||
const formats = @compat Dict{String, Any}("tex" => tex,
|
||||
"texminted" => texminted,
|
||||
"pandoc" => pandoc,
|
||||
"github" => github,
|
||||
"rst" => rst,
|
||||
"asciidoc" => adoc
|
||||
)
|
|
@ -1,54 +1,51 @@
|
|||
using Gadfly
|
||||
module GadflyPlots
|
||||
|
||||
Gadfly.set_default_plot_format(:png)
|
||||
using ..Weave, ..Gadfly
|
||||
|
||||
#Captures figures
|
||||
function Base.display(report::Report, m::MIME"image/png", p::Plot)
|
||||
|
||||
Gadfly.set_default_plot_format(:svg)
|
||||
|
||||
Base.showable(m::MIME"application/pdf", p::Gadfly.Plot) = true
|
||||
Base.showable(m::MIME"application/png", p::Gadfly.Plot) = true
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"application/pdf", p::Gadfly.Plot)
|
||||
display(report, MIME("image/svg+xml"), p)
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"image/png", p::Gadfly.Plot)
|
||||
display(report, MIME("image/svg+xml"), p)
|
||||
end
|
||||
|
||||
# Gadfly doesn't call the default display methods, this catches
|
||||
# all Gadfly plots
|
||||
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", p::Gadfly.Plot)
|
||||
chunk = report.cur_chunk
|
||||
|
||||
full_name, rel_name = get_figname(report, chunk)
|
||||
w = chunk.options[:fig_width] * Gadfly.inch
|
||||
h = chunk.options[:fig_height] * Gadfly.inch
|
||||
format = chunk.options[:fig_ext]
|
||||
dpi = chunk.options[:dpi]
|
||||
|
||||
docformat = formats[report.formatdict[:doctype]]
|
||||
|
||||
#Add to results for term chunks and store otherwise
|
||||
if chunk[:term]
|
||||
chunk[:figure] = [rel_name]
|
||||
|
||||
if report.term_state == :text
|
||||
report.cur_result *= "\n" * report.formatdict[:codeend] * "\n"
|
||||
end
|
||||
|
||||
|
||||
report.cur_result *= formatfigures(chunk, docformat)
|
||||
report.term_state = :fig
|
||||
chunk[:figure] = String[]
|
||||
else
|
||||
push!(report.figures, rel_name)
|
||||
end
|
||||
full_name, rel_name = Weave.get_figname(report, chunk, ext = format)
|
||||
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
|
||||
w = chunk[:fig_width]inch
|
||||
h = chunk[:fig_height]inch
|
||||
format = chunk[:fig_ext]
|
||||
dpi = chunk[:dpi]
|
||||
|
||||
#This is probably not the correct way to handle different formats, but it works.
|
||||
if format == ".png"
|
||||
try
|
||||
draw(PNG(full_name, w, h, dpi=dpi), p)
|
||||
catch
|
||||
draw(PNG(full_name, w, h), p) #Compose < 0.3.1, Gadfly < 0.3.1
|
||||
end
|
||||
elseif format == ".pdf"
|
||||
draw(PDF(full_name, w, h), p)
|
||||
elseif format == ".ps"
|
||||
draw(PS(full_name, w, h), p)
|
||||
elseif format == ".svg"
|
||||
draw(SVG(full_name, w, h), p)
|
||||
if format == ".svg"
|
||||
Gadfly.draw(Gadfly.SVG(full_name, w, h), p)
|
||||
elseif format == ".js.svg"
|
||||
draw(SVGJS(full_name, w, h), p)
|
||||
else:
|
||||
warn("Can't save figure. Unsupported format")
|
||||
Gadfly.draw(Gadfly.SVGJS(full_name, w, h), p)
|
||||
elseif format == ".png"
|
||||
Gadfly.draw(Gadfly.PNG(full_name, w, h, dpi = dpi), p)
|
||||
elseif format == ".pdf"
|
||||
Gadfly.draw(Gadfly.PDF(full_name, w, h), p)
|
||||
elseif format == ".ps"
|
||||
Gadfly.draw(Gadfly.PS(full_name, w, h), p)
|
||||
elseif format == ".tex"
|
||||
Gadfly.draw(Gadfly.PGF(full_name, w, h, true), p)
|
||||
else
|
||||
@warn("Can't save figure. Unsupported format, $format")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
module WeavePlots
|
||||
|
||||
using ..Base64, ..Plots, ..Weave
|
||||
|
||||
|
||||
# Pre-execute hooks to set the plot size for the chunk
|
||||
function plots_set_size!(chunk)
|
||||
w = chunk.options[:fig_width] * chunk.options[:dpi]
|
||||
h = chunk.options[:fig_height] * chunk.options[:dpi]
|
||||
Plots.default(size = (w, h))
|
||||
end
|
||||
|
||||
Weave.push_preexecution_hook!(plots_set_size!)
|
||||
|
||||
# PNG or SVG is not working, output html
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/svg+xml",
|
||||
data::Plots.Plot{Plots.PlotlyBackend},
|
||||
)
|
||||
# Remove extra spaces from start of line for pandoc
|
||||
s = repr(MIME("text/html"), data)
|
||||
splitted = split(s, "\n")
|
||||
start = split(splitted[1], r"(?=<div)")
|
||||
# script = lstrip(start[1]) # local
|
||||
|
||||
div = lstrip(start[2])
|
||||
plot = join(map(lstrip, splitted[2:end]), "\n")
|
||||
|
||||
if report.first_plot
|
||||
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
|
||||
report.first_plot = false
|
||||
end
|
||||
|
||||
report.rich_output *= "\n" * div * "\n" * plot
|
||||
end
|
||||
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/png",
|
||||
data::Plots.Plot{Plots.PlotlyBackend},
|
||||
)
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
end
|
||||
|
||||
# PNG or SVG is not working, output html
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/svg+xml",
|
||||
plot::Plots.Plot{Plots.PlotlyJSBackend},
|
||||
)
|
||||
body = Plots.PlotlyJS.html_body(plot.o.plot)
|
||||
|
||||
if report.first_plot
|
||||
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
|
||||
report.first_plot = false
|
||||
end
|
||||
|
||||
report.rich_output *= "\n" * body
|
||||
end
|
||||
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/png",
|
||||
plot::Plots.Plot{Plots.PlotlyJSBackend},
|
||||
)
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
end
|
||||
|
||||
"""Add saved figure name to results and return the name"""
|
||||
function add_plots_figure(report::Weave.Report, plot::Plots.Plot, ext)
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = Weave.get_figname(report, chunk, ext = ext)
|
||||
|
||||
Plots.savefig(plot, full_name)
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
return full_name
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"application/pdf", plot::Plots.Plot)
|
||||
add_plots_figure(report, plot, ".pdf")
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"image/png", plot::Plots.Plot)
|
||||
add_plots_figure(report, plot, ".png")
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", plot::Plots.Plot)
|
||||
add_plots_figure(report, plot, ".svg")
|
||||
end
|
||||
|
||||
# write out html to view Animated gif
|
||||
function Base.display(report::Weave.Report, ::MIME"text/html", agif::Plots.AnimatedGif)
|
||||
ext = agif.filename[end-2:end]
|
||||
res = ""
|
||||
if ext == "gif"
|
||||
img = stringmime(MIME("image/gif"), read(agif.filename))
|
||||
res = "<img src=\"data:image/gif;base64,$img\" />"
|
||||
elseif ext in ("mov", "mp4")
|
||||
# Uncomment to embed mp4, make global or chunk option?
|
||||
# img = stringmime(MIME("video/$ext"), read(agif.filename))
|
||||
# res = "<video controls><source src=\"data:video/$(ext);base64,$img\" type=\"video/$ext\"></video>"
|
||||
res = "<video controls><source src=\"$(relpath(agif.filename))\" type=\"video/$ext\"></video>"
|
||||
else
|
||||
error("Cannot show animation with extension $ext: $agif")
|
||||
end
|
||||
|
||||
report.rich_output *= "\n" * res * "\n"
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,95 @@
|
|||
function parse_markdown(document_body; is_pandoc = false)
|
||||
header_text, document_body, offset = separate_header_text(document_body)
|
||||
header = parse_header(header_text)
|
||||
code_start, code_end = if is_pandoc
|
||||
r"^<<(?<options>.*?)>>=\s*$",
|
||||
r"^@\s*$"
|
||||
else
|
||||
r"^[`~]{3}(\{?)julia\s*([;,\{]?)\s*(?<options>.*?)(\}|\s*)$",
|
||||
r"^[`~]{3}\s*$"
|
||||
end
|
||||
return header, parse_markdown_body(document_body, code_start, code_end, offset)
|
||||
end
|
||||
|
||||
# headers
|
||||
# -------
|
||||
|
||||
const HEADER_REGEX = r"^---$(?<header>((?!---).)+)^---$"ms
|
||||
|
||||
# TODO: non-Weave headers should keep live in a doc
|
||||
# separates header section from `text`
|
||||
function separate_header_text(text)
|
||||
m = match(HEADER_REGEX, text)
|
||||
isnothing(m) && return "", text, 0
|
||||
header_text = m[:header]
|
||||
offset = @static if VERSION ≥ v"1.4"
|
||||
count("\n", header_text)
|
||||
else
|
||||
count(c->c==='\n', header_text)
|
||||
end
|
||||
return header_text, replace(text, HEADER_REGEX => ""; count = 1), offset
|
||||
end
|
||||
|
||||
# HACK:
|
||||
# YAML.jl can't parse text including ``` characters, so first replace all the inline code
|
||||
# with these temporary code start/end string
|
||||
const HEADER_INLINE_START = "<weave_header_inline_start>"
|
||||
const HEADER_INLINE_END = "<weave_header_inline_end>"
|
||||
|
||||
function parse_header(header_text)
|
||||
isempty(header_text) && return Dict()
|
||||
pat = INLINE_REGEX => SubstitutionString("$(HEADER_INLINE_START)\\1$(HEADER_INLINE_END)")
|
||||
header_text = replace(header_text, pat)
|
||||
return YAML.load(header_text)
|
||||
end
|
||||
|
||||
# body
|
||||
# ----
|
||||
|
||||
function parse_markdown_body(document_body, code_start, code_end, offset)
|
||||
lines = split(document_body, '\n')
|
||||
|
||||
state = :doc
|
||||
doc_no = 0
|
||||
code_no = 0
|
||||
content = ""
|
||||
start_line = offset
|
||||
|
||||
options = OptionDict()
|
||||
option_string = ""
|
||||
|
||||
chunks = WeaveChunk[]
|
||||
for (line_no, line) in enumerate(lines)
|
||||
m = match(code_start, line)
|
||||
if !isnothing(m) && state === :doc
|
||||
state = :code
|
||||
|
||||
option_string = isnothing(m[:options]) ? "" : strip(m[:options])
|
||||
options = parse_options(option_string)
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
|
||||
isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
|
||||
|
||||
start_line = line_no + offset
|
||||
content = ""
|
||||
continue
|
||||
end
|
||||
|
||||
if occursin(code_end, line) && state === :code
|
||||
push!(chunks, CodeChunk(content, code_no += 1, start_line, option_string, options))
|
||||
|
||||
start_line = line_no + offset
|
||||
content = ""
|
||||
state = :doc
|
||||
continue
|
||||
end
|
||||
|
||||
content *= isone(line_no) ? line : string('\n', line)
|
||||
end
|
||||
|
||||
# Remember the last chunk
|
||||
isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
|
||||
|
||||
return chunks
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
using JSON
|
||||
|
||||
|
||||
function parse_notebook(document_body)
|
||||
nb = JSON.parse(document_body)
|
||||
code_no = 0
|
||||
doc_no = 0
|
||||
|
||||
# TODO: handle some of options ?
|
||||
options = Dict{Symbol,Any}()
|
||||
opt_string = ""
|
||||
|
||||
chunks = map(nb["cells"]) do cell
|
||||
text = string('\n', join(cell["source"]), '\n')
|
||||
return if cell["cell_type"] == "code"
|
||||
CodeChunk(text, code_no += 1, 0, opt_string, options)
|
||||
else
|
||||
DocChunk(text, doc_no += 1, 0; notebook = true)
|
||||
end
|
||||
end
|
||||
|
||||
return Dict(), chunks
|
||||
end
|
|
@ -0,0 +1,128 @@
|
|||
using YAML
|
||||
|
||||
|
||||
function WeaveDoc(source, informat = nothing)
|
||||
path = abspath(source)
|
||||
_, fname = splitdir(path)
|
||||
basename = splitext(fname)[1]
|
||||
|
||||
isnothing(informat) && (informat = detect_informat(source))
|
||||
header, chunks = parse_doc(read(source, String), informat)
|
||||
|
||||
# update default chunk options from header
|
||||
chunk_defaults = deepcopy(get_chunk_defaults())
|
||||
if (weave_options = get(header, WEAVE_OPTION_NAME, nothing)) !== nothing
|
||||
for key in keys(chunk_defaults)
|
||||
if (val = get(weave_options, string(key), nothing)) !== nothing
|
||||
chunk_defaults[key] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
if haskey(header, WEAVE_OPTION_NAME_DEPRECATED)
|
||||
@warn "Weave: `options` key is deprecated. Use `weave_options` key instead." _id = WEAVE_OPTION_DEPRECATE_ID maxlog = 1
|
||||
for key in keys(chunk_defaults)
|
||||
if (val = get(header[WEAVE_OPTION_NAME_DEPRECATED], string(key), nothing)) !== nothing
|
||||
chunk_defaults[key] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return WeaveDoc(
|
||||
source,
|
||||
basename,
|
||||
path,
|
||||
chunks,
|
||||
"",
|
||||
nothing,
|
||||
"",
|
||||
"",
|
||||
header,
|
||||
chunk_defaults,
|
||||
)
|
||||
end
|
||||
|
||||
"""
|
||||
detect_informat(path)
|
||||
|
||||
Detect Weave input format based on file extension of `path`.
|
||||
"""
|
||||
function detect_informat(path)
|
||||
ext = lowercase(last(splitext(path)))
|
||||
|
||||
ext == ".jl" && return "script"
|
||||
ext == ".jmd" && return "markdown"
|
||||
ext == ".ipynb" && return "notebook"
|
||||
return "noweb"
|
||||
end
|
||||
|
||||
function parse_doc(document, informat)
|
||||
document = replace(document, "\r\n" => "\n") # normalize line ending
|
||||
|
||||
return informat == "markdown" ? parse_markdown(document) :
|
||||
informat == "noweb" ? parse_markdown(document; is_pandoc = true) :
|
||||
informat == "script" ? parse_script(document) :
|
||||
informat == "notebook" ? parse_notebook(document) :
|
||||
error("unsupported input format given: $informat")
|
||||
end
|
||||
|
||||
# inline
|
||||
# ------
|
||||
|
||||
function DocChunk(text::AbstractString, number, start_line; notebook = false)
|
||||
# don't parse inline code in notebook
|
||||
content = notebook ? parse_inline(text) : parse_inlines(text)
|
||||
return DocChunk(content, number, start_line)
|
||||
end
|
||||
|
||||
const INLINE_REGEX = r"`j\s+(.*?)`"
|
||||
const INLINE_REGEXES = r"`j\s+(.*?)`|^!\s(.*)$"m
|
||||
|
||||
# handle code units correctly !
|
||||
function parse_inlines(str)
|
||||
ret = Inline[]
|
||||
s = 1
|
||||
code_no = text_no = 0
|
||||
for m in eachmatch(INLINE_REGEXES, str)
|
||||
e = m.offset
|
||||
push!(ret, InlineText((str[s:prevind(str,e)]), text_no += 1))
|
||||
i = findfirst(!isnothing, m.captures)
|
||||
push!(ret, InlineCode(m.captures[i], code_no += 1, isone(i) ? :inline : :line))
|
||||
s = e + ncodeunits(m.match)
|
||||
end
|
||||
push!(ret, InlineText(str[s:end], text_no += 1))
|
||||
return ret
|
||||
end
|
||||
|
||||
parse_inline(str) = Inline[InlineText(str, 1)]
|
||||
|
||||
# options
|
||||
# -------
|
||||
|
||||
const OptionDict = Dict{Symbol,Any}
|
||||
|
||||
function parse_options(str)::OptionDict
|
||||
str = string('(', str, ')')
|
||||
ex = Meta.parse(str)
|
||||
nt = if Meta.isexpr(ex, (
|
||||
:block, # "(k1 = v1; k2 = v2, ...)"
|
||||
:tuple, # "(k1 = v1, k2 = v2, ...)"
|
||||
))
|
||||
eval(Expr(:tuple, filter(is_valid_kv, ex.args)...))
|
||||
elseif is_valid_kv(ex) # "(k = v)"
|
||||
eval(Expr(:tuple, ex))
|
||||
else
|
||||
NamedTuple{}()
|
||||
end
|
||||
return dict(nt)
|
||||
end
|
||||
|
||||
is_valid_kv(x) = Meta.isexpr(x, :(=))
|
||||
dict(nt) = Dict((k => v for (k,v) in zip(keys(nt), values(nt)))...)
|
||||
nt(dict) = NamedTuple{(Symbol.(keys(dict))...,)}((collect(values(dict))...,))
|
||||
|
||||
# each input format
|
||||
# -----------------
|
||||
|
||||
include("markdown.jl")
|
||||
include("script.jl")
|
||||
include("notebook.jl")
|
|
@ -0,0 +1,67 @@
|
|||
function parse_script(document_body)
|
||||
lines = split(document_body, '\n')
|
||||
|
||||
doc_line = r"(^#'.*)|(^#%%.*)|(^# %%.*)"
|
||||
doc_start = r"(^#')|(^#%%)|(^# %%)"
|
||||
opt_line = r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)"
|
||||
opt_start = r"(^#\+)|(^#%%\+)|(^# %%\+)"
|
||||
|
||||
content = ""
|
||||
state = :code
|
||||
doc_no = 0
|
||||
code_no = 0
|
||||
start_line = 1
|
||||
|
||||
options = OptionDict()
|
||||
option_string = ""
|
||||
|
||||
chunks = WeaveChunk[]
|
||||
for (line_no, line) in enumerate(lines)
|
||||
if (m = match(doc_line, line)) !== nothing && (m = match(opt_line, line)) === nothing
|
||||
line = replace(line, doc_start => "", count = 1)
|
||||
startswith(line, ' ') && (line = replace(line, ' ' => "", count = 1))
|
||||
if state === :code && !isempty(strip(content))
|
||||
push!(chunks, CodeChunk(string('\n', strip(content)), code_no += 1, start_line, option_string, options))
|
||||
content = ""
|
||||
start_line = line_no
|
||||
end
|
||||
state = :doc
|
||||
elseif (m = match(opt_line, line)) !== nothing
|
||||
start_line = line_no
|
||||
if state === :code && !isempty(strip(content))
|
||||
push!(chunks, CodeChunk(string('\n', strip(content)), code_no += 1, start_line, option_string, options))
|
||||
content = ""
|
||||
end
|
||||
if state === :doc && !isempty(strip(content))
|
||||
iszero(doc_no) || (content = string('\n', content)) # Add whitespace to doc chunk. Needed for markdown output
|
||||
push!(chunks, DocChunk(content, doc_no += 1, start_line))
|
||||
content = ""
|
||||
end
|
||||
|
||||
option_string = replace(line, opt_start => "", count = 1)
|
||||
options = parse_options(option_string)
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
|
||||
state = :code
|
||||
continue
|
||||
elseif state === :doc # && strip(line) != "" && strip(content) != ""
|
||||
state = :code
|
||||
iszero(doc_no) || (content = string('\n', content)) # Add whitespace to doc chunk. Needed for markdown output
|
||||
push!(chunks, DocChunk(content, doc_no += 1, start_line))
|
||||
content = ""
|
||||
|
||||
options = Dict{Symbol,Any}()
|
||||
start_line = line_no
|
||||
end
|
||||
content *= string(line, '\n')
|
||||
end
|
||||
|
||||
# Handle the last chunk
|
||||
chunk = state === :code ?
|
||||
CodeChunk(string('\n', strip(content)), code_no, start_line, option_string, options) :
|
||||
DocChunk(content, doc_no, start_line)
|
||||
push!(chunks, chunk)
|
||||
|
||||
return Dict(), chunks
|
||||
end
|
|
@ -1,84 +0,0 @@
|
|||
pushopt(options::Dict,expr::Expr) = Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
|
||||
|
||||
const input_formats = @compat Dict{String, Any}(
|
||||
"noweb" => Dict{Symbol, Any}(
|
||||
:codestart => r"^<<(.*?)>>=\s*$",
|
||||
:codeend => r"^@\s*$"
|
||||
),
|
||||
"markdown" => Dict{Symbol, Any}(
|
||||
:codestart => r"(?:^(?:`|~){3,}\s*(?:\{|\{\.|)julia(?:;|\s)(.*)\}\s*$)|(?:^(?:`|~){3,}\s*julia\s*$)",
|
||||
:codeend => r"^`|~{3,}\s*$"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
function read_document(document, format)
|
||||
#doctext = readall(open(document))
|
||||
lines = split(bytestring(open(document) do io
|
||||
mmap_array(Uint8,(filesize(document),),io)
|
||||
end), "\n")
|
||||
|
||||
codestart = input_formats[format][:codestart]
|
||||
codeend = input_formats[format][:codeend]
|
||||
state = "doc"
|
||||
|
||||
docno = 1
|
||||
codeno = 1
|
||||
content = ""
|
||||
start_line = 0
|
||||
|
||||
options = Dict()
|
||||
optionstring = ""
|
||||
parsed = Dict[]
|
||||
for lineno in 1:length(lines)
|
||||
line = lines[lineno]
|
||||
if (m = match(codestart, line)) != nothing && state=="doc"
|
||||
state = "code"
|
||||
if m.captures[1] == nothing
|
||||
optionstring = ""
|
||||
else
|
||||
optionstring=strip(m.captures[1])
|
||||
end
|
||||
#@show optionstring
|
||||
options = Dict{Symbol,Any}()
|
||||
if length(optionstring) > 0
|
||||
expr = parse(optionstring)
|
||||
Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
Base.Meta.isexpr(expr,:toplevel) && map(pushopt,fill(options,length(expr.args)),expr.args)
|
||||
end
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
#@show options
|
||||
chunk = @compat Dict{Symbol,Any}(:type => "doc", :content => content,
|
||||
:number => docno,:start_line => start_line)
|
||||
docno += 1
|
||||
start_line = lineno
|
||||
push!(parsed, chunk)
|
||||
content = ""
|
||||
continue
|
||||
end
|
||||
if ismatch(codeend, line) && state=="code"
|
||||
chunk = @compat Dict{Symbol,Any}(:type => "code", :content => content,
|
||||
:number => codeno, :options => options,
|
||||
:optionstring => optionstring,
|
||||
:start_line => start_line)
|
||||
codeno+=1
|
||||
start_line = lineno
|
||||
content = ""
|
||||
state = "doc"
|
||||
push!(parsed, chunk)
|
||||
continue
|
||||
end
|
||||
|
||||
content *= "\n" * line
|
||||
end
|
||||
|
||||
#Remember the last chunk
|
||||
if content != ""
|
||||
chunk = @compat Dict{Symbol,Any}(:type => "doc", :content => content,
|
||||
:number => docno, :start_line => start_line)
|
||||
push!(parsed, chunk)
|
||||
end
|
||||
return parsed
|
||||
end
|
|
@ -0,0 +1,162 @@
|
|||
# fallback methods
|
||||
# ----------------
|
||||
|
||||
set_format_options!(docformat::WeaveFormat; _kwargs...) = return
|
||||
|
||||
function restore_header!(doc)
|
||||
(hasproperty(doc.format, :preserve_header) && doc.format.preserve_header) || return
|
||||
|
||||
# only strips Weave headers
|
||||
delete!(doc.header, WEAVE_OPTION_NAME)
|
||||
if haskey(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
|
||||
@warn "Weave: `options` key is deprecated. Use `weave_options` key instead." _id = WEAVE_OPTION_DEPRECATE_ID maxlog = 1
|
||||
delete!(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
|
||||
end
|
||||
isempty(doc.header) && return
|
||||
|
||||
# restore remained headers as `DocChunk`
|
||||
header_text = "---\n$(YAML.write(doc.header))---"
|
||||
pushfirst!(doc.chunks, DocChunk(header_text, 0, 0))
|
||||
end
|
||||
|
||||
render_chunk(docformat::WeaveFormat, chunk::DocChunk) = join((render_inline(c) for c in chunk.content))
|
||||
|
||||
render_inline(inline::InlineText) = inline.content
|
||||
|
||||
function render_inline(inline::InlineCode)
|
||||
isempty(inline.rich_output) || return inline.rich_output
|
||||
isempty(inline.figures) || return inline.figures[end]
|
||||
return inline.output
|
||||
end
|
||||
|
||||
function render_chunk(docformat::WeaveFormat, chunk::CodeChunk)
|
||||
|
||||
# Fill undefined options with format specific defaults
|
||||
isnothing(chunk.options[:out_width]) && (chunk.options[:out_width] = docformat.out_width)
|
||||
isnothing(chunk.options[:fig_pos]) && (chunk.options[:fig_pos] = docformat.fig_pos)
|
||||
|
||||
# Only use floats if chunk has caption or sets fig_env
|
||||
if !isnothing(chunk.options[:fig_cap]) && isnothing(chunk.options[:fig_env])
|
||||
(chunk.options[:fig_env] = docformat.fig_env)
|
||||
end
|
||||
|
||||
hasproperty(docformat, :indent) && (chunk.content = indent(chunk.content, docformat.indent))
|
||||
|
||||
chunk.content = render_code(docformat, chunk.content)
|
||||
|
||||
echo = chunk.options[:echo]
|
||||
|
||||
chunk.options[:eval] || return echo ? string(docformat.codestart, chunk.content, docformat.codeend) : ""
|
||||
|
||||
if chunk.options[:term]
|
||||
result = render_termchunk(docformat, chunk)
|
||||
else
|
||||
result = if echo
|
||||
# Convert to output format and highlight (html, tex...) if needed
|
||||
string(docformat.codestart, chunk.content, docformat.codeend, '\n')
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
if (strip(chunk.output) ≠ "" || strip(chunk.rich_output) ≠ "") &&
|
||||
(chunk.options[:results] ≠ "hidden")
|
||||
if chunk.options[:results] ≠ "markup" && chunk.options[:results] ≠ "hold"
|
||||
strip(chunk.output) ≠ "" && (result *= "$(chunk.output)\n")
|
||||
strip(chunk.rich_output) ≠ "" && (result *= "$(chunk.rich_output)\n")
|
||||
else
|
||||
if chunk.options[:wrap]
|
||||
chunk.output =
|
||||
'\n' * wraplines(chunk.output, chunk.options[:line_width])
|
||||
chunk.output = render_output(docformat, chunk.output)
|
||||
else
|
||||
chunk.output = '\n' * rstrip(chunk.output)
|
||||
chunk.output = render_output(docformat, chunk.output)
|
||||
end
|
||||
|
||||
hasproperty(docformat, :indent) && (chunk.output = indent(chunk.output, docformat.indent))
|
||||
|
||||
strip(chunk.output) ≠ "" && (
|
||||
result *= "$(docformat.outputstart)$(chunk.output)\n$(docformat.outputend)\n"
|
||||
)
|
||||
strip(chunk.rich_output) ≠ "" && (result *= chunk.rich_output * '\n')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Handle figures
|
||||
if chunk.options[:fig] && length(chunk.figures) > 0
|
||||
result *= render_figures(docformat, chunk)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
render_code(docformat::WeaveFormat, code) = code
|
||||
|
||||
indent(text, nindent) = join(map(x -> string(repeat(' ', nindent), x), split(text, '\n')), '\n')
|
||||
|
||||
function wraplines(text, line_width = 75)
|
||||
result = AbstractString[]
|
||||
lines = split(text, '\n')
|
||||
for line in lines
|
||||
if length(line) > line_width
|
||||
push!(result, wrapline(line, line_width))
|
||||
else
|
||||
push!(result, line)
|
||||
end
|
||||
end
|
||||
|
||||
return strip(join(result, '\n'))
|
||||
end
|
||||
|
||||
function wrapline(text, line_width = 75)
|
||||
result = ""
|
||||
while length(text) > line_width
|
||||
result *= first(text, line_width) * '\n'
|
||||
text = chop(text, head = line_width, tail = 0)
|
||||
end
|
||||
result *= text
|
||||
end
|
||||
|
||||
render_output(docformat::WeaveFormat, output) = output
|
||||
|
||||
function render_termchunk(docformat::WeaveFormat, chunk)
|
||||
return if should_render(chunk)
|
||||
string(docformat.termstart, chunk.output, docformat.termend)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
should_render(chunk) = chunk.options[:echo] && chunk.options[:results] ≠ "hidden"
|
||||
|
||||
render_doc(docformat, body, doc) = body
|
||||
|
||||
# utilities
|
||||
# ---------
|
||||
|
||||
function clear_buffer_and_format!(io::IOBuffer, out::IOBuffer, render_function)
|
||||
text = take2string!(io)
|
||||
m = Markdown.parse(text, flavor = WeaveMarkdown.weavemd)
|
||||
write(out, string(render_function(m)))
|
||||
end
|
||||
|
||||
addlines(op, inline) = inline.ctype === :line ? string('\n', op, '\n') : op
|
||||
|
||||
get_mustache_template(path::AbstractString) = Mustache.template_from_file(path)
|
||||
get_mustache_template(tpl::Mustache.MustacheTokens) = tpl
|
||||
|
||||
get_highlight_stylesheet(mime, highlight_theme) =
|
||||
get_highlight_stylesheet(mime, get_highlight_theme(highlight_theme))
|
||||
get_highlight_stylesheet(mime, highlight_theme::Type{<:Highlights.AbstractTheme}) =
|
||||
sprint((io, x) -> Highlights.stylesheet(io, mime, x), highlight_theme)
|
||||
|
||||
get_highlight_theme(::Nothing) = Highlights.Themes.DefaultTheme
|
||||
get_highlight_theme(highlight_theme::Type{<:Highlights.AbstractTheme}) = highlight_theme
|
||||
|
||||
highlight_code(mime, code, highlight_theme) =
|
||||
highlight(mime, strip(code), Highlights.Lexers.JuliaLexer, highlight_theme)
|
||||
highlight_term(mime, output, highlight_theme) =
|
||||
highlight(mime, strip(output), Highlights.Lexers.JuliaConsoleLexer, highlight_theme)
|
||||
highlight(mime, output, lexer, theme = Highlights.Themes.DefaultTheme) =
|
||||
sprint((io, x) -> Highlights.highlight(io, mime, x, lexer, theme), output)
|
|
@ -0,0 +1,24 @@
|
|||
abstract type ExportFormat <: WeaveFormat end
|
||||
|
||||
function Base.getproperty(sf::T, s::Symbol) where {T<:ExportFormat}
|
||||
hasfield(T, s) && return getfield(sf, s)
|
||||
return getproperty(sf.primaryformat, s)
|
||||
end
|
||||
function Base.setproperty!(sf::T, s::Symbol, v) where {T<:ExportFormat}
|
||||
if hasfield(T, s)
|
||||
setfield!(sf, s, v)
|
||||
else
|
||||
setproperty!(sf.primaryformat, s, v)
|
||||
end
|
||||
end
|
||||
function Base.hasproperty(sf::T, s::Symbol) where {T<:ExportFormat}
|
||||
hasfield(T, s) || hasproperty(sf.primaryformat, s)
|
||||
end
|
||||
|
||||
render_doc(df::ExportFormat, body, doc) = render_doc(df.primaryformat, body, doc)
|
||||
|
||||
render_chunk(df::ExportFormat, chunk) = render_chunk(df.primaryformat, chunk)
|
||||
# Need to define these to avoid ambiguities
|
||||
render_chunk(df::ExportFormat, chunk::DocChunk) = render_chunk(df.primaryformat, chunk)
|
||||
render_chunk(df::ExportFormat, chunk::CodeChunk) = render_chunk(df.primaryformat, chunk)
|
||||
render_output(df::ExportFormat, output) = render_output(df.primaryformat, output)
|
|
@ -0,0 +1,146 @@
|
|||
# HTML
|
||||
# ----
|
||||
|
||||
abstract type HTMLFormat <: WeaveFormat end
|
||||
|
||||
render_code(docformat::HTMLFormat, code) =
|
||||
highlight_code(MIME("text/html"), code, docformat.highlight_theme)
|
||||
|
||||
render_termchunk(docformat::HTMLFormat, chunk) =
|
||||
should_render(chunk) ? highlight_term(MIME("text/html"), chunk.output, docformat.highlight_theme) : ""
|
||||
|
||||
# Julia markdown
|
||||
# --------------
|
||||
|
||||
Base.@kwdef mutable struct WeaveHTML <: HTMLFormat
|
||||
description = "Weave-style HTML"
|
||||
extension = "html"
|
||||
codestart = '\n'
|
||||
codeend = '\n'
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "<pre class=\"output\">"
|
||||
outputend = "</pre>\n"
|
||||
mimetypes = ["image/png", "image/jpg", "image/svg+xml",
|
||||
"text/html", "text/markdown", "text/plain"]
|
||||
fig_ext = ".png"
|
||||
out_width = nothing
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
template = nothing
|
||||
stylesheet = nothing
|
||||
highlight_theme = nothing
|
||||
end
|
||||
register_format!("md2html", WeaveHTML())
|
||||
|
||||
function set_format_options!(docformat::WeaveHTML; template = nothing, css = nothing, highlight_theme = nothing, _kwargs...)
|
||||
template_path = isnothing(template) ? normpath(TEMPLATE_DIR, "md2html.tpl") : template
|
||||
docformat.template = get_mustache_template(template_path)
|
||||
stylesheet_path = isnothing(css) ? normpath(STYLESHEET_DIR, "skeleton.css") : css
|
||||
docformat.stylesheet = read(stylesheet_path, String)
|
||||
docformat.highlight_theme = get_highlight_theme(highlight_theme)
|
||||
end
|
||||
|
||||
# very similar to tex version of function
|
||||
function render_chunk(docformat::WeaveHTML, chunk::DocChunk)
|
||||
out = IOBuffer()
|
||||
io = IOBuffer()
|
||||
for inline in chunk.content
|
||||
if isa(inline, InlineText)
|
||||
write(io, inline.content)
|
||||
elseif !isempty(inline.rich_output)
|
||||
clear_buffer_and_format!(io, out, WeaveMarkdown.html)
|
||||
write(out, addlines(inline.rich_output, inline))
|
||||
elseif !isempty(inline.figures)
|
||||
write(io, inline.figures[end])
|
||||
elseif !isempty(inline.output)
|
||||
write(io, addlines(inline.output, inline))
|
||||
end
|
||||
end
|
||||
clear_buffer_and_format!(io, out, WeaveMarkdown.html)
|
||||
return take2string!(out)
|
||||
end
|
||||
|
||||
render_output(docformat::WeaveHTML, output) = Markdown.htmlesc(output)
|
||||
|
||||
function render_figures(docformat::WeaveHTML, chunk)
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
width = chunk.options[:out_width]
|
||||
height = chunk.options[:out_height]
|
||||
f_pos = chunk.options[:fig_pos]
|
||||
f_env = chunk.options[:fig_env]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
# Set size
|
||||
attribs = ""
|
||||
isnothing(width) || (attribs = "width=\"$width\"")
|
||||
(!isempty(attribs) && !isnothing(height)) && (attribs *= ",")
|
||||
isnothing(height) || (attribs *= " height=\"$height\" ")
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= """<figure>\n"""
|
||||
end
|
||||
|
||||
for fig in fignames
|
||||
figstring *= """<img src="$fig" $attribs />\n"""
|
||||
end
|
||||
|
||||
result *= figstring
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= """
|
||||
<figcaption>$caption</figcaption>
|
||||
"""
|
||||
end
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= "</figure>\n"
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function render_doc(docformat::WeaveHTML, body, doc; css = nothing)
|
||||
_, weave_source = splitdir(abspath(doc.source))
|
||||
weave_version, weave_date = weave_info()
|
||||
|
||||
return Mustache.render(
|
||||
docformat.template;
|
||||
body = body,
|
||||
stylesheet = docformat.stylesheet,
|
||||
highlight_stylesheet = get_highlight_stylesheet(MIME("text/html"), docformat.highlight_theme),
|
||||
header_script = doc.header_script,
|
||||
weave_source = weave_source,
|
||||
weave_version = weave_version,
|
||||
weave_date = weave_date,
|
||||
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
|
||||
)
|
||||
end
|
||||
|
||||
# Pandoc
|
||||
# ------
|
||||
|
||||
Base.@kwdef mutable struct Pandoc2HTML <: ExportFormat
|
||||
description = "HTML via intermediate Pandoc Markdown (requires Pandoc 2)"
|
||||
primaryformat = Pandoc()
|
||||
template_path = nothing
|
||||
stylesheet_path = nothing
|
||||
highlight_theme = nothing
|
||||
pandoc_options = String[]
|
||||
end
|
||||
register_format!("pandoc2html", Pandoc2HTML())
|
||||
|
||||
function set_format_options!(docformat::Pandoc2HTML; template = nothing, css = nothing, highlight_theme = nothing, pandoc_options = String[], _kwargs...)
|
||||
docformat.template_path =
|
||||
isnothing(template) ? normpath(TEMPLATE_DIR, "pandoc2html.html") : template
|
||||
docformat.stylesheet_path =
|
||||
isnothing(css) ? normpath(STYLESHEET_DIR, "pandoc2html_skeleton.css") : css
|
||||
docformat.highlight_theme = get_highlight_theme(highlight_theme)
|
||||
docformat.pandoc_options = pandoc_options
|
||||
end
|
||||
|
||||
render_figures(docformat::Pandoc2HTML, chunk) = render_figures(Pandoc(), chunk)
|
|
@ -0,0 +1,224 @@
|
|||
# GitHub markdown
|
||||
# ---------------
|
||||
|
||||
Base.@kwdef mutable struct GitHubMarkdown <: WeaveFormat
|
||||
description = "GitHub Markdown"
|
||||
extension = "md"
|
||||
codestart = "```julia"
|
||||
codeend = "```\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "```"
|
||||
outputend = "```\n\n"
|
||||
fig_ext = ".png"
|
||||
mimetypes = ["image/png", "image/svg+xml", "image/jpg",
|
||||
"text/markdown", "text/plain"]
|
||||
out_width = nothing
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
preserve_header = true
|
||||
end
|
||||
register_format!("github", GitHubMarkdown())
|
||||
|
||||
function render_figures(docformat::GitHubMarkdown, chunk)
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
length(fignames) > 0 || (return "")
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= "![$caption]($(fignames[1]))\n"
|
||||
for fig in fignames[2:end]
|
||||
result *= "![]($fig)\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
end
|
||||
else
|
||||
for fig in fignames
|
||||
result *= "![]($fig)\n"
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
# Hugo markdown
|
||||
# -------------
|
||||
|
||||
Base.@kwdef mutable struct Hugo <: WeaveFormat
|
||||
description = "Hugo Markdown (using shortcodes)"
|
||||
extension = "md"
|
||||
codestart = "```julia"
|
||||
codeend = "```\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "```"
|
||||
outputend = "```\n\n"
|
||||
mimetypes = default_mime_types
|
||||
fig_ext = ".png"
|
||||
out_width = nothing
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
preserve_header = true
|
||||
uglyURLs = false # if `false`, prepend figure path by `..`
|
||||
end
|
||||
register_format!("hugo", Hugo())
|
||||
|
||||
function render_figures(docformat::Hugo, chunk)
|
||||
relpath = docformat.uglyURLs ? "" : ".."
|
||||
mapreduce(*, enumerate(chunk.figures), init = "") do (index, fig)
|
||||
if index > 1
|
||||
@warn("Only the first figure gets a caption.")
|
||||
title_spec = ""
|
||||
else
|
||||
caption = chunk.options[:fig_cap]
|
||||
title_spec = isnothing(caption) ? "" : "title=\"$(caption)\" "
|
||||
end
|
||||
"{{< figure src=\"$(joinpath(relpath, fig))\" $(title_spec) >}}"
|
||||
end
|
||||
end
|
||||
|
||||
# multi language markdown
|
||||
# -----------------------
|
||||
|
||||
Base.@kwdef mutable struct MultiMarkdown <: WeaveFormat
|
||||
description = "MultiMarkdown"
|
||||
extension = "md"
|
||||
codestart = "```julia"
|
||||
codeend = "```\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "```"
|
||||
outputend = "```\n\n"
|
||||
mimetypes = default_mime_types
|
||||
fig_ext = ".png"
|
||||
out_width = nothing
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
preserve_header = true
|
||||
end
|
||||
register_format!("multimarkdown", MultiMarkdown())
|
||||
|
||||
function render_figures(docformat::MultiMarkdown, chunk)
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
if chunk.options[:out_width] == nothing
|
||||
width = ""
|
||||
else
|
||||
width = "width=$(chunk.options[:out_width])"
|
||||
end
|
||||
|
||||
length(fignames) > 0 || (return "")
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= "![$caption][$(fignames[1])]\n\n"
|
||||
result *= "[$(fignames[1])]: $(fignames[1]) $width\n"
|
||||
for fig in fignames[2:end]
|
||||
result *= "![][$fig]\n\n"
|
||||
result *= "[$fig]: $fig $width\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
end
|
||||
else
|
||||
for fig in fignames
|
||||
result *= "![][$fig]\n\n"
|
||||
result *= "[$fig]: $fig $width\n"
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
# Rest
|
||||
# ----
|
||||
|
||||
Base.@kwdef mutable struct Rest <: WeaveFormat
|
||||
description = "reStructuredText and Sphinx"
|
||||
extension = "rst"
|
||||
codestart = ".. code-block:: julia\n"
|
||||
codeend = "\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "::\n"
|
||||
outputend = "\n\n"
|
||||
mimetypes = default_mime_types
|
||||
fig_ext = ".png"
|
||||
out_width = "15 cm"
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
indent = 4
|
||||
end
|
||||
register_format!("rst", Rest())
|
||||
|
||||
function render_figures(docformat::Rest, chunk)
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
width = chunk.options[:out_width]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
for fig in fignames
|
||||
figstring *= @sprintf(".. image:: %s\n :width: %s\n\n", fig, width)
|
||||
end
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= string(
|
||||
".. figure:: $(fignames[1])\n",
|
||||
" :width: $width\n\n",
|
||||
" $caption\n\n",
|
||||
)
|
||||
else
|
||||
result *= figstring
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
# Ansii
|
||||
# -----
|
||||
|
||||
# asciidoc -b html5 -a source-highlighter=pygments ...
|
||||
Base.@kwdef mutable struct AsciiDoc <: WeaveFormat
|
||||
description = "AsciiDoc"
|
||||
extension = "txt"
|
||||
codestart = "[source,julia]\n--------------------------------------"
|
||||
codeend = "--------------------------------------\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "--------------------------------------"
|
||||
outputend = "--------------------------------------\n\n"
|
||||
mimetypes = default_mime_types
|
||||
fig_ext = ".png"
|
||||
out_width = "600"
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
end
|
||||
register_format!("asciidoc", AsciiDoc())
|
||||
|
||||
function render_figures(docformat::AsciiDoc, chunk)
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
width = chunk.options[:out_width]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
for fig in fignames
|
||||
figstring *= @sprintf("image::%s[width=%s]\n", fig, width)
|
||||
end
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= string("image::$(fignames[1])", "[width=$width,", "title=\"$caption\"]")
|
||||
else
|
||||
result *= figstring
|
||||
return result
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
abstract type PandocFormat <: WeaveFormat end
|
||||
|
||||
function render_figures(docformat::PandocFormat, chunk)
|
||||
fignames = chunk.figures
|
||||
length(fignames) > 0 || (return "")
|
||||
|
||||
caption = chunk.options[:fig_cap]
|
||||
label = get(chunk.options, :label, nothing)
|
||||
result = ""
|
||||
figstring = ""
|
||||
attribs = ""
|
||||
width = chunk.options[:out_width]
|
||||
height = chunk.options[:out_height]
|
||||
|
||||
# Build figure attibutes
|
||||
attribs = String[]
|
||||
isnothing(width) || push!(attribs, "width=$width")
|
||||
isnothing(height) || push!(attribs, "height=$height")
|
||||
isnothing(label) || push!(attribs, "#fig:$label")
|
||||
attribs = isempty(attribs) ? "" : "{" * join(attribs, " ") * "}"
|
||||
|
||||
if !isnothing(caption)
|
||||
result *= "![$caption]($(fignames[1]))$attribs\n"
|
||||
for fig in fignames[2:end]
|
||||
result *= "![]($fig)$attribs\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
end
|
||||
else
|
||||
for fig in fignames
|
||||
result *= "![]($fig)$attribs\\ \n\n"
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
Base.@kwdef mutable struct Pandoc <: PandocFormat
|
||||
description = "Pandoc Markdown"
|
||||
extension = "md"
|
||||
codestart = "~~~~{.julia}"
|
||||
codeend = "~~~~~~~~~~~~~\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "~~~~"
|
||||
outputend = "~~~~\n\n"
|
||||
# Prefer png figures for markdown conversion, svg doesn't work with latex
|
||||
mimetypes = ["image/png", "image/jpg", "image/svg+xml", "text/markdown", "text/plain"]
|
||||
fig_ext = ".png"
|
||||
out_width = nothing
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
preserve_header = true
|
||||
end
|
||||
register_format!("pandoc", Pandoc())
|
||||
|
||||
|
||||
const DEFAULT_PANDOC_OPTIONS = String[]
|
||||
|
||||
Base.@kwdef mutable struct Pandoc2PDF <: ExportFormat
|
||||
description = "PDF via intermediate Pandoc Markdown"
|
||||
primaryformat = Pandoc()
|
||||
pandoc_options = DEFAULT_PANDOC_OPTIONS
|
||||
header_template = normpath(TEMPLATE_DIR, "pandoc2pdf_header.txt")
|
||||
end
|
||||
register_format!("pandoc2pdf", Pandoc2PDF())
|
||||
|
||||
function set_format_options!(docformat::Pandoc2PDF; pandoc_options = DEFAULT_PANDOC_OPTIONS, _kwargs...)
|
||||
docformat.pandoc_options = pandoc_options
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
# TODO:
|
||||
# - 1. Improve argument handling
|
||||
# - 2. Update code to use UnPack.jl to make it more readable
|
||||
# - 3. Export new interface
|
||||
# - 4. Document Interface
|
||||
|
||||
using Mustache, Highlights, .WeaveMarkdown, Markdown, Dates, Printf
|
||||
|
||||
|
||||
const FORMATS = Dict{String,WeaveFormat}()
|
||||
|
||||
# TODO: do some assertion for necessary fields of `format`
|
||||
register_format!(format_name::AbstractString, format::WeaveFormat) = push!(FORMATS, format_name => format)
|
||||
register_format!(_, format) = error("Format needs to be a subtype of WeaveFormat.")
|
||||
|
||||
set_format_options!(doc; kwargs...) = set_format_options!(doc.format; kwargs...)
|
||||
|
||||
function render_doc(doc::WeaveDoc)
|
||||
restore_header!(doc)
|
||||
|
||||
docformat = doc.format
|
||||
body = joinlines(render_chunk.(Ref(docformat), copy(doc.chunks)))
|
||||
return render_doc(docformat, body, doc)
|
||||
end
|
||||
|
||||
include("exportformat.jl")
|
||||
include("common.jl")
|
||||
include("pandocformats.jl")
|
||||
include("htmlformats.jl")
|
||||
include("texformats.jl")
|
||||
include("miscformats.jl")
|
|
@ -0,0 +1,264 @@
|
|||
# Tex
|
||||
# ---
|
||||
|
||||
abstract type LaTeXFormat <: WeaveFormat end
|
||||
|
||||
function set_format_options!(docformat::LaTeXFormat; keep_unicode = false, template = nothing, _kwargs...)
|
||||
docformat.keep_unicode |= keep_unicode
|
||||
docformat.template =
|
||||
get_mustache_template(isnothing(template) ? normpath(TEMPLATE_DIR, "md2pdf.tpl") : template)
|
||||
end
|
||||
|
||||
# very similar to export to html
|
||||
function render_chunk(docformat::LaTeXFormat, chunk::DocChunk)
|
||||
out = IOBuffer()
|
||||
io = IOBuffer()
|
||||
for inline in chunk.content
|
||||
if isa(inline, InlineText)
|
||||
write(io, inline.content)
|
||||
elseif !isempty(inline.rich_output)
|
||||
clear_buffer_and_format!(io, out, WeaveMarkdown.latex)
|
||||
write(out, addlines(inline.rich_output, inline))
|
||||
elseif !isempty(inline.figures)
|
||||
write(io, inline.figures[end], inline)
|
||||
elseif !isempty(inline.output)
|
||||
write(io, addlines(inline.output, inline))
|
||||
end
|
||||
end
|
||||
clear_buffer_and_format!(io, out, WeaveMarkdown.latex)
|
||||
out = take2string!(out)
|
||||
return unicode2latex(docformat, out)
|
||||
end
|
||||
|
||||
render_output(docformat::LaTeXFormat, output) = unicode2latex(docformat, output, true)
|
||||
|
||||
render_code(docformat::LaTeXFormat, code) = unicode2latex(docformat, code, true)
|
||||
|
||||
render_termchunk(docformat::LaTeXFormat, chunk) =
|
||||
string(docformat.termstart,
|
||||
unicode2latex(docformat, chunk.output, true),
|
||||
docformat.termend, "\n")
|
||||
|
||||
# from julia symbols (e.g. "\bfhoge") to valid latex
|
||||
const UNICODE2LATEX = let
|
||||
function texify(s)
|
||||
return if occursin(r"^\\bf[A-Z]$", s)
|
||||
replace(s, "\\bf" => "\\bm{\\mathrm{") * "}}"
|
||||
elseif startswith(s, "\\bfrak")
|
||||
replace(s, "\\bfrak" => "\\bm{\\mathfrak{") * "}}"
|
||||
elseif startswith(s, "\\bf")
|
||||
replace(s, "\\bf" => "\\bm{\\") * "}"
|
||||
elseif startswith(s, "\\frak")
|
||||
replace(s, "\\frak" => "\\mathfrak{") * "}"
|
||||
else
|
||||
s
|
||||
end
|
||||
end
|
||||
Dict(unicode => texify(sym) for (sym, unicode) in REPL.REPLCompletions.latex_symbols)
|
||||
end
|
||||
|
||||
function unicode2latex(docformat::LaTeXFormat, s, escape = false)
|
||||
# Check whether to convert at all and return input if not
|
||||
docformat.keep_unicode && return s
|
||||
for (unicode, latex) in UNICODE2LATEX
|
||||
body = "\\ensuremath{$(latex)}"
|
||||
target = escape ? string(docformat.escape_starter, body, docformat.escape_closer) : body
|
||||
s = replace(s, unicode => target)
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
function render_figures(docformat::LaTeXFormat, chunk)
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
width = chunk.options[:out_width]
|
||||
height = chunk.options[:out_height]
|
||||
f_pos = chunk.options[:fig_pos]
|
||||
f_env = chunk.options[:fig_env]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
if isnothing(f_env) && !isnothing(caption)
|
||||
f_env = "figure"
|
||||
end
|
||||
|
||||
(isnothing(f_pos)) && (f_pos = "!h")
|
||||
# Set size
|
||||
attribs = ""
|
||||
isnothing(width) || (attribs = "width=$(md_length_to_latex(width,"\\linewidth"))")
|
||||
(!isempty(attribs) && !isnothing(height)) && (attribs *= ",")
|
||||
isnothing(height) || (attribs *= "height=$(md_length_to_latex(height,"\\paperheight"))")
|
||||
|
||||
if !isnothing(f_env)
|
||||
result *= "\\begin{$f_env}"
|
||||
(!isempty(f_pos)) && (result *= "[$f_pos]")
|
||||
result *= "\n"
|
||||
end
|
||||
|
||||
for fig in fignames
|
||||
if splitext(fig)[2] == ".tex" # Tikz figures
|
||||
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
|
||||
else
|
||||
if isempty(attribs)
|
||||
figstring *= "\\includegraphics{$fig}\n"
|
||||
else
|
||||
figstring *= "\\includegraphics[$attribs]{$fig}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Figure environment
|
||||
if !isnothing(caption)
|
||||
result *= string("\\center\n", "$figstring", "\\caption{$caption}\n")
|
||||
else
|
||||
result *= figstring
|
||||
end
|
||||
|
||||
if !isnothing(chunk.options[:label]) && !isnothing(f_env)
|
||||
label = chunk.options[:label]
|
||||
result *= "\\label{fig:$label}\n"
|
||||
end
|
||||
|
||||
if !isnothing(f_env)
|
||||
result *= "\\end{$f_env}\n"
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function md_length_to_latex(def, reference)
|
||||
if occursin("%", def)
|
||||
_def = tryparse(Float64, replace(def, "%" => ""))
|
||||
isnothing(_def) && return def
|
||||
perc = round(_def / 100, digits = 2)
|
||||
return "$perc$reference"
|
||||
end
|
||||
return def
|
||||
end
|
||||
|
||||
function render_doc(docformat::LaTeXFormat, body, doc)
|
||||
return Mustache.render(
|
||||
docformat.template;
|
||||
body = body,
|
||||
highlight = "",
|
||||
tex_deps = docformat.tex_deps,
|
||||
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
|
||||
)
|
||||
end
|
||||
|
||||
# minted Tex
|
||||
# ----------
|
||||
|
||||
Base.@kwdef mutable struct LaTeXMinted <: LaTeXFormat
|
||||
description = "LaTeX using minted package for code highlighting"
|
||||
extension = "tex"
|
||||
codestart = "\\begin{minted}[texcomments = true, mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}"
|
||||
codeend = "\\end{minted}"
|
||||
termstart = "\\begin{minted}[texcomments = true, mathescape, fontsize=\\footnotesize, xleftmargin=0.5em]{jlcon}"
|
||||
termend = "\\end{minted}"
|
||||
outputstart = "\\begin{minted}[texcomments = true, mathescape, fontsize=\\small, xleftmargin=0.5em, frame = leftline]{text}"
|
||||
outputend = "\\end{minted}"
|
||||
mimetypes = ["application/pdf", "image/png", "text/latex", "text/plain"]
|
||||
fig_ext = ".pdf"
|
||||
out_width = "\\linewidth"
|
||||
out_height = nothing
|
||||
fig_pos = "htpb"
|
||||
fig_env = "figure"
|
||||
# specials
|
||||
keep_unicode = false
|
||||
template = nothing
|
||||
tex_deps = "\\usepackage{minted}"
|
||||
# how to escape latex in verbatim/code environment
|
||||
escape_starter = "|\$"
|
||||
escape_closer = reverse(escape_starter)
|
||||
end
|
||||
register_format!("texminted", LaTeXMinted())
|
||||
|
||||
# Tex (directly to PDF)
|
||||
# ---------------------
|
||||
|
||||
abstract type WeaveLaTeXFormat <: LaTeXFormat end
|
||||
|
||||
function set_format_options!(docformat::WeaveLaTeXFormat; template = nothing, highlight_theme = nothing, keep_unicode = false, _kwargs...)
|
||||
docformat.template =
|
||||
get_mustache_template(isnothing(template) ? normpath(TEMPLATE_DIR, "md2pdf.tpl") : template)
|
||||
docformat.highlight_theme = get_highlight_theme(highlight_theme)
|
||||
docformat.keep_unicode |= keep_unicode
|
||||
end
|
||||
|
||||
function render_output(docformat::WeaveLaTeXFormat, output)
|
||||
# Highligts has some extra escaping defined, eg of $, ", ...
|
||||
output_escaped = sprint(
|
||||
(io, x) ->
|
||||
Highlights.Format.escape(io, MIME("text/latex"), x, charescape = true),
|
||||
output,
|
||||
)
|
||||
return unicode2latex(docformat, output_escaped, true)
|
||||
end
|
||||
|
||||
function render_code(docformat::WeaveLaTeXFormat, code)
|
||||
ret = highlight_code(MIME("text/latex"), code, docformat.highlight_theme)
|
||||
unicode2latex(docformat, ret, false)
|
||||
end
|
||||
|
||||
function render_termchunk(docformat::WeaveLaTeXFormat, chunk)
|
||||
if should_render(chunk)
|
||||
ret = highlight_term(MIME("text/latex"), chunk.output, docformat.highlight_theme)
|
||||
unicode2latex(docformat, ret, true)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
function render_doc(docformat::WeaveLaTeXFormat, body, doc)
|
||||
return Mustache.render(
|
||||
docformat.template;
|
||||
body = body,
|
||||
highlight = get_highlight_stylesheet(MIME("text/latex"), docformat.highlight_theme),
|
||||
tex_deps = docformat.tex_deps,
|
||||
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
|
||||
)
|
||||
end
|
||||
|
||||
Base.@kwdef mutable struct WeaveLaTeX <: WeaveLaTeXFormat
|
||||
description = "Weave-styled LaTeX"
|
||||
extension = "tex"
|
||||
codestart = ""
|
||||
codeend = ""
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "\\begin{lstlisting}"
|
||||
outputend = "\\end{lstlisting}\n"
|
||||
mimetypes = ["application/pdf", "image/png", "image/jpg", "text/latex", "text/markdown", "text/plain"]
|
||||
fig_ext = ".pdf"
|
||||
out_width = "\\linewidth"
|
||||
out_height = nothing
|
||||
fig_pos = nothing
|
||||
fig_env = nothing
|
||||
# specials
|
||||
highlight_theme = nothing
|
||||
template = nothing
|
||||
keep_unicode = false
|
||||
tex_deps = ""
|
||||
# how to escape latex in verbatim/code environment
|
||||
escape_starter = "(*@"
|
||||
escape_closer = "@*)"
|
||||
end
|
||||
register_format!("md2tex", WeaveLaTeX())
|
||||
|
||||
# will be used by `write_doc`
|
||||
const DEFAULT_LATEX_CMD = ["xelatex", "-shell-escape", "-halt-on-error"]
|
||||
|
||||
|
||||
Base.@kwdef mutable struct LaTeX2PDF <: ExportFormat
|
||||
primaryformat = WeaveLaTeX()
|
||||
description = "PDF via LaTeX"
|
||||
latex_cmd = DEFAULT_LATEX_CMD
|
||||
end
|
||||
register_format!("md2pdf", LaTeX2PDF())
|
||||
register_format!("minted2pdf", LaTeX2PDF(primaryformat=LaTeXMinted()))
|
||||
|
||||
function set_format_options!(docformat::LaTeX2PDF; latex_cmd = DEFAULT_LATEX_CMD, _kwargs...)
|
||||
docformat.latex_cmd = latex_cmd
|
||||
set_format_options!(docformat.primaryformat; _kwargs...)
|
||||
end
|
|
@ -0,0 +1,451 @@
|
|||
using Base64
|
||||
|
||||
|
||||
const PROGRESS_ID = "weave_progress"
|
||||
|
||||
function run_doc(
|
||||
doc::WeaveDoc;
|
||||
doctype::Union{Nothing,AbstractString} = nothing,
|
||||
out_path::Union{Symbol,AbstractString} = :doc,
|
||||
args::Any = Dict(),
|
||||
mod::Union{Module,Nothing} = nothing,
|
||||
fig_path::Union{Nothing,AbstractString} = nothing,
|
||||
fig_ext::Union{Nothing,AbstractString} = nothing,
|
||||
cache_path::AbstractString = "cache",
|
||||
cache::Symbol = :off,
|
||||
)
|
||||
# cache :all, :user, :off, :refresh
|
||||
|
||||
doc.doctype = isnothing(doctype) ? (doctype = detect_doctype(doc.source)) : doctype
|
||||
doc.format = deepcopy(get_format(doctype))
|
||||
|
||||
cwd = doc.cwd = get_cwd(doc, out_path)
|
||||
mkpath(cwd)
|
||||
|
||||
# TODO: provide a way not to create `fig_path` ?
|
||||
if isnothing(fig_path)
|
||||
fig_path = if (endswith(doctype, "2pdf") && cache === :off) || endswith(doctype, "2html")
|
||||
basename(mktempdir(abspath(cwd)))
|
||||
else
|
||||
DEFAULT_FIG_PATH
|
||||
end
|
||||
end
|
||||
mkpath(normpath(cwd, fig_path))
|
||||
# This is needed for latex and should work on all output formats
|
||||
@static Sys.iswindows() && (fig_path = replace(fig_path, "\\" => "/"))
|
||||
set_rc_params(doc, fig_path, fig_ext)
|
||||
|
||||
cache === :off || @eval import Serialization # XXX: evaluate in a more sensible module
|
||||
|
||||
# New sandbox for each document with args exposed
|
||||
isnothing(mod) && (mod = sandbox = Core.eval(Main, :(module $(gensym(:WeaveSandBox)) end))::Module)
|
||||
Core.eval(mod, :(WEAVE_ARGS = $(args)))
|
||||
|
||||
mimetypes = doc.format.mimetypes
|
||||
|
||||
report = Report(cwd, doc.basename, doc.format, mimetypes)
|
||||
cd_back = let d = pwd(); () -> cd(d); end
|
||||
cd(cwd)
|
||||
pushdisplay(report)
|
||||
try
|
||||
if cache !== :off && cache !== :refresh
|
||||
cached = read_cache(doc, cache_path)
|
||||
isnothing(cached) && @info "No cached results found, running code"
|
||||
else
|
||||
cached = nothing
|
||||
end
|
||||
|
||||
executed = []
|
||||
n = length(filter(chunk->isa(chunk,CodeChunk), doc.chunks))
|
||||
i = 0
|
||||
for chunk in doc.chunks
|
||||
if chunk isa CodeChunk
|
||||
options = merge(doc.chunk_defaults, chunk.options)
|
||||
merge!(chunk.options, options)
|
||||
|
||||
@info "Weaving chunk $(chunk.number) from line $(chunk.start_line)" progress=(i)/n _id=PROGRESS_ID
|
||||
i+=1
|
||||
end
|
||||
|
||||
restore = (cache === :user && chunk isa CodeChunk && chunk.options[:cache])
|
||||
result_chunks = if cached ≠ nothing && (cache === :all || restore)
|
||||
restore_chunk(chunk, cached)
|
||||
else
|
||||
run_chunk(chunk, doc, report, mod)
|
||||
end
|
||||
executed = [executed; result_chunks]
|
||||
end
|
||||
|
||||
replace_header_inline!(doc, report, mod) # evaluate and replace inline code in header
|
||||
|
||||
doc.header_script = report.header_script
|
||||
doc.chunks = executed
|
||||
|
||||
cache !== :off && write_cache(doc, cache_path)
|
||||
|
||||
@isdefined(sandbox) && clear_module!(sandbox)
|
||||
catch err
|
||||
rethrow(err)
|
||||
finally
|
||||
@info "Weaved all chunks" progress=1 _id=PROGRESS_ID
|
||||
cd_back()
|
||||
popdisplay(report) # ensure display pops out even if internal error occurs
|
||||
# Temporary fig_path is not automatically removed because it contains files so...
|
||||
!isnothing(fig_path) && startswith(fig_path, "jl_") && rm(normpath(cwd, fig_path), force=true, recursive=true)
|
||||
end
|
||||
|
||||
return doc
|
||||
end
|
||||
|
||||
run_doc(doc::WeaveDoc, doctype::Union{Nothing,AbstractString}; kwargs...) =
|
||||
run_doc(doc; doctype = doctype, kwargs...)
|
||||
|
||||
"""
|
||||
detect_doctype(path)
|
||||
|
||||
Detect the output format based on file extension.
|
||||
"""
|
||||
function detect_doctype(path)
|
||||
_, ext = lowercase.(splitext(path))
|
||||
|
||||
match(r"^\.(jl|.?md|ipynb)", ext) !== nothing && return "md2html"
|
||||
ext == ".rst" && return "rst"
|
||||
ext == ".tex" && return "texminted"
|
||||
ext == ".txt" && return "asciidoc"
|
||||
|
||||
return "pandoc"
|
||||
end
|
||||
|
||||
function get_cwd(doc, out_path)
|
||||
return if out_path === :doc
|
||||
dirname(doc.path)
|
||||
elseif out_path === :pwd
|
||||
pwd()
|
||||
else
|
||||
path, ext = splitext(out_path)
|
||||
if isempty(ext) # directory given
|
||||
path
|
||||
else # file given
|
||||
dirname(path)
|
||||
end
|
||||
end |> abspath
|
||||
end
|
||||
|
||||
function run_chunk(chunk::CodeChunk, doc, report, mod)
|
||||
result = eval_chunk(doc, chunk, report, mod)
|
||||
occursin("2html", doc.doctype) && (embed_figures!(result, report.cwd))
|
||||
return result
|
||||
end
|
||||
|
||||
function embed_figures!(chunk::CodeChunk, cwd)
|
||||
for (i, fig) in enumerate(chunk.figures)
|
||||
chunk.figures[i] = img2base64(fig, cwd)
|
||||
end
|
||||
end
|
||||
embed_figures!(chunks, cwd) = embed_figures!.(chunks, Ref(cwd))
|
||||
|
||||
function img2base64(fig, cwd)
|
||||
ext = splitext(fig)[2]
|
||||
f = open(joinpath(cwd, fig), "r")
|
||||
raw = read(f)
|
||||
close(f)
|
||||
return ext == ".png" ? "data:image/png;base64," * stringmime(MIME("image/png"), raw) :
|
||||
ext == ".svg" ? "data:image/svg+xml;base64," * stringmime(MIME("image/svg"), raw) :
|
||||
ext == ".gif" ? "data:image/gif;base64," * stringmime(MIME("image/gif"), raw) :
|
||||
fig
|
||||
end
|
||||
|
||||
function run_chunk(chunk::DocChunk, doc, report, mod)
|
||||
chunk.content = [run_inline(c, doc, report, mod) for c in chunk.content]
|
||||
return chunk
|
||||
end
|
||||
|
||||
run_inline(inline::InlineText, ::WeaveDoc, ::Report, ::Module) = inline
|
||||
|
||||
const INLINE_OPTIONS = Dict(
|
||||
:term => false,
|
||||
:hold => true,
|
||||
:wrap => false
|
||||
)
|
||||
|
||||
function run_inline(inline::InlineCode, doc::WeaveDoc, report::Report, mod::Module)
|
||||
# Make a temporary CodeChunk for running code. Collect results and don't wrap
|
||||
chunk = CodeChunk(inline.content, 0, 0, "", INLINE_OPTIONS)
|
||||
options = merge(doc.chunk_defaults, chunk.options)
|
||||
merge!(chunk.options, options)
|
||||
|
||||
chunks = eval_chunk(doc, chunk, report, mod)
|
||||
occursin("2html", doc.doctype) && (embed_figures!(chunks, report.cwd))
|
||||
|
||||
output = chunks[1].output
|
||||
endswith(output, "\n") && (output = output[1:end-1])
|
||||
inline.output = output
|
||||
inline.rich_output = chunks[1].rich_output
|
||||
inline.figures = chunks[1].figures
|
||||
return inline
|
||||
end
|
||||
|
||||
function run_code(doc::WeaveDoc, chunk::CodeChunk, report::Report, mod::Module)
|
||||
code = chunk.content
|
||||
path = doc.path
|
||||
error = chunk.options[:error]
|
||||
codes = chunk.options[:term] ? split_code(code) : [code]
|
||||
capture = code -> capture_output(code, mod, path, error, report)
|
||||
return capture.(codes)
|
||||
end
|
||||
|
||||
function split_code(code)
|
||||
res = String[]
|
||||
e = 1
|
||||
ex = :init
|
||||
while true
|
||||
s = e
|
||||
ex, e = Meta.parse(code, s)
|
||||
isnothing(ex) && break
|
||||
push!(res, strip(code[s:e-1]))
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function capture_output(code, mod, path, error, report)
|
||||
reset_report!(report)
|
||||
|
||||
old = stdout
|
||||
rw, wr = redirect_stdout()
|
||||
reader = @async read(rw, String)
|
||||
|
||||
local out = nothing
|
||||
task_local_storage(:SOURCE_PATH, path) do
|
||||
try
|
||||
obj = include_string(mod, code, path) # TODO: fix line number
|
||||
!isnothing(obj) && !REPL.ends_with_semicolon(code) && display(obj)
|
||||
catch _err
|
||||
err = unwrap_load_err(_err)
|
||||
error || throw(err)
|
||||
display(err)
|
||||
@warn "ERROR: $(typeof(err)) occurred, including output in Weaved document"
|
||||
finally
|
||||
redirect_stdout(old)
|
||||
close(wr)
|
||||
out = fetch(reader)
|
||||
close(rw)
|
||||
end
|
||||
end
|
||||
|
||||
return ChunkOutput(code, remove_ansi_control_chars(out), report.rich_output, report.figures)
|
||||
end
|
||||
|
||||
function reset_report!(report)
|
||||
report.rich_output = ""
|
||||
report.figures = String[]
|
||||
end
|
||||
|
||||
unwrap_load_err(err) = return err
|
||||
unwrap_load_err(err::LoadError) = return err.error
|
||||
|
||||
# https://stackoverflow.com/a/33925425/12113178
|
||||
remove_ansi_control_chars(s) = replace(s, r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]" => "")
|
||||
|
||||
function eval_chunk(doc::WeaveDoc, chunk::CodeChunk, report::Report, mod::Module)
|
||||
if !chunk.options[:eval]
|
||||
chunk.output = ""
|
||||
chunk.options[:fig] = false
|
||||
return chunk
|
||||
end
|
||||
|
||||
execute_prehooks!(chunk)
|
||||
|
||||
report.fignum = 1
|
||||
report.cur_chunk = chunk
|
||||
|
||||
if hasproperty(report.format, :out_width) && isnothing(chunk.options[:out_width])
|
||||
chunk.options[:out_width] = report.format.out_width
|
||||
end
|
||||
|
||||
chunk.result = run_code(doc, chunk, report, mod)
|
||||
|
||||
execute_posthooks!(chunk)
|
||||
|
||||
return chunk.options[:term] ? collect_term_results(chunk) :
|
||||
chunk.options[:hold] ? collect_hold_results(chunk) :
|
||||
collect_results(chunk)
|
||||
end
|
||||
|
||||
# Hooks to run before and after chunks, this is form IJulia,
|
||||
const preexecution_hooks = Function[]
|
||||
push_preexecution_hook!(f::Function) = push!(preexecution_hooks, f)
|
||||
function pop_preexecution_hook!(f::Function)
|
||||
i = findfirst(x -> x == f, preexecution_hooks)
|
||||
isnothing(i) && error("this function has not been registered in the pre-execution hook yet")
|
||||
return splice!(preexecution_hooks, i)
|
||||
end
|
||||
function execute_prehooks!(chunk::CodeChunk)
|
||||
for prehook in preexecution_hooks
|
||||
Base.invokelatest(prehook, chunk)
|
||||
end
|
||||
end
|
||||
|
||||
const postexecution_hooks = Function[]
|
||||
push_postexecution_hook!(f::Function) = push!(postexecution_hooks, f)
|
||||
function pop_postexecution_hook!(f::Function)
|
||||
i = findfirst(x -> x == f, postexecution_hooks)
|
||||
isnothing(i) && error("this function has not been registered in the post-execution hook yet")
|
||||
return splice!(postexecution_hooks, i)
|
||||
end
|
||||
function execute_posthooks!(chunk::CodeChunk)
|
||||
for posthook in postexecution_hooks
|
||||
Base.invokelatest(posthook, chunk)
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
clear_module!(mod::Module)
|
||||
|
||||
Recursively sets variables in `mod` to `nothing` so that they're GCed.
|
||||
|
||||
!!! warning
|
||||
`const` variables can't be reassigned, as such they can't be cleared.
|
||||
"""
|
||||
function clear_module!(mod::Module)
|
||||
for name in names(mod; all = true)
|
||||
name === :eval && continue
|
||||
try
|
||||
v = getfield(mod, name)
|
||||
if v isa Module && v != mod
|
||||
clear_module!(v)
|
||||
continue
|
||||
end
|
||||
isconst(mod, name) && continue # can't clear constant
|
||||
Core.eval(mod, :($name = nothing))
|
||||
catch err
|
||||
@debug err
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function get_figname(report::Report, chunk; fignum = nothing, ext = nothing)
|
||||
isnothing(ext) && (ext = chunk.options[:fig_ext])
|
||||
isnothing(fignum) && (fignum = report.fignum)
|
||||
|
||||
chunkid = isnothing(chunk.options[:label]) ? chunk.number : chunk.options[:label]
|
||||
basename = string(report.basename, '_', chunkid, '_', fignum, ext)
|
||||
full_name = normpath(report.cwd, chunk.options[:fig_path], basename)
|
||||
rel_name = string(chunk.options[:fig_path], '/', basename) # Relative path is used in output
|
||||
return full_name, rel_name
|
||||
end
|
||||
|
||||
function set_rc_params(doc::WeaveDoc, fig_path, fig_ext)
|
||||
doc.chunk_defaults[:fig_ext] = isnothing(fig_ext) ? doc.format.fig_ext : fig_ext
|
||||
doc.chunk_defaults[:fig_path] = fig_path
|
||||
end
|
||||
|
||||
function collect_results(chunk::CodeChunk)
|
||||
content = ""
|
||||
result_chunks = CodeChunk[]
|
||||
for r in chunk.result
|
||||
content *= r.code
|
||||
# Check if there is any output from chunk
|
||||
if any(!isempty ∘ strip, (r.stdout, r.rich_output)) || !isempty(r.figures)
|
||||
rchunk = CodeChunk(
|
||||
content,
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
rchunk.output = r.stdout
|
||||
rchunk.rich_output = r.rich_output
|
||||
rchunk.figures = r.figures
|
||||
push!(result_chunks, rchunk)
|
||||
content = ""
|
||||
end
|
||||
end
|
||||
if !isempty(content)
|
||||
rchunk = CodeChunk(
|
||||
content,
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
push!(result_chunks, rchunk)
|
||||
end
|
||||
|
||||
return result_chunks
|
||||
end
|
||||
|
||||
function collect_term_results(chunk::CodeChunk)
|
||||
output = ""
|
||||
prompt = chunk.options[:prompt]
|
||||
result_chunks = CodeChunk[]
|
||||
for r in chunk.result
|
||||
output *= string('\n', indent_term_code(prompt, r.code), '\n', r.stdout)
|
||||
if !isempty(r.figures)
|
||||
rchunk = CodeChunk(
|
||||
"",
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
rchunk.output = output
|
||||
output = ""
|
||||
rchunk.figures = r.figures
|
||||
push!(result_chunks, rchunk)
|
||||
end
|
||||
end
|
||||
if !isempty(output)
|
||||
rchunk = CodeChunk(
|
||||
"",
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
rchunk.output = output
|
||||
push!(result_chunks, rchunk)
|
||||
end
|
||||
|
||||
return result_chunks
|
||||
end
|
||||
|
||||
function indent_term_code(prompt, code)
|
||||
prompt_with_space = string(prompt, ' ')
|
||||
n = length(prompt_with_space)
|
||||
pads = ' ' ^ n
|
||||
return map(enumerate(split(code, '\n'))) do (i,line)
|
||||
isone(i) ? string(prompt_with_space, line) : string(pads, line)
|
||||
end |> joinlines
|
||||
end
|
||||
|
||||
function collect_hold_results(chunk::CodeChunk)
|
||||
for r in chunk.result
|
||||
chunk.output *= r.stdout
|
||||
chunk.rich_output *= r.rich_output
|
||||
chunk.figures = [chunk.figures; r.figures]
|
||||
end
|
||||
return [chunk]
|
||||
end
|
||||
|
||||
const HEADER_INLINE = Regex("$(HEADER_INLINE_START)(?<code>.+)$(HEADER_INLINE_END)")
|
||||
|
||||
replace_header_inline!(doc, report, mod) = _replace_header_inline!(doc, doc.header, report, mod)
|
||||
|
||||
function _replace_header_inline!(doc, header, report, mod)
|
||||
replace!(header) do (k,v)
|
||||
return k =>
|
||||
v isa Dict ? _replace_header_inline!(doc, v, report, mod) :
|
||||
!isa(v, AbstractString) ? v :
|
||||
replace(v, HEADER_INLINE => s -> begin
|
||||
code = replace(s, HEADER_INLINE => s"\g<code>")
|
||||
run_inline_code(code, doc, report, mod)
|
||||
end)
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
function run_inline_code(code, doc, report, mod)
|
||||
inline = InlineCode(code, 1, :inline)
|
||||
inline = run_inline(inline, doc, report, mod)
|
||||
return strip(inline.output, '"')
|
||||
end
|
|
@ -0,0 +1,72 @@
|
|||
# TODO: concreate typing
|
||||
|
||||
abstract type WeaveChunk end
|
||||
abstract type Inline end
|
||||
abstract type WeaveFormat end
|
||||
|
||||
mutable struct WeaveDoc
|
||||
source::AbstractString
|
||||
basename::AbstractString
|
||||
path::AbstractString
|
||||
chunks::Vector{WeaveChunk}
|
||||
cwd::AbstractString
|
||||
format::Any
|
||||
doctype::String
|
||||
header_script::String
|
||||
header::Dict
|
||||
chunk_defaults::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
struct ChunkOutput
|
||||
code::String
|
||||
stdout::String
|
||||
rich_output::String
|
||||
figures::Vector{String}
|
||||
end
|
||||
|
||||
mutable struct CodeChunk <: WeaveChunk
|
||||
content::String
|
||||
number::Int
|
||||
start_line::Int
|
||||
optionstring::String
|
||||
options::Dict{Symbol,Any}
|
||||
output::AbstractString
|
||||
rich_output::AbstractString
|
||||
figures::Vector{String}
|
||||
result::Vector{ChunkOutput}
|
||||
end
|
||||
|
||||
function CodeChunk(content, number, start_line, optionstring, options)
|
||||
return CodeChunk(
|
||||
string(rstrip(content), '\n'), # normalize end of chunk)
|
||||
number,
|
||||
start_line,
|
||||
optionstring,
|
||||
options,
|
||||
"",
|
||||
"",
|
||||
AbstractString[],
|
||||
ChunkOutput[]
|
||||
)
|
||||
end
|
||||
|
||||
mutable struct DocChunk <: WeaveChunk
|
||||
content::Vector{Inline}
|
||||
number::Int
|
||||
start_line::Int
|
||||
end
|
||||
|
||||
struct InlineText <: Inline
|
||||
content::String
|
||||
number::Int
|
||||
end
|
||||
|
||||
mutable struct InlineCode <: Inline
|
||||
content::String
|
||||
number::Int
|
||||
ctype::Symbol
|
||||
output::String
|
||||
rich_output::String
|
||||
figures::Vector{String}
|
||||
end
|
||||
InlineCode(content, number, ctype) = InlineCode(content, number, ctype, "", "", String[])
|
|
@ -1,35 +0,0 @@
|
|||
import Winston
|
||||
|
||||
function Base.display(report::Report, m::MIME"image/png", data)
|
||||
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = get_figname(report, chunk)
|
||||
|
||||
docformat = formats[report.formatdict[:doctype]]
|
||||
|
||||
#Add to results for term chunks and store otherwise
|
||||
if chunk[:term]
|
||||
chunk[:figure] = [rel_name]
|
||||
|
||||
if report.term_state == :text
|
||||
report.cur_result *= "\n" * report.formatdict[:codeend] * "\n"
|
||||
end
|
||||
|
||||
report.cur_result *= formatfigures(chunk, docformat)
|
||||
report.term_state = :fig
|
||||
chunk[:figure] = String[]
|
||||
else
|
||||
push!(report.figures, rel_name)
|
||||
end
|
||||
|
||||
vector_fmts = [".pdf", ".svg"]
|
||||
|
||||
#Don't use dpi for vector formats
|
||||
if chunk[:fig_ext] in vector_fmts
|
||||
Winston.savefig(data, full_name, width=chunk[:fig_width]*100, height=chunk[:fig_height]*100)
|
||||
else
|
||||
Winston.savefig(data, full_name, width=chunk[:fig_width]*chunk[:dpi], height=chunk[:fig_height]*chunk[:dpi])
|
||||
end
|
||||
|
||||
report.fignum += 1
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
function write_doc(docformat::LaTeX2PDF, doc, rendered, out_path)
|
||||
cd_back = let d = pwd(); () -> cd(d); end
|
||||
cd(doc.cwd)
|
||||
try
|
||||
tex_path = basename(out_path)
|
||||
write(tex_path, rendered)
|
||||
cmds = copy(docformat.latex_cmd)
|
||||
push!(cmds, tex_path)
|
||||
cmd = Cmd(cmds)
|
||||
run(cmd); run(cmd) # XXX: is twice enough for every case ?
|
||||
catch
|
||||
@warn "Error converting document to pdf. Try running latex manually"
|
||||
rethrow()
|
||||
finally
|
||||
cd_back()
|
||||
end
|
||||
|
||||
return get_out_path(doc, out_path, "pdf")
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
function write_doc(docformat::Pandoc2HTML, doc, rendered, out_path)
|
||||
_, weave_source = splitdir(abspath(doc.source))
|
||||
weave_version, weave_date = weave_info()
|
||||
|
||||
# Header is inserted from displayed plots
|
||||
header_script = doc.header_script
|
||||
self_contained = (header_script ≠ "") ? [] : "--self-contained"
|
||||
|
||||
if haskey(doc.header, "bibliography")
|
||||
filt = "--filter"
|
||||
citeproc = "pandoc-citeproc"
|
||||
else
|
||||
filt = []
|
||||
citeproc = []
|
||||
end
|
||||
|
||||
out_path = get_out_path(doc, out_path, "html")
|
||||
cd_back = let d = pwd(); () -> cd(d); end
|
||||
cd(dirname(out_path))
|
||||
try
|
||||
out = basename(out_path)
|
||||
highlight_stylesheet = get_highlight_stylesheet(MIME("text/html"), docformat.highlight_theme)
|
||||
cmd = `pandoc -f markdown+raw_html -s --mathjax=""
|
||||
$filt $citeproc $(docformat.pandoc_options)
|
||||
--template $(docformat.template_path)
|
||||
-H $(docformat.stylesheet_path)
|
||||
$(self_contained)
|
||||
-V highlight_stylesheet=$(highlight_stylesheet)
|
||||
-V weave_version=$(weave_version)
|
||||
-V weave_date=$(weave_date)
|
||||
-V weave_source=$(weave_source)
|
||||
-V headerscript=$(header_script)
|
||||
-o $(out)`
|
||||
proc = open(cmd, "r+")
|
||||
println(proc.in, rendered)
|
||||
close(proc.in)
|
||||
proc_output = read(proc.out, String)
|
||||
catch
|
||||
rethrow() # TODO: just show error content instead of rethrow the err
|
||||
finally
|
||||
cd_back()
|
||||
end
|
||||
|
||||
return out_path
|
||||
end
|
||||
|
||||
function write_doc(docformat::Pandoc2PDF, doc, rendered, out_path)
|
||||
if haskey(doc.header, "bibliography")
|
||||
filt = "--filter"
|
||||
citeproc = "pandoc-citeproc"
|
||||
else
|
||||
filt = []
|
||||
citeproc = []
|
||||
end
|
||||
|
||||
out_path = get_out_path(doc, out_path, "pdf")
|
||||
cd_back = let d = pwd(); () -> cd(d); end
|
||||
cd(dirname(out_path))
|
||||
try
|
||||
out = basename(out_path)
|
||||
cmd = `pandoc -f markdown+raw_tex -s --pdf-engine=xelatex --highlight-style=tango
|
||||
$filt $citeproc $(docformat.pandoc_options)
|
||||
--include-in-header=$(docformat.header_template)
|
||||
-o $(out)`
|
||||
proc = open(cmd, "r+")
|
||||
println(proc.in, rendered)
|
||||
close(proc.in)
|
||||
proc_output = read(proc.out, String)
|
||||
catch
|
||||
rethrow()
|
||||
finally
|
||||
cd_back()
|
||||
end
|
||||
|
||||
return out_path
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
function write_doc(doc, rendered, out_path)
|
||||
return write_doc(doc.format, doc, rendered, out_path)
|
||||
end
|
||||
|
||||
function write_doc(::WeaveFormat, doc, rendered, out_path)
|
||||
write(out_path, rendered)
|
||||
return out_path
|
||||
end
|
||||
|
||||
include("pandoc.jl")
|
||||
include("latex.jl")
|
|
@ -0,0 +1,550 @@
|
|||
<style type="text/css">
|
||||
@font-face {
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
}
|
||||
@font-face {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
}
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
table {
|
||||
font-family: monospace, monospace;
|
||||
font-size : 0.8em;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
thead th {
|
||||
border-bottom: 1px solid black;
|
||||
background-color: white;
|
||||
}
|
||||
tr:nth-child(odd){
|
||||
background-color: rgb(248,248,248);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skeleton V2.0.4
|
||||
* Copyright 2014, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 12/29/2014
|
||||
*/
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box; }
|
||||
.column,
|
||||
.columns {
|
||||
width: 100%;
|
||||
float: left;
|
||||
box-sizing: border-box; }
|
||||
@media (min-width: 400px) {
|
||||
.container {
|
||||
width: 85%;
|
||||
padding: 0; }
|
||||
}
|
||||
@media (min-width: 550px) {
|
||||
.container {
|
||||
width: 80%; }
|
||||
.column,
|
||||
.columns {
|
||||
margin-left: 4%; }
|
||||
.column:first-child,
|
||||
.columns:first-child {
|
||||
margin-left: 0; }
|
||||
|
||||
.one.column,
|
||||
.one.columns { width: 4.66666666667%; }
|
||||
.two.columns { width: 13.3333333333%; }
|
||||
.three.columns { width: 22%; }
|
||||
.four.columns { width: 30.6666666667%; }
|
||||
.five.columns { width: 39.3333333333%; }
|
||||
.six.columns { width: 48%; }
|
||||
.seven.columns { width: 56.6666666667%; }
|
||||
.eight.columns { width: 65.3333333333%; }
|
||||
.nine.columns { width: 74.0%; }
|
||||
.ten.columns { width: 82.6666666667%; }
|
||||
.eleven.columns { width: 91.3333333333%; }
|
||||
.twelve.columns { width: 100%; margin-left: 0; }
|
||||
|
||||
.one-third.column { width: 30.6666666667%; }
|
||||
.two-thirds.column { width: 65.3333333333%; }
|
||||
|
||||
.one-half.column { width: 48%; }
|
||||
|
||||
/* Offsets */
|
||||
.offset-by-one.column,
|
||||
.offset-by-one.columns { margin-left: 8.66666666667%; }
|
||||
.offset-by-two.column,
|
||||
.offset-by-two.columns { margin-left: 17.3333333333%; }
|
||||
.offset-by-three.column,
|
||||
.offset-by-three.columns { margin-left: 26%; }
|
||||
.offset-by-four.column,
|
||||
.offset-by-four.columns { margin-left: 34.6666666667%; }
|
||||
.offset-by-five.column,
|
||||
.offset-by-five.columns { margin-left: 43.3333333333%; }
|
||||
.offset-by-six.column,
|
||||
.offset-by-six.columns { margin-left: 52%; }
|
||||
.offset-by-seven.column,
|
||||
.offset-by-seven.columns { margin-left: 60.6666666667%; }
|
||||
.offset-by-eight.column,
|
||||
.offset-by-eight.columns { margin-left: 69.3333333333%; }
|
||||
.offset-by-nine.column,
|
||||
.offset-by-nine.columns { margin-left: 78.0%; }
|
||||
.offset-by-ten.column,
|
||||
.offset-by-ten.columns { margin-left: 86.6666666667%; }
|
||||
.offset-by-eleven.column,
|
||||
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
|
||||
|
||||
.offset-by-one-third.column,
|
||||
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
|
||||
.offset-by-two-thirds.column,
|
||||
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
|
||||
|
||||
.offset-by-one-half.column,
|
||||
.offset-by-one-half.columns { margin-left: 52%; }
|
||||
|
||||
}
|
||||
html {
|
||||
font-size: 62.5%; }
|
||||
body {
|
||||
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
|
||||
line-height: 1.6;
|
||||
font-weight: 400;
|
||||
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #222; }
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 2rem;
|
||||
font-weight: 300; }
|
||||
h1 { font-size: 3.6rem; line-height: 1.2; letter-spacing: -.1rem;}
|
||||
h2 { font-size: 3.4rem; line-height: 1.25; letter-spacing: -.1rem; }
|
||||
h3 { font-size: 3.2rem; line-height: 1.3; letter-spacing: -.1rem; }
|
||||
h4 { font-size: 2.8rem; line-height: 1.35; letter-spacing: -.08rem; }
|
||||
h5 { font-size: 2.4rem; line-height: 1.5; letter-spacing: -.05rem; }
|
||||
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
|
||||
|
||||
p {
|
||||
margin-top: 0; }
|
||||
a {
|
||||
color: #1EAEDB; }
|
||||
a:hover {
|
||||
color: #0FA0CE; }
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"] {
|
||||
display: inline-block;
|
||||
height: 38px;
|
||||
padding: 0 30px;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 38px;
|
||||
letter-spacing: .1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #bbb;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box; }
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
.button:focus,
|
||||
button:focus,
|
||||
input[type="submit"]:focus,
|
||||
input[type="reset"]:focus,
|
||||
input[type="button"]:focus {
|
||||
color: #333;
|
||||
border-color: #888;
|
||||
outline: 0; }
|
||||
.button.button-primary,
|
||||
button.button-primary,
|
||||
input[type="submit"].button-primary,
|
||||
input[type="reset"].button-primary,
|
||||
input[type="button"].button-primary {
|
||||
color: #FFF;
|
||||
background-color: #33C3F0;
|
||||
border-color: #33C3F0; }
|
||||
.button.button-primary:hover,
|
||||
button.button-primary:hover,
|
||||
input[type="submit"].button-primary:hover,
|
||||
input[type="reset"].button-primary:hover,
|
||||
input[type="button"].button-primary:hover,
|
||||
.button.button-primary:focus,
|
||||
button.button-primary:focus,
|
||||
input[type="submit"].button-primary:focus,
|
||||
input[type="reset"].button-primary:focus,
|
||||
input[type="button"].button-primary:focus {
|
||||
color: #FFF;
|
||||
background-color: #1EAEDB;
|
||||
border-color: #1EAEDB; }
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="text"],
|
||||
input[type="tel"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
textarea,
|
||||
select {
|
||||
height: 38px;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
background-color: #fff;
|
||||
border: 1px solid #D1D1D1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box; }
|
||||
/* Removes awkward default styles on some inputs for iOS */
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="text"],
|
||||
input[type="tel"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none; }
|
||||
textarea {
|
||||
min-height: 65px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px; }
|
||||
input[type="email"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="search"]:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="tel"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="password"]:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border: 1px solid #33C3F0;
|
||||
outline: 0; }
|
||||
label,
|
||||
legend {
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
font-weight: 600; }
|
||||
fieldset {
|
||||
padding: 0;
|
||||
border-width: 0; }
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
display: inline; }
|
||||
label > .label-body {
|
||||
display: inline-block;
|
||||
margin-left: .5rem;
|
||||
font-weight: normal; }
|
||||
ul {
|
||||
list-style: circle inside; }
|
||||
ol {
|
||||
list-style: decimal inside; }
|
||||
ol, ul {
|
||||
padding-left: 0;
|
||||
margin-top: 0; }
|
||||
ul ul,
|
||||
ul ol,
|
||||
ol ol,
|
||||
ol ul {
|
||||
margin: 1.5rem 0 1.5rem 3rem;
|
||||
font-size: 90%; }
|
||||
li {
|
||||
margin-bottom: 1rem; }
|
||||
th,
|
||||
td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #E1E1E1; }
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
padding-left: 0; }
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
padding-right: 0; }
|
||||
button,
|
||||
.button {
|
||||
margin-bottom: 1rem; }
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
fieldset {
|
||||
margin-bottom: 1.5rem; }
|
||||
pre,
|
||||
blockquote,
|
||||
dl,
|
||||
figure,
|
||||
table,
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
form {
|
||||
margin-bottom: 2.5rem; }
|
||||
.u-full-width {
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.u-max-full-width {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.u-pull-right {
|
||||
float: right; }
|
||||
.u-pull-left {
|
||||
float: left; }
|
||||
hr {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 3.5rem;
|
||||
border-width: 0;
|
||||
border-top: 1px solid #E1E1E1; }
|
||||
.container:after,
|
||||
.row:after,
|
||||
.u-cf {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both; }
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
padding: 9.5px;
|
||||
margin: 0 0 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.42857143;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
pre.sourceCode.julia {
|
||||
display: block;
|
||||
padding: 9.5px;
|
||||
margin: 0 0 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.42857143;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
pre.julia-error {
|
||||
color : red
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
code {
|
||||
background-color: #ffffff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
code.sourceCode.julia {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 400px) {}
|
||||
@media (min-width: 550px) {}
|
||||
@media (min-width: 750px) {}
|
||||
@media (min-width: 1000px) {}
|
||||
@media (min-width: 1200px) {}
|
||||
|
||||
h1.title {margin-top : 20px}
|
||||
img {max-width : 100%}
|
||||
</style>
|
|
@ -0,0 +1,538 @@
|
|||
@font-face {
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
}
|
||||
@font-face {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
}
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
table {
|
||||
font-family: monospace, monospace;
|
||||
font-size : 0.8em;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
thead th {
|
||||
border-bottom: 1px solid black;
|
||||
background-color: white;
|
||||
}
|
||||
tr:nth-child(odd){
|
||||
background-color: rgb(248,248,248);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skeleton V2.0.4
|
||||
* Copyright 2014, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 12/29/2014
|
||||
*/
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box; }
|
||||
.column,
|
||||
.columns {
|
||||
width: 100%;
|
||||
float: left;
|
||||
box-sizing: border-box; }
|
||||
@media (min-width: 400px) {
|
||||
.container {
|
||||
width: 85%;
|
||||
padding: 0; }
|
||||
}
|
||||
@media (min-width: 550px) {
|
||||
.container {
|
||||
width: 80%; }
|
||||
.column,
|
||||
.columns {
|
||||
margin-left: 4%; }
|
||||
.column:first-child,
|
||||
.columns:first-child {
|
||||
margin-left: 0; }
|
||||
|
||||
.one.column,
|
||||
.one.columns { width: 4.66666666667%; }
|
||||
.two.columns { width: 13.3333333333%; }
|
||||
.three.columns { width: 22%; }
|
||||
.four.columns { width: 30.6666666667%; }
|
||||
.five.columns { width: 39.3333333333%; }
|
||||
.six.columns { width: 48%; }
|
||||
.seven.columns { width: 56.6666666667%; }
|
||||
.eight.columns { width: 65.3333333333%; }
|
||||
.nine.columns { width: 74.0%; }
|
||||
.ten.columns { width: 82.6666666667%; }
|
||||
.eleven.columns { width: 91.3333333333%; }
|
||||
.twelve.columns { width: 100%; margin-left: 0; }
|
||||
|
||||
.one-third.column { width: 30.6666666667%; }
|
||||
.two-thirds.column { width: 65.3333333333%; }
|
||||
|
||||
.one-half.column { width: 48%; }
|
||||
|
||||
/* Offsets */
|
||||
.offset-by-one.column,
|
||||
.offset-by-one.columns { margin-left: 8.66666666667%; }
|
||||
.offset-by-two.column,
|
||||
.offset-by-two.columns { margin-left: 17.3333333333%; }
|
||||
.offset-by-three.column,
|
||||
.offset-by-three.columns { margin-left: 26%; }
|
||||
.offset-by-four.column,
|
||||
.offset-by-four.columns { margin-left: 34.6666666667%; }
|
||||
.offset-by-five.column,
|
||||
.offset-by-five.columns { margin-left: 43.3333333333%; }
|
||||
.offset-by-six.column,
|
||||
.offset-by-six.columns { margin-left: 52%; }
|
||||
.offset-by-seven.column,
|
||||
.offset-by-seven.columns { margin-left: 60.6666666667%; }
|
||||
.offset-by-eight.column,
|
||||
.offset-by-eight.columns { margin-left: 69.3333333333%; }
|
||||
.offset-by-nine.column,
|
||||
.offset-by-nine.columns { margin-left: 78.0%; }
|
||||
.offset-by-ten.column,
|
||||
.offset-by-ten.columns { margin-left: 86.6666666667%; }
|
||||
.offset-by-eleven.column,
|
||||
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
|
||||
|
||||
.offset-by-one-third.column,
|
||||
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
|
||||
.offset-by-two-thirds.column,
|
||||
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
|
||||
|
||||
.offset-by-one-half.column,
|
||||
.offset-by-one-half.columns { margin-left: 52%; }
|
||||
|
||||
}
|
||||
html {
|
||||
font-size: 62.5%; }
|
||||
body {
|
||||
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
|
||||
line-height: 1.6;
|
||||
font-weight: 400;
|
||||
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #222; }
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 2rem;
|
||||
font-weight: 300; }
|
||||
h1 { font-size: 3.6rem; line-height: 1.2; letter-spacing: -.1rem;}
|
||||
h2 { font-size: 3.4rem; line-height: 1.25; letter-spacing: -.1rem; }
|
||||
h3 { font-size: 3.2rem; line-height: 1.3; letter-spacing: -.1rem; }
|
||||
h4 { font-size: 2.8rem; line-height: 1.35; letter-spacing: -.08rem; }
|
||||
h5 { font-size: 2.4rem; line-height: 1.5; letter-spacing: -.05rem; }
|
||||
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
|
||||
|
||||
p {
|
||||
margin-top: 0; }
|
||||
a {
|
||||
color: #1EAEDB; }
|
||||
a:hover {
|
||||
color: #0FA0CE; }
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"] {
|
||||
display: inline-block;
|
||||
height: 38px;
|
||||
padding: 0 30px;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 38px;
|
||||
letter-spacing: .1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #bbb;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box; }
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
.button:focus,
|
||||
button:focus,
|
||||
input[type="submit"]:focus,
|
||||
input[type="reset"]:focus,
|
||||
input[type="button"]:focus {
|
||||
color: #333;
|
||||
border-color: #888;
|
||||
outline: 0; }
|
||||
.button.button-primary,
|
||||
button.button-primary,
|
||||
input[type="submit"].button-primary,
|
||||
input[type="reset"].button-primary,
|
||||
input[type="button"].button-primary {
|
||||
color: #FFF;
|
||||
background-color: #33C3F0;
|
||||
border-color: #33C3F0; }
|
||||
.button.button-primary:hover,
|
||||
button.button-primary:hover,
|
||||
input[type="submit"].button-primary:hover,
|
||||
input[type="reset"].button-primary:hover,
|
||||
input[type="button"].button-primary:hover,
|
||||
.button.button-primary:focus,
|
||||
button.button-primary:focus,
|
||||
input[type="submit"].button-primary:focus,
|
||||
input[type="reset"].button-primary:focus,
|
||||
input[type="button"].button-primary:focus {
|
||||
color: #FFF;
|
||||
background-color: #1EAEDB;
|
||||
border-color: #1EAEDB; }
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="text"],
|
||||
input[type="tel"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
textarea,
|
||||
select {
|
||||
height: 38px;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
background-color: #fff;
|
||||
border: 1px solid #D1D1D1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box; }
|
||||
/* Removes awkward default styles on some inputs for iOS */
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="text"],
|
||||
input[type="tel"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none; }
|
||||
textarea {
|
||||
min-height: 65px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px; }
|
||||
input[type="email"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="search"]:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="tel"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="password"]:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border: 1px solid #33C3F0;
|
||||
outline: 0; }
|
||||
label,
|
||||
legend {
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
font-weight: 600; }
|
||||
fieldset {
|
||||
padding: 0;
|
||||
border-width: 0; }
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
display: inline; }
|
||||
label > .label-body {
|
||||
display: inline-block;
|
||||
margin-left: .5rem;
|
||||
font-weight: normal; }
|
||||
ul {
|
||||
list-style: circle; }
|
||||
ol {
|
||||
list-style: decimal; }
|
||||
ul ul,
|
||||
ul ol,
|
||||
ol ol,
|
||||
ol ul {
|
||||
margin: 1.5rem 0 1.5rem 3rem;
|
||||
font-size: 90%; }
|
||||
li > p {margin : 0;}
|
||||
th,
|
||||
td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #E1E1E1; }
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
padding-left: 0; }
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
padding-right: 0; }
|
||||
button,
|
||||
.button {
|
||||
margin-bottom: 1rem; }
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
fieldset {
|
||||
margin-bottom: 1.5rem; }
|
||||
pre,
|
||||
blockquote,
|
||||
dl,
|
||||
figure,
|
||||
table,
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
form {
|
||||
margin-bottom: 1.0rem; }
|
||||
.u-full-width {
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.u-max-full-width {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.u-pull-right {
|
||||
float: right; }
|
||||
.u-pull-left {
|
||||
float: left; }
|
||||
hr {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 3.5rem;
|
||||
border-width: 0;
|
||||
border-top: 1px solid #E1E1E1; }
|
||||
.container:after,
|
||||
.row:after,
|
||||
.u-cf {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both; }
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
padding: 9.5px;
|
||||
margin: 0 0 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.42857143;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
pre.hljl {
|
||||
margin: 0 0 10px;
|
||||
display: block;
|
||||
background: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
padding : 5px;
|
||||
}
|
||||
|
||||
pre.output {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
pre.code {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
pre.julia-error {
|
||||
color : red
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 400px) {}
|
||||
@media (min-width: 550px) {}
|
||||
@media (min-width: 750px) {}
|
||||
@media (min-width: 1000px) {}
|
||||
@media (min-width: 1200px) {}
|
||||
|
||||
h1.title {margin-top : 20px}
|
||||
img {max-width : 100%}
|
||||
div.title {text-align: center;}
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<HTML lang = "en">
|
||||
<HEAD>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
{{#:title}}<title>{{:title}}</title>{{/:title}}
|
||||
{{{ :header_script }}}
|
||||
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({
|
||||
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]},
|
||||
TeX: { equationNumbers: { autoNumber: "AMS" } }
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
|
||||
</script>
|
||||
|
||||
{{{ :highlight_stylesheet }}}
|
||||
|
||||
<style type="text/css">
|
||||
{{{ :stylesheet }}}
|
||||
</style>
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
<div class ="container">
|
||||
<div class = "row">
|
||||
<div class = "col-md-12 twelve columns">
|
||||
<div class="title">
|
||||
{{#:title}}<h1 class="title">{{:title}}</h1>{{/:title}}
|
||||
{{#:author}}<h5>{{{:author}}}</h5>{{/:author}}
|
||||
{{#:date}}<h5>{{{:date}}}</h5>{{/:date}}
|
||||
</div>
|
||||
|
||||
{{{ :body }}}
|
||||
|
||||
<HR/>
|
||||
<div class="footer">
|
||||
<p>
|
||||
Published from <a href="{{{:weave_source}}}">{{{:weave_source}}}</a>
|
||||
using <a href="http://github.com/JunoLab/Weave.jl">Weave.jl</a> {{:weave_version}} on {{:weave_date}}.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
|
@ -0,0 +1,45 @@
|
|||
\documentclass[12pt,a4paper]{article}
|
||||
|
||||
\usepackage[a4paper,text={16.5cm,25.2cm},centering]{geometry}
|
||||
\usepackage{lmodern}
|
||||
\usepackage{amssymb,amsmath}
|
||||
\usepackage{bm}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{microtype}
|
||||
\usepackage{hyperref}
|
||||
{{#:tex_deps}}
|
||||
{{{ :tex_deps }}}
|
||||
{{/:tex_deps}}
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{1.2ex}
|
||||
|
||||
\hypersetup
|
||||
{ pdfauthor = { {{{:author}}} },
|
||||
pdftitle={ {{{:title}}} },
|
||||
colorlinks=TRUE,
|
||||
linkcolor=black,
|
||||
citecolor=blue,
|
||||
urlcolor=blue
|
||||
}
|
||||
|
||||
{{#:title}}
|
||||
\title{ {{{ :title }}} }
|
||||
{{/:title}}
|
||||
|
||||
{{#:author}}
|
||||
\author{ {{{ :author }}} }
|
||||
{{/:author}}
|
||||
|
||||
{{#:date}}
|
||||
\date{ {{{ :date }}} }
|
||||
{{/:date}}
|
||||
|
||||
{{ :highlight }}
|
||||
|
||||
\begin{document}
|
||||
|
||||
{{#:title}}\maketitle{{/:title}}
|
||||
|
||||
{{{ :body }}}
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,96 @@
|
|||
<!DOCTYPE html>
|
||||
<html$if(lang)$ lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="pandoc">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
$for(author-meta)$
|
||||
<meta name="author" content="$author-meta$">
|
||||
$endfor$
|
||||
$if(date-meta)$
|
||||
<meta name="dcterms.date" content="$date-meta$">
|
||||
$endif$
|
||||
$if(keywords)$
|
||||
<meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$">
|
||||
$endif$
|
||||
<title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>
|
||||
|
||||
<!-- TODO check if math works with plotly -->
|
||||
<!-- Need to load plotly before Mathjax or pandoc equations don't work -->
|
||||
$headerscript$
|
||||
|
||||
$if(math)$
|
||||
<script type="text/javascript">
|
||||
var fileref=document.createElement('script')
|
||||
fileref.setAttribute("type","text/javascript")
|
||||
fileref.setAttribute("src", "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML")
|
||||
document.getElementsByTagName("head")[0].appendChild(fileref)
|
||||
</script>
|
||||
$endif$
|
||||
|
||||
$for(header-includes)$
|
||||
$header-includes$
|
||||
$endfor$
|
||||
|
||||
$highlight_stylesheet$
|
||||
|
||||
$if(highlighting-css)$
|
||||
<style type="text/css">
|
||||
$highlighting-css$
|
||||
</style>
|
||||
$endif$
|
||||
|
||||
$for(css)$
|
||||
<link rel="stylesheet" href="$css$">
|
||||
$endfor$
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class ="container">
|
||||
<div class = "row">
|
||||
<div class = "col-md-12 twelve columns">
|
||||
|
||||
$for(include-before)$
|
||||
$include-before$
|
||||
$endfor$
|
||||
|
||||
$if(title)$
|
||||
|
||||
<h1 class="title">$title$</h1>
|
||||
$if(subtitle)$
|
||||
<h1 class="subtitle">$subtitle$</h1>
|
||||
$endif$
|
||||
|
||||
<p><strong>Author:</strong>
|
||||
$for(author)$
|
||||
$author$
|
||||
$endfor$
|
||||
<br/>
|
||||
|
||||
$if(date)$
|
||||
<strong>Date: </strong>$date$
|
||||
$endif$
|
||||
</p>
|
||||
$endif$
|
||||
|
||||
$if(toc)$
|
||||
<nav id="$idprefix$TOC">
|
||||
$toc$
|
||||
</nav>
|
||||
$endif$
|
||||
$body$
|
||||
$for(include-after)$
|
||||
$include-after$
|
||||
$endfor$
|
||||
|
||||
<HR/>
|
||||
<div class="footer"><p>
|
||||
Published from <a href="$source$">$source$</a> using
|
||||
<a href="http://github.com/mpastell/Weave.jl">Weave.jl</a> $weave_version$ on $weave_date$.
|
||||
<p></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
\usepackage[a4paper,text={16.5cm,25.2cm},centering]{geometry}
|
|
@ -1,5 +0,0 @@
|
|||
julia 0.3
|
||||
Cairo
|
||||
Gadfly
|
||||
Winston
|
||||
PyPlot
|
|
@ -0,0 +1,28 @@
|
|||
# Test if running document with and without cache works
|
||||
isdir("documents/cache") && rm("documents/cache", recursive = true)
|
||||
weave("documents/chunk_options.noweb", cache=:all)
|
||||
result = read("documents/chunk_options.md", String)
|
||||
rm("documents/chunk_options.md")
|
||||
weave("documents/chunk_options.noweb", cache=:all)
|
||||
cached_result = read("documents/chunk_options.md", String)
|
||||
@test result == cached_result
|
||||
|
||||
# cache = :user
|
||||
isdir("documents/cache") && rm("documents/cache", recursive = true)
|
||||
out = "documents/chunk_cache.md"
|
||||
Weave.weave("documents/chunk_cache.noweb", cache=:user);
|
||||
result = read(out, String)
|
||||
rm(out)
|
||||
Weave.weave("documents/chunk_cache.noweb", cache=:user);
|
||||
cached_result = read(out, String)
|
||||
@test result == cached_result
|
||||
|
||||
# cache = :all
|
||||
isdir("documents/cache") && rm("documents/cache", recursive = true)
|
||||
out = "documents/chunk_cache.md"
|
||||
Weave.weave("documents/chunk_cache.noweb", cache=:all);
|
||||
result = read(out, String)
|
||||
rm(out)
|
||||
Weave.weave("documents/chunk_cache.noweb", cache=:all);
|
||||
cached_result = read(out, String)
|
||||
@test result == cached_result
|
|
@ -1,28 +0,0 @@
|
|||
using Weave
|
||||
using Base.Test
|
||||
|
||||
#Test chunk options and output formats
|
||||
weave("documents/chunk_options.noweb", plotlib=nothing)
|
||||
result = readall(open("documents/chunk_options.md"))
|
||||
ref = readall(open("documents/chunk_options_ref.md"))
|
||||
@test result == ref
|
||||
|
||||
weave("documents/chunk_options.noweb", doctype="tex", plotlib=nothing)
|
||||
result = readall(open("documents/chunk_options.tex"))
|
||||
ref = readall(open("documents/chunk_options_ref.tex"))
|
||||
@test result == ref
|
||||
|
||||
weave("documents/chunk_options.noweb", doctype="texminted", plotlib=nothing)
|
||||
result = readall(open("documents/chunk_options.tex"))
|
||||
ref = readall(open("documents/chunk_options_ref.texminted"))
|
||||
@test result == ref
|
||||
|
||||
weave("documents/chunk_options.noweb", doctype="rst", plotlib=nothing)
|
||||
result = readall(open("documents/chunk_options.rst"))
|
||||
ref = readall(open("documents/chunk_options_ref.rst"))
|
||||
@test result == ref
|
||||
|
||||
tangle("documents/chunk_options.noweb")
|
||||
result = readall(open("documents/chunk_options.jl"))
|
||||
ref = readall(open("documents/chunk_options_ref.jl"))
|
||||
@test result == ref
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
<<term=true>>=
|
||||
y= [2, 5, 12]
|
||||
@
|
||||
|
||||
Some text `j print(10)` and continues with another inline code `j y`.
|
||||
|
||||
<<term=true; cache=true>>=
|
||||
y= [2, 5, 12]
|
||||
@
|
||||
|
||||
|
||||
<<>>=
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
@
|
||||
|
||||
<<cache=true>>=
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
@
|
||||
|
||||
<<>>=
|
||||
y = 1:5
|
||||
println(y)
|
||||
@
|
||||
|
||||
`j y`
|
||||
|
||||
<<cache=true>>=
|
||||
y = 1:5
|
||||
println(y)
|
||||
@
|
||||
|
||||
Some text in the end
|
|
@ -0,0 +1,179 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"y= [2, 5, 12]"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"x = [12, 10]\nprintln(y)\nprintln(x)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(\"Results without code\")\nprintln(x)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"y = randn(5)\nprintln(\"Don't eval, but show code\")"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"y = 1:5\nprintln(y)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"a = \"Don't print me\"\nprintln(a)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(\"No markup for results.\")"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Test wrapping:"
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(collect(0:10:1000))"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(collect(0:10:1000))"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
""
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(collect(0:10:1000))"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
}
|
||||
],
|
||||
"nbformat_minor": 2,
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"file_extension": ".jl",
|
||||
"mimetype": "application/julia",
|
||||
"name": "julia",
|
||||
"version": "0.5.0"
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "julia-0.5",
|
||||
"display_name": "Julia 0.5.0",
|
||||
"language": "julia"
|
||||
}
|
||||
},
|
||||
"nbformat": 4
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
#+ term=true
|
||||
|
||||
y= [2, 5, 12]
|
||||
|
||||
|
||||
#+ term=true
|
||||
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
|
||||
|
||||
#+
|
||||
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
|
||||
|
||||
#+ echo=false
|
||||
|
||||
println("Results without code")
|
||||
println(x)
|
||||
|
||||
|
||||
#+ eval=false; tangle=false
|
||||
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
|
||||
|
||||
#+
|
||||
|
||||
y = 1:5
|
||||
println(y)
|
||||
|
||||
|
||||
#+ results="hidden"
|
||||
|
||||
a = "Don't print me"
|
||||
println(a)
|
||||
|
||||
|
||||
#+ results="as_is"
|
||||
|
||||
println("No markup for results.")
|
||||
|
||||
#'
|
||||
#'
|
||||
#' Test wrapping:
|
||||
#'
|
||||
#+
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
#+ wrap=false
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
#+ line_width=60
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
|
@ -3,6 +3,12 @@
|
|||
y= [2, 5, 12]
|
||||
@
|
||||
|
||||
<<term=true>>=
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
@
|
||||
|
||||
<<>>=
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
|
@ -16,7 +22,7 @@ println(x)
|
|||
@
|
||||
|
||||
|
||||
<<eval=false>>=
|
||||
<<eval=false; tangle=false>>=
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
@
|
||||
|
@ -35,3 +41,17 @@ println(a)
|
|||
<<results="as_is">>=
|
||||
println("No markup for results.")
|
||||
@
|
||||
|
||||
Test wrapping:
|
||||
|
||||
<<>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
||||
<<wrap=false>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
||||
<<line_width=60>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
|
|
@ -8,9 +8,6 @@ println(x)
|
|||
println("Results without code")
|
||||
println(x)
|
||||
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
|
||||
y = 1:5
|
||||
println(y)
|
||||
|
||||
|
@ -18,3 +15,9 @@ a = "Don't print me"
|
|||
println(a)
|
||||
|
||||
println("No markup for results.")
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
~~~~{.julia}
|
||||
julia> y= [2, 5, 12]
|
||||
3-element Array{Int64,1}:
|
||||
|
@ -11,55 +9,75 @@ julia> y= [2, 5, 12]
|
|||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
julia> x = 1:10
|
||||
1:10
|
||||
|
||||
julia> d = Dict("Weave" => "testing")
|
||||
Dict{String,String} with 1 entry:
|
||||
"Weave" => "testing"
|
||||
|
||||
julia> y = [2, 4 ,8]
|
||||
3-element Array{Int64,1}:
|
||||
2
|
||||
4
|
||||
8
|
||||
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~
|
||||
[2, 4, 8]
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
println(x)
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
[2,5,12]
|
||||
[12,10]
|
||||
~~~~~~~~~~~~~
|
||||
~~~~
|
||||
[12, 10]
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
~~~~
|
||||
Results without code
|
||||
[12,10]
|
||||
~~~~~~~~~~~~~
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
~~~~
|
||||
[12, 10]
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
y = 1:5
|
||||
println(y)
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
~~~~
|
||||
1:5
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
|
@ -70,13 +88,61 @@ println(a)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
println("No markup for results.")
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
No markup for results.
|
||||
|
||||
|
||||
|
||||
|
||||
Test wrapping:
|
||||
|
||||
~~~~{.julia}
|
||||
println(collect(0:10:1000))
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~
|
||||
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160,
|
||||
170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310,
|
||||
320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460,
|
||||
470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610,
|
||||
620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760,
|
||||
770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910,
|
||||
920, 930, 940, 950, 960, 970, 980, 990, 1000]
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
println(collect(0:10:1000))
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~
|
||||
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970, 980, 990, 1000]
|
||||
~~~~
|
||||
|
||||
|
||||
|
||||
~~~~{.julia}
|
||||
println(collect(0:10:1000))
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
~~~~
|
||||
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130,
|
||||
140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250,
|
||||
260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370,
|
||||
380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490,
|
||||
500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610,
|
||||
620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730,
|
||||
740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850,
|
||||
860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970,
|
||||
980, 990, 1000]
|
||||
~~~~
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
|
||||
|
||||
.. code-block:: julia
|
||||
|
||||
julia> y= [2, 5, 12]
|
||||
3-element Array{Int64,1}:
|
||||
2
|
||||
5
|
||||
12
|
||||
|
||||
julia> y= [2, 5, 12]
|
||||
3-element Array{Int64,1}:
|
||||
2
|
||||
5
|
||||
12
|
||||
|
||||
|
||||
|
||||
|
@ -18,13 +16,25 @@
|
|||
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
[2,5,12]
|
||||
|
||||
|
||||
|
||||
|
||||
.. code-block:: julia
|
||||
|
||||
println(x)
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
[12,10]
|
||||
|
||||
|
||||
|
@ -36,6 +46,12 @@
|
|||
::
|
||||
|
||||
Results without code
|
||||
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
[12,10]
|
||||
|
||||
|
||||
|
@ -86,6 +102,63 @@
|
|||
|
||||
|
||||
|
||||
|
||||
No markup for results.
|
||||
|
||||
|
||||
|
||||
|
||||
Test wrapping:
|
||||
|
||||
.. code-block:: julia
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,2
|
||||
10,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,
|
||||
400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580
|
||||
,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
|
||||
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,9
|
||||
60,970,980,990,1000]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.. code-block:: julia
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
|
||||
::
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,1000]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.. code-block:: julia
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,17
|
||||
0,180,190,200,210,220,230,240,250,260,270,280,290,300,310,32
|
||||
0,330,340,350,360,370,380,390,400,410,420,430,440,450,460,47
|
||||
0,480,490,500,510,520,530,540,550,560,570,580,590,600,610,62
|
||||
0,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
|
||||
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,92
|
||||
0,930,940,950,960,970,980,990,1000]
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
|
||||
|
||||
\begin{juliaterm}
|
||||
julia> y= [2, 5, 12]
|
||||
3-element Array{Int64,1}:
|
||||
2
|
||||
5
|
||||
12
|
||||
|
||||
\end{juliaterm}
|
||||
|
||||
|
||||
|
@ -14,10 +12,16 @@ julia> y= [2, 5, 12]
|
|||
\begin{juliacode}
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
|
||||
\end{juliacode}
|
||||
\begin{juliaout}
|
||||
[2,5,12]
|
||||
\end{juliaout}
|
||||
|
||||
\begin{juliacode}
|
||||
println(x)
|
||||
\end{juliacode}
|
||||
\begin{juliaout}
|
||||
[12,10]
|
||||
\end{juliaout}
|
||||
|
||||
|
@ -26,6 +30,9 @@ println(x)
|
|||
|
||||
\begin{juliaout}
|
||||
Results without code
|
||||
\end{juliaout}
|
||||
|
||||
\begin{juliaout}
|
||||
[12,10]
|
||||
\end{juliaout}
|
||||
|
||||
|
@ -59,6 +66,45 @@ println(a)
|
|||
\begin{juliacode}
|
||||
println("No markup for results.")
|
||||
\end{juliacode}
|
||||
|
||||
No markup for results.
|
||||
|
||||
|
||||
|
||||
|
||||
Test wrapping:
|
||||
|
||||
\begin{juliacode}
|
||||
println(collect(0:10:1000))
|
||||
\end{juliacode}
|
||||
\begin{juliaout}
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,2
|
||||
10,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,
|
||||
400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580
|
||||
,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
|
||||
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,9
|
||||
60,970,980,990,1000]
|
||||
\end{juliaout}
|
||||
|
||||
|
||||
|
||||
\begin{juliacode}
|
||||
println(collect(0:10:1000))
|
||||
\end{juliacode}
|
||||
\begin{juliaout}[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,1000]
|
||||
|
||||
\end{juliaout}
|
||||
|
||||
|
||||
|
||||
\begin{juliacode}
|
||||
println(collect(0:10:1000))
|
||||
\end{juliacode}
|
||||
\begin{juliaout}
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,17
|
||||
0,180,190,200,210,220,230,240,250,260,270,280,290,300,310,32
|
||||
0,330,340,350,360,370,380,390,400,410,420,430,440,450,460,47
|
||||
0,480,490,500,510,520,530,540,550,560,570,580,590,600,610,62
|
||||
0,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
|
||||
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,92
|
||||
0,930,940,950,960,970,980,990,1000]
|
||||
\end{juliaout}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
|
||||
|
||||
\begin{minted}[fontsize=\footnotesize, xleftmargin=0.5em, mathescape]{julia}
|
||||
julia> y= [2, 5, 12]
|
||||
3-element Array{Int64,1}:
|
||||
2
|
||||
5
|
||||
12
|
||||
|
||||
\end{minted}
|
||||
|
||||
|
||||
|
@ -14,10 +12,16 @@ julia> y= [2, 5, 12]
|
|||
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
|
||||
\end{minted}
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
|
||||
[2,5,12]
|
||||
\end{minted}
|
||||
|
||||
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
|
||||
println(x)
|
||||
\end{minted}
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
|
||||
[12,10]
|
||||
\end{minted}
|
||||
|
||||
|
@ -26,6 +30,9 @@ println(x)
|
|||
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
|
||||
Results without code
|
||||
\end{minted}
|
||||
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
|
||||
[12,10]
|
||||
\end{minted}
|
||||
|
||||
|
@ -59,6 +66,45 @@ println(a)
|
|||
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
|
||||
println("No markup for results.")
|
||||
\end{minted}
|
||||
|
||||
No markup for results.
|
||||
|
||||
|
||||
|
||||
|
||||
Test wrapping:
|
||||
|
||||
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
|
||||
println(collect(0:10:1000))
|
||||
\end{minted}
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,2
|
||||
10,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,
|
||||
400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580
|
||||
,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
|
||||
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,9
|
||||
60,970,980,990,1000]
|
||||
\end{minted}
|
||||
|
||||
|
||||
|
||||
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
|
||||
println(collect(0:10:1000))
|
||||
\end{minted}
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,1000]
|
||||
|
||||
\end{minted}
|
||||
|
||||
|
||||
|
||||
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
|
||||
println(collect(0:10:1000))
|
||||
\end{minted}
|
||||
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
|
||||
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,17
|
||||
0,180,190,200,210,220,230,240,250,260,270,280,290,300,310,32
|
||||
0,330,340,350,360,370,380,390,400,410,420,430,440,450,460,47
|
||||
0,480,490,500,510,520,530,540,550,560,570,580,590,600,610,62
|
||||
0,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
|
||||
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,92
|
||||
0,930,940,950,960,970,980,990,1000]
|
||||
\end{minted}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"y= [2, 5, 12]"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"x = 1:10\nd = Dict(\"Weave\" => \"testing\")\ny = [2, 4 ,8]"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"x = [12, 10]\nprintln(y)\nprintln(x)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(\"Results without code\")\nprintln(x)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"y = randn(5)\nprintln(\"Don't eval, but show code\")"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"y = 1:5\nprintln(y)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"a = \"Don't print me\"\nprintln(a)"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(\"No markup for results.\")"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Test wrapping:"
|
||||
],
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(collect(0:10:1000))"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(collect(0:10:1000))"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"outputs": [],
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"println(collect(0:10:1000))"
|
||||
],
|
||||
"metadata": {},
|
||||
"execution_count": null
|
||||
}
|
||||
],
|
||||
"nbformat_minor": 2,
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"file_extension": ".jl",
|
||||
"mimetype": "application/julia",
|
||||
"name": "julia",
|
||||
"version": "0.5.0"
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "julia-0.5",
|
||||
"display_name": "Julia 0.5.0",
|
||||
"language": "julia"
|
||||
}
|
||||
},
|
||||
"nbformat": 4
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
#+ term=true
|
||||
|
||||
y= [2, 5, 12]
|
||||
|
||||
|
||||
#+ term=true
|
||||
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
|
||||
|
||||
#+
|
||||
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
|
||||
|
||||
#+ echo=false
|
||||
|
||||
println("Results without code")
|
||||
println(x)
|
||||
|
||||
|
||||
#+ eval=false; tangle=false
|
||||
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
|
||||
|
||||
#+
|
||||
|
||||
y = 1:5
|
||||
println(y)
|
||||
|
||||
|
||||
#+ results="hidden"
|
||||
|
||||
a = "Don't print me"
|
||||
println(a)
|
||||
|
||||
|
||||
#+ results="as_is"
|
||||
|
||||
println("No markup for results.")
|
||||
|
||||
#'
|
||||
#'
|
||||
#' Test wrapping:
|
||||
#'
|
||||
#+
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
#+ wrap=false
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
||||
|
||||
#+ line_width=60
|
||||
|
||||
println(collect(0:10:1000))
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
```julia;term=true
|
||||
y= [2, 5, 12]
|
||||
```
|
||||
|
||||
```julia;term=true
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
```
|
||||
|
||||
```julia
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
```
|
||||
|
||||
```julia;echo=false
|
||||
println("Results without code")
|
||||
println(x)
|
||||
```
|
||||
|
||||
```julia;eval=false; tangle=false
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
```
|
||||
|
||||
```julia
|
||||
y = 1:5
|
||||
println(y)
|
||||
```
|
||||
|
||||
```julia;results="hidden"
|
||||
a = "Don't print me"
|
||||
println(a)
|
||||
```
|
||||
|
||||
```julia;results="as_is"
|
||||
println("No markup for results.")
|
||||
```
|
||||
|
||||
|
||||
Test wrapping:
|
||||
|
||||
```julia
|
||||
println(collect(0:10:1000))
|
||||
```
|
||||
|
||||
```julia;wrap=false
|
||||
println(collect(0:10:1000))
|
||||
```
|
||||
|
||||
```julia;line_width=60
|
||||
println(collect(0:10:1000))
|
||||
```
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
<<term=true>>=
|
||||
y= [2, 5, 12]
|
||||
@
|
||||
|
||||
<<term=true>>=
|
||||
x = 1:10
|
||||
d = Dict("Weave" => "testing")
|
||||
y = [2, 4 ,8]
|
||||
@
|
||||
|
||||
<<>>=
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
@
|
||||
|
||||
<<echo=false>>=
|
||||
println("Results without code")
|
||||
println(x)
|
||||
@
|
||||
|
||||
<<eval=false; tangle=false>>=
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
@
|
||||
|
||||
<<>>=
|
||||
y = 1:5
|
||||
println(y)
|
||||
@
|
||||
|
||||
<<results="hidden">>=
|
||||
a = "Don't print me"
|
||||
println(a)
|
||||
@
|
||||
|
||||
<<results="as_is">>=
|
||||
println("No markup for results.")
|
||||
@
|
||||
|
||||
|
||||
Test wrapping:
|
||||
|
||||
<<>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
||||
<<wrap=false>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
||||
<<line_width=60>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
|
||||
|
||||
<<>>=
|
||||
y= [2, 5, 12]
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
x = [12, 10]
|
||||
println(y)
|
||||
println(x)
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
println("Results without code")
|
||||
println(x)
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
y = randn(5)
|
||||
println("Don't eval, but show code")
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
y = 1:5
|
||||
println(y)
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
a = "Don't print me"
|
||||
println(a)
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
println("No markup for results.")
|
||||
@
|
||||
|
||||
Test wrapping:
|
||||
|
||||
<<>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
||||
|
||||
|
||||
|
||||
<<>>=
|
||||
println(collect(0:10:1000))
|
||||
@
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
|
||||
<<fig_cap="sin(x) function."; label="sin_fun"; fig_pos="ht">>=
|
||||
using Gadfly
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
@
|
||||
|
||||
<<echo=false; fig_cap="cos(x) function."; dpi=200>>=
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
@
|
||||
|
||||
<<echo=false; label="cos2_fun">>=
|
||||
plot(x=x, y = cos(2x), Geom.line)
|
||||
@
|
||||
|
||||
<<term=true;fig_width=5>>=
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
y = 20
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
@
|
||||
|
||||
<<out_width="15cm">>=
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
y = 20
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
@
|
|
@ -1,80 +0,0 @@
|
|||
|
||||
|
||||
|
||||
````julia
|
||||
using Gadfly
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
````
|
||||
|
||||
|
||||
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.js.svg)
|
||||
|
||||
|
||||
|
||||
![cos(x) function.](figures/gadfly_formats_test_2_1.js.svg)
|
||||
|
||||
|
||||
|
||||
![](figures/gadfly_formats_test_cos2_fun_1.js.svg)
|
||||
|
||||
|
||||
|
||||
````julia
|
||||
julia> x = linspace(0, 2π, 200)
|
||||
200-element Array{Float64,1}:
|
||||
0.0
|
||||
0.0315738
|
||||
0.0631476
|
||||
0.0947214
|
||||
0.126295
|
||||
0.157869
|
||||
0.189443
|
||||
0.221017
|
||||
0.25259
|
||||
0.284164
|
||||
⋮
|
||||
6.03059
|
||||
6.06217
|
||||
6.09374
|
||||
6.12532
|
||||
6.15689
|
||||
6.18846
|
||||
6.22004
|
||||
6.25161
|
||||
6.28319
|
||||
|
||||
julia> plot(x=x, y = sin(x), Geom.line)
|
||||
|
||||
````
|
||||
|
||||
|
||||
![](figures/gadfly_formats_test_4_1.js.svg)
|
||||
|
||||
|
||||
````julia
|
||||
julia> y = 20
|
||||
20
|
||||
|
||||
julia> plot(x=x, y = cos(x), Geom.line)
|
||||
|
||||
````
|
||||
|
||||
|
||||
![](figures/gadfly_formats_test_4_2.js.svg)
|
||||
|
||||
|
||||
|
||||
|
||||
````julia
|
||||
x = linspace(0, 2π, 200)
|
||||
plot(x=x, y = sin(x), Geom.line)
|
||||
y = 20
|
||||
plot(x=x, y = cos(x), Geom.line)
|
||||
````
|
||||
|
||||
|
||||
![](figures/gadfly_formats_test_5_1.js.svg)
|
||||
![](figures/gadfly_formats_test_5_2.js.svg)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue