├── LICENSE ├── Makefile ├── README.md ├── alltests.md └── src ├── main.c ├── pdf.c └── pdf.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, John MacFarlane 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CCFLAGS = -g 2 | UNAME_S := $(shell uname -s) 3 | ifeq ($(UNAME_S),Linux) 4 | CCFLAGS += -D _LINUX 5 | endif 6 | ifeq ($(UNAME_S),Darwin) 7 | CCFLAGS += -D _OSX 8 | endif 9 | 10 | .PHONY: all clean leakcheck 11 | 12 | all: cmarkpdf 13 | 14 | %.o: src/%.c 15 | $(CC) -Wall -c $< -o $@ $(CCFLAGS) 16 | 17 | cmarkpdf: main.o pdf.o 18 | $(CC) $^ -o $@ $(CCFLAGS) -lhpdf -lcmark 19 | 20 | leakcheck: 21 | valgrind -q --leak-check=full --dsymutil=yes --error-exitcode=1 ./cmarkpdf -o leakcheck.pdf alltests.md 22 | 23 | clean: 24 | -rm *.o cmarkpdf 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cmarkpdf 2 | ======== 3 | 4 | This is an experimental native PDF renderer for 5 | [cmark](https://github.com/jgm/cmark), using 6 | [libharu](https://github.com/libharu/libharu). 7 | 8 | It links dynamically against both libcmark and 9 | libhpdf (libharu), which must be installed. 10 | A recent version of libhpdf that supports UTF-8 11 | encoding is needed. 12 | 13 | To build on Linux or OSX, `make`. 14 | 15 | To use: 16 | 17 | ./cmarkpdf --smart -o output.pdf input.txt 18 | 19 | Note that for now, paths to fonts are hardcoded in `src/pdf.c` 20 | and may need to be adjusted if your system puts fonts 21 | in a different place or has different fonts. 22 | 23 | Roadmap 24 | ------- 25 | 26 | - [x] Line wrapping and justification, using greedy 27 | algorithm. (In the future we might explore using 28 | Knuth-Prass.) 29 | - [x] List items (currently all treated as bulleted). 30 | - [x] Bullet lists should use different bullets at different 31 | indent level. 32 | - [x] Proper list markers for ordered lists 33 | - [x] Code spans 34 | - [x] Code blocks 35 | - [x] Block quotes 36 | - [x] Hrules 37 | - [x] Headers 38 | - [x] Strong 39 | - [x] Emph 40 | - [x] Links 41 | - [ ] Images: support jpeg too 42 | - [ ] Adjust vert space before rendering line so images get right 43 | space 44 | - [ ] Better error handling (check status of every function) 45 | - [ ] Customizability (e.g. selecting fonts, margins, sizes) 46 | - [ ] Ensure that PDF is searchable and copy-pasteable. 47 | Currently the PDFs work well is some viewers (e.g. Chrome's or 48 | Adobe Reader) but not in others. In Ubuntu Evince the text is not 49 | selectable. In OSX Mavericks Preview, the text can be selected 50 | and copied, but it is garbled when pasted. See 51 | https://groups.google.com/forum/#!searchin/libharu/copy$20paste/libharu/YzXoH_K3OAI/YNCsn6XXF-gJ, 52 | http://superuser.com/questions/137824/pdf-has-garbled-text-when-copy-pasting, 53 | and comments in the code. 54 | -------------------------------------------------------------------------------- /alltests.md: -------------------------------------------------------------------------------- 1 | foo baz bim 2 | 3 | foo baz bim 4 | 5 | a a 6 | ὐ a 7 | 8 | - foo 9 | 10 | bar 11 | 12 | > foo bar 13 | 14 | - `one 15 | - two` 16 | 17 | *** 18 | --- 19 | ___ 20 | 21 | +++ 22 | 23 | === 24 | 25 | -- 26 | ** 27 | __ 28 | 29 | *** 30 | *** 31 | *** 32 | 33 | *** 34 | 35 | Foo 36 | *** 37 | 38 | _____________________________________ 39 | 40 | - - - 41 | 42 | ** * ** * ** * ** 43 | 44 | - - - - 45 | 46 | - - - - 47 | 48 | _ _ _ _ a 49 | 50 | a------ 51 | 52 | ---a--- 53 | 54 | *-* 55 | 56 | - foo 57 | *** 58 | - bar 59 | 60 | Foo 61 | *** 62 | bar 63 | 64 | Foo 65 | --- 66 | bar 67 | 68 | * Foo 69 | * * * 70 | * Bar 71 | 72 | - Foo 73 | - * * * 74 | 75 | # foo 76 | ## foo 77 | ### foo 78 | #### foo 79 | ##### foo 80 | ###### foo 81 | 82 | ####### foo 83 | 84 | #5 bolt 85 | 86 | #foobar 87 | 88 | \## foo 89 | 90 | # foo *bar* \*baz\* 91 | 92 | # foo 93 | 94 | ### foo 95 | ## foo 96 | # foo 97 | 98 | # foo 99 | 100 | foo 101 | # bar 102 | 103 | ## foo ## 104 | ### bar ### 105 | 106 | # foo ################################## 107 | ##### foo ## 108 | 109 | ### foo ### 110 | 111 | ### foo ### b 112 | 113 | # foo# 114 | 115 | ### foo \### 116 | ## foo #\## 117 | # foo \# 118 | 119 | **** 120 | ## foo 121 | **** 122 | 123 | Foo bar 124 | # baz 125 | Bar foo 126 | 127 | ## 128 | # 129 | ### ### 130 | 131 | Foo *bar* 132 | ========= 133 | 134 | Foo *bar* 135 | --------- 136 | 137 | Foo 138 | ------------------------- 139 | 140 | Foo 141 | = 142 | 143 | Foo 144 | --- 145 | 146 | Foo 147 | ----- 148 | 149 | Foo 150 | === 151 | 152 | Foo 153 | --- 154 | 155 | Foo 156 | --- 157 | 158 | Foo 159 | ---- 160 | 161 | Foo 162 | --- 163 | 164 | Foo 165 | = = 166 | 167 | Foo 168 | --- - 169 | 170 | Foo 171 | ----- 172 | 173 | Foo\ 174 | ---- 175 | 176 | `Foo 177 | ---- 178 | ` 179 | 180 | 183 | 184 | > Foo 185 | --- 186 | 187 | - Foo 188 | --- 189 | 190 | Foo 191 | Bar 192 | --- 193 | 194 | Foo 195 | Bar 196 | === 197 | 198 | --- 199 | Foo 200 | --- 201 | Bar 202 | --- 203 | Baz 204 | 205 | 206 | ==== 207 | 208 | --- 209 | --- 210 | 211 | - foo 212 | ----- 213 | 214 | foo 215 | --- 216 | 217 | > foo 218 | ----- 219 | 220 | \> foo 221 | ------ 222 | 223 | a simple 224 | indented code block 225 | 226 | - foo 227 | 228 | bar 229 | 230 | 1. foo 231 | 232 | - bar 233 | 234 | 235 | *hi* 236 | 237 | - one 238 | 239 | chunk1 240 | 241 | chunk2 242 | 243 | 244 | 245 | chunk3 246 | 247 | chunk1 248 | 249 | chunk2 250 | 251 | Foo 252 | bar 253 | 254 | 255 | foo 256 | bar 257 | 258 | # Header 259 | foo 260 | Header 261 | ------ 262 | foo 263 | ---- 264 | 265 | foo 266 | bar 267 | 268 | 269 | 270 | foo 271 | 272 | 273 | 274 | foo 275 | 276 | ``` 277 | < 278 | > 279 | ``` 280 | 281 | ~~~ 282 | < 283 | > 284 | ~~~ 285 | 286 | ``` 287 | aaa 288 | ~~~ 289 | ``` 290 | 291 | ~~~ 292 | aaa 293 | ``` 294 | ~~~ 295 | 296 | ```` 297 | aaa 298 | ``` 299 | `````` 300 | 301 | ~~~~ 302 | aaa 303 | ~~~ 304 | ~~~~ 305 | 306 | ``` 307 | 308 | ````` 309 | 310 | ``` 311 | aaa 312 | 313 | > ``` 314 | > aaa 315 | 316 | bbb 317 | 318 | ``` 319 | 320 | 321 | ``` 322 | 323 | ``` 324 | ``` 325 | 326 | ``` 327 | aaa 328 | aaa 329 | ``` 330 | 331 | ``` 332 | aaa 333 | aaa 334 | aaa 335 | ``` 336 | 337 | ``` 338 | aaa 339 | aaa 340 | aaa 341 | ``` 342 | 343 | ``` 344 | aaa 345 | ``` 346 | 347 | ``` 348 | aaa 349 | ``` 350 | 351 | ``` 352 | aaa 353 | ``` 354 | 355 | ``` 356 | aaa 357 | ``` 358 | 359 | ``` ``` 360 | aaa 361 | 362 | ~~~~~~ 363 | aaa 364 | ~~~ ~~ 365 | 366 | foo 367 | ``` 368 | bar 369 | ``` 370 | baz 371 | 372 | foo 373 | --- 374 | ~~~ 375 | bar 376 | ~~~ 377 | # baz 378 | 379 | ```ruby 380 | def foo(x) 381 | return 3 382 | end 383 | ``` 384 | 385 | ~~~~ ruby startline=3 $%@#$ 386 | def foo(x) 387 | return 3 388 | end 389 | ~~~~~~~ 390 | 391 | ````; 392 | ```` 393 | 394 | ``` aa ``` 395 | foo 396 | 397 | ``` 398 | ``` aaa 399 | ``` 400 | 401 |
404 | hi 405 | | 406 |
449 | foo 450 | |
482 | import Text.HTML.TagSoup
483 |
484 | main :: IO ()
485 | main = print $ parseTags tags
486 |
487 |
488 |
493 |
494 |
500 |
501 |
515 | *foo*
516 |
517 | *bar*
518 | *baz*
519 |
520 | 1. *bar*
523 |
524 |
528 |
529 | ';
532 |
533 | ?>
534 |
535 |
536 |
537 |
549 |
550 |
551 |
552 |
553 |
554 | 587 | Hi 588 | | 589 | 590 |
599 | Hi 600 | | 601 | 602 |