 	}
 	
 	private func htmlFor(markdownChunk: RmdDocumentChunk, index: Int) -> String {
-		let html = mdownParser.htmlFor(markdown: parsedDocument!.string(for: markdownChunk))
+		var chunkString = parsedDocument!.string(for: markdownChunk)
+		// replace all inline chunks with a placeholder
+		for (idx, ichunk) in markdownChunk.children.reversed().enumerated() {
+			guard let range = Range<String.Index>(ichunk.chunkRange, in: chunkString) else { fatalError("invalid range") }
+			chunkString = chunkString.replacingCharacters(in: range, with: "!IC-\(idx)!")
+		}
+		// convert markdown to html
+		let html = mdownParser.htmlFor(markdown: chunkString)
+		// restore inline chunks. reverse so don't invalidate later ranges
+		for idx in (0..<markdownChunk.children.count).reversed() {
+			let replacement = textFor(inlineChunk: markdownChunk.children[idx], parent: markdownChunk)
+			html.replaceOccurrences(of: "!IC-\(idx)!", with: replacement, options: [], range: NSRange(location: 0, length: html.length))
+		}
 		// modify source position to include chunk number
 		_ = dataSourceRegex.replaceMatches(in: html, range: NSRange(location: 0, length: html.length), withTemplate: "data-sourcepos=\"\(index).$2")
 		return html as String

			Log.info("udpating just chunks \(changedChunkIndexes)")
			for chunkNumber in changedChunkIndexes {
				let chunk = curDoc.chunks[chunkNumber]
				let html = escapeForJavascript(htmlFor(chunk: chunk, index: chunkNumber))
				let command = "$(\"section[index='\(chunkNumber)']\").html('\(html)'); MathJax.typeset()"
				outputView?.evaluateJavaScript(command, completionHandler: nil)
			}
		} else { // no changes, so just refresh everything

	/// replaces the visible html document
	/// - Parameter html: the new html to display
	private func load(html: String)  {
		let nav = outputView?.loadHTMLString(html, baseURL: htmlRoot)
		if let realNav = nav { emptyNavigations.insert(realNav) }
	}
	
