markdown.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package.path=package.path..";" ..debug.getinfo(1).source:match("(.*[/\\])"):sub(2) .. "?.lua"
  2. require("polyfill")
  3. local url = require('url')
  4. local pandoc=pandoc
  5. local PANDOC_STATE=PANDOC_STATE
  6. local PATH = pandoc.path
  7. local doc_dir = nil
  8. local media_dir = nil
  9. if Mode == nil then
  10. Mode = 'default'
  11. end
  12. -- print("Mode: "..Mode)
  13. if PANDOC_STATE.output_file then
  14. local output_file = PANDOC_STATE.output_file
  15. doc_dir = PATH.directory(output_file)
  16. if PANDOC_WRITER_OPTIONS.variables["media_dir"] then
  17. media_dir = PANDOC_WRITER_OPTIONS.variables["media_dir"]
  18. else
  19. media_dir = PATH.split_extension(output_file)
  20. if Mode ~= 'hugo' then
  21. media_dir = media_dir .. '-media'
  22. end
  23. end
  24. end
  25. assert(doc_dir, "doc_dir is nil")
  26. assert(media_dir, "media_dir is nil")
  27. local function get_absolute_path(file_path)
  28. if PATH.is_absolute(file_path) then
  29. return file_path
  30. end
  31. for _, dir in pairs(PANDOC_STATE.resource_path) do
  32. local full_path = PATH.join({dir, file_path})
  33. if os.exists(full_path) then
  34. return full_path
  35. end
  36. end
  37. for _, file in pairs(PANDOC_STATE.input_files) do
  38. if not PATH.is_absolute(file) then
  39. file = PATH.join({pandoc.system.get_working_directory(), file_path})
  40. end
  41. local dir = PATH.directory(file)
  42. local full_path = PATH.join({dir, file_path})
  43. if os.exists(full_path) then
  44. return full_path
  45. end
  46. end
  47. return nil
  48. end
  49. local function get_output_file(file_path)
  50. if media_dir then
  51. local new_file_name = pandoc.utils.sha1(file_path)
  52. local _, new_file_ext = PATH.split_extension(file_path)
  53. file_path = new_file_name .. new_file_ext
  54. local full_path = PATH.join({media_dir, file_path})
  55. return full_path
  56. else
  57. return nil
  58. end
  59. end
  60. local function extract_media(file_path)
  61. os.mkdir(media_dir)
  62. file_path = url.decode(file_path)
  63. local abs_path = get_absolute_path(file_path)
  64. local file = get_output_file(file_path)
  65. if abs_path and file then
  66. if not os.exists(file) then
  67. os.copy(abs_path, file)
  68. end
  69. local rel_path = PATH.make_relative(file, doc_dir, false)
  70. local parts = PATH.split(rel_path)
  71. for i,v in ipairs(parts) do
  72. parts[i] = url.encode(v)
  73. end
  74. local encoded_rel_path = table.concat(parts, "/")
  75. if Mode == 'hugo' then
  76. encoded_rel_path = '../' .. encoded_rel_path
  77. end
  78. return encoded_rel_path
  79. end
  80. end
  81. local function raw(s)
  82. return pandoc.RawInline('markdown', s)
  83. end
  84. function Image(el)
  85. local src = extract_media(el.src)
  86. if src then
  87. el.src = src
  88. end
  89. return el
  90. end
  91. function Space()
  92. return raw(' ')
  93. end
  94. function SoftBreak()
  95. return raw('\n')
  96. end
  97. function RawInline(el)
  98. if el.format == "html" then
  99. el.format = 'markdown'
  100. el.text = string.gsub(el.text, '<img[^>]+>', function(img)
  101. return string.gsub(img, 'src="([^"]+)"', function(url)
  102. if string.find(url, '^[Hh][Tt][Tt][Pp][Ss]?://') == nil then
  103. local extract_media_url = extract_media(url)
  104. if extract_media_url then
  105. return 'src="' .. extract_media_url .. '"'
  106. end
  107. return '123'
  108. end
  109. return 'src="' .. url .. '"'
  110. end)
  111. end)
  112. end
  113. return el
  114. end
  115. function RawBlock(el)
  116. if el.format == "html" then
  117. el.format = 'markdown'
  118. end
  119. return el
  120. end
  121. function Math(el)
  122. if Mode == 'hugo' then
  123. if el.mathtype == 'DisplayMath' then
  124. return raw('{{< mathjax >}}\n$$' .. el.text .. '$$\n{{</mathjax >}}')
  125. else
  126. el.text = string.gsub(el.text, '\\[\\{\\}]', function (v)
  127. return '\\' .. v
  128. end)
  129. el.text = string.gsub(el.text, '_', function (v)
  130. return '\\' .. v
  131. end)
  132. end
  133. end
  134. return el
  135. end
  136. function Para(el)
  137. local content = {}
  138. local in_display_math = false
  139. for _, item in pairs(el.content) do
  140. if item.t == 'Str'and item.text == "$$" then
  141. in_display_math = not in_display_math
  142. else
  143. if in_display_math then
  144. if item.t == 'RawInline' and item.format == 'tex' then
  145. local n = pandoc.Math('DisplayMath', '\n' .. item.text .. '\n')
  146. table.insert(content, Math(n))
  147. else
  148. table.insert(content, item)
  149. end
  150. else
  151. table.insert(content, item)
  152. end
  153. end
  154. end
  155. el.content = content
  156. return el
  157. end
  158. function Pandoc(el)
  159. return el
  160. end