md2sht with Haskell

3b48c91bf6b6f0bfd0fda50625598656?s=47 Justin Woo
November 04, 2016

md2sht with Haskell

Small talk I gave for Futurice WWWeeklies for a tool I wrote to convert Markdown into inline-Styled HTml for our CMS.

3b48c91bf6b6f0bfd0fda50625598656?s=128

Justin Woo

November 04, 2016
Tweet

Transcript

  1. md2sht with Haskell Justin Woo

  2. Convert Markdown to inline-styled HTML

  3. The problem For a tech company, we just don’t have

    enough tech posts on our blog. Flockler requires inline-styled HTML to be input to the “code view” to get styled HTML in posts (especially important for code blocks). Everyone complains about Flockler being terrible since it doesn’t have Markdown support. As a result, shit don’t get done. How much do developers like…? Testing Writing PLs Bitching
  4. The solution Why not make a tool to make inline-styled

    HTML generation easy? We can use some amazing Haskell libraries to do this!
  5. The team Who even likes Haskell anyway? Justin Oleg Some

    weird Asian guy who decided he should be solving this problem for everyone, whose picture isn’t even here FutuHaskell guru who helped fix the terrible code Justin wrote, whose picture is also not here You You might not think so, but you are also vital to this project, as a user and as a developer.
  6. Timeline How md2sht came to be January 2016 Justin goes

    back to Japan for vacation after visiting Futurice in Oct 2015 April 2016 Justin moves to Helsinki October 2016 Justin asks some silly questions about writing a CSS Parser for some ungodly reason October 2016 md2sht is published on GitHub, much to the dismay of the civilized world Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec
  7. Why Haskell? Mature libraries like Pandoc, attoparsec Good small HTML

    parsing libs like TagSoup Fun! How would I get involved? Start using md2sht, read some source code, ask questions on Flowdock/Twitter or in Person! Don’t I need to know a lot of hard/unfamiliar functional programming to do Haskell? Nope! Most of the code uses little more than “Either Error [Rule]” and [Rule] -> String -> String Why/How?
  8. Install md2sht and run md2sht --input YourPost.md md2sht writers’ workflow

    Step 1 Write your post with Markdown like you normally would Step 2 Step 3 Copy the generated HTML into the Flockler code view and save your post
  9. Haskell Fun for everyone * for certain definitions of “fun”

  10. md2sht process The md2sht program is composed of • the

    executable, which takes care of ◦ parsing command line options ◦ reading input ◦ outputting the results • the library, which contains ◦ a function to parse and apply transforms to our HTML ◦ a parser for CSS Parse CSS using AttoParsec to a flat List of Rules of Selector and List of Lines (property-value pairs) Parse HTML using TagSoup to a flat List of Tags (Open, Closing, Text, etc.) Extract the styles by matching the Rules to classes in the HTML and inline them, removing classes in the process
  11. Parsing CSS First need to put it in terms of

    types we can work with, using simple data types. Then we use AttoParsec’s functions to write instructions to move around a cursor and parse the result out. “>>” -- sequentially compose two actions and throw away the left side). “<|>” -- attempt the left action, and apply the right if it fails ~48 LOC with whitespace This is the whole parser!
  12. Transforming HTML We should be able to take a list

    of our Rules and input HTML to produce transformed HTML. We use TagSoup here to parse the HTML and conditionally apply a transform as we need. We extract styles that we need from the rules using a list of classnames that we get from the tag. We then remove the class attribute since Flockler will wipe all attributes if it exists on a tag.
  13. Extracting styles We use the simplest way possible to match

    the styles, by looking for “.classname” being an infix of a selector (which was defined as simply Selector Text). For every match, we return the result of all the inlinable strings concatenated together per Line, per Rule.
  14. Result ```js function a(b) { return Promise.resolve( b.x + 123

    + window.x ); } ``` md2sht ➡
  15. That’s it! 112 lines, 410 words in src/ 63 lines,

    244 words in app/ Only bug after compiling and running: comment parsing in CSS (faulty logic) ...which is why you write tests!
  16. Tests!

  17. Tests (cont.) • You will never write another “expect(a).toBeType(A)” again

    • Testing pure functions is very easy, and you won’t even be allowed to implicitly test effectful functions by the compiler (but you can explicitly if you need/want to) • You only ever need to test values and logic (e.g. not “does this function correctly return an object with these keys?”)
  18. That’s it! • Haskell checks our code and guides us

    as we guide it • Our code can be very descriptive and still be short • We still need tests for value-level details • Everyone can write Haskell and have FUNctional programming And even if you don’t care about Haskell, • Writing technical posts on Flockler is super easy now, so do it!
  19. Thanks for listening! • Code is on github.com/justinwoo/md2sht • Oleg

    is collecting posts on futurice/tech-blogs ◦ (internal-only repo, sorry everyone)