Skip to content

Commit

Permalink
Ipnyb: allow lossless round-tripping of markdown cell content.
Browse files Browse the repository at this point in the history
The reader now parses the contents of the markdown cell to a Pandoc
structure, but *also* stores the raw markdown in a `source`
attribute on the cell Div.  When we convert back to markdown,
this attribute is stripped off and the original source is used.
When we convert to other formats, the attribute is usually
ignored (though it will come through in HTML as a `data-source`
attribute, not unhelpfully).

I'll note some potential drawbacks of this approach:

- It makes it impossible to use pandoc to clean up or
  change the contents of markdown cells, e.g.
  going from `+smart` to `-smart`.

- There may be formats where the addition of the `source`
  attribute is problematic.  I can't think of any, though.

Closes #5408.
  • Loading branch information
jgm committed Jun 30, 2020
1 parent 35a18bb commit efbc205
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/Text/Pandoc/Readers/Ipynb.hs
Expand Up @@ -79,7 +79,8 @@ cellToBlocks opts lang c = do
case cellType c of
Ipynb.Markdown -> do
Pandoc _ bs <- walk fixImage <$> readMarkdown opts source
return $ B.divWith ("",["cell","markdown"],kvs)
let kvs' = ("source", source) : kvs
return $ B.divWith ("",["cell","markdown"],kvs')
$ B.fromList bs
Ipynb.Heading lev -> do
Pandoc _ bs <- readMarkdown opts
Expand Down
7 changes: 5 additions & 2 deletions src/Text/Pandoc/Writers/Ipynb.hs
Expand Up @@ -102,10 +102,13 @@ extractCells _ [] = return []
extractCells opts (Div (_id,classes,kvs) xs : bs)
| "cell" `elem` classes
, "markdown" `elem` classes = do
let meta = pairsToJSONMeta kvs
let meta = pairsToJSONMeta [(k,v) | (k,v) <- kvs, k /= "source"]
(newdoc, attachments) <-
runStateT (walkM addAttachment (Pandoc nullMeta xs)) mempty
source <- writeMarkdown opts{ writerTemplate = Nothing } newdoc
source <- case lookup "source" kvs of
Just s -> return s
Nothing -> writeMarkdown opts{ writerTemplate = Nothing }
newdoc
(Ipynb.Cell{
cellType = Markdown
, cellSource = Source $ breakLines $ T.stripEnd source
Expand Down
6 changes: 3 additions & 3 deletions test/ipynb/simple.out.native
@@ -1,15 +1,15 @@
Pandoc (Meta {unMeta = fromList [("jupyter",MetaMap (fromList [("nbformat",MetaString "4"),("nbformat_minor",MetaString "5")]))]})
[Div ("",["cell","markdown"],[])
[Div ("",["cell","markdown"],[("source","Lorem ipsum\n===========\n\n**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus\nbibendum felis dictum sodales.")])
[Header 1 ("lorem-ipsum",[],[]) [Str "Lorem",Space,Str "ipsum"]
,Para [Strong [Str "Lorem",Space,Str "ipsum"],Space,Str "dolor",Space,Str "sit",Space,Str "amet,",Space,Str "consectetur",Space,Str "adipiscing",Space,Str "elit.",Space,Str "Nunc",Space,Str "luctus",SoftBreak,Str "bibendum",Space,Str "felis",Space,Str "dictum",Space,Str "sodales."]]
,Div ("",["cell","code"],[])
[CodeBlock ("",["python"],[]) "print(\"hello\")"]
,Div ("",["cell","markdown"],[])
,Div ("",["cell","markdown"],[("source","Pyout\n-----")])
[Header 2 ("pyout",[],[]) [Str "Pyout"]]
,Div ("",["cell","code"],[("execution_count","2")])
[CodeBlock ("",["python"],[]) "from IPython.display import HTML\nHTML(\"\"\"\n<script>\nconsole.log(\"hello\");\n</script>\n<b>HTML</b>\n\"\"\")"
,Div ("",["output","execute_result"],[("execution_count","2")])
[RawBlock (Format "html") "<script>\nconsole.log(\"hello\");\n</script>\n<b>HTML</b>\nhello"]]
,Div ("",["cell","markdown"],[("tags","[\"foo\",\"bar\"]")])
,Div ("",["cell","markdown"],[("source","Image\n-----\n\nThis image ![the moon](attachment:lalune.jpg) will be included as a cell\nattachment."),("tags","[\"foo\",\"bar\"]")])
[Header 2 ("image",[],[]) [Str "Image"]
,Para [Str "This",Space,Str "image",Space,Image ("",[],[]) [Str "the",Space,Str "moon"] ("lalune.jpg",""),Space,Str "will",Space,Str "be",Space,Str "included",Space,Str "as",Space,Str "a",Space,Str "cell",SoftBreak,Str "attachment."]]]

0 comments on commit efbc205

Please sign in to comment.