Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2019
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.49 KB | None | 0 0
  1. require 'lfs'
  2. local p = {} -- processor
  3. local docs = {}
  4. local concat = table.concat
  5. local targetDir = arg[1] or './docs/'
  6.  
  7. function fread(file)
  8. local h = io.open(file,'r')
  9. return coroutine.wrap(function()
  10. for l in h:lines() do
  11. coroutine.yield(l)
  12. end
  13. h:close()
  14. end)
  15. end
  16.  
  17. function pexec (cmd)
  18. local h = io.popen(cmd,'r')
  19. return coroutine.wrap(function()
  20. for l in h:lines() do
  21. coroutine.yield(l)
  22. end
  23. h:close()
  24. end)
  25. end
  26.  
  27. local ENDED, STARTED, WRITING = 1,2,3
  28.  
  29. p.processed = {}
  30. p.mdHeadLvl = 3
  31.  
  32. function p:slugify(str)
  33. return str:gsub('%W+','-'):gsub('^%-*',''):gsub('%-*$',''):lower()
  34. end
  35.  
  36.  
  37. function p:excerptOpen(line)
  38. if self.state == ENDED then
  39. local m,l,md = line:match('^%s*(%-%--)%[(=*)%[(md.*)$')
  40. if m then
  41. local file = md:match('^md%s*:%s*([^%s./]+)') or 'reference'
  42. if not docs[file] then docs[file] = {toc={}, body={}, name=file} end
  43. self.doc = docs[file]
  44. self.doc.body[#(self.doc.body)+ 1] = "\n"
  45. self._cmtLvl = l or ''
  46. self.state = STARTED
  47. end
  48. return true
  49. end
  50. return false
  51. end
  52.  
  53. -- Treat the lines considered the body of markdown
  54. -- first line of block can be considered topics if starts with #
  55. -- Observe that the if you jump the # level (ex. # to ###) you may
  56. -- break the table of contents (toc)
  57. function p:excerptBody(line)
  58. local indent,content = line:match('^(%s*)(%S.*)$')
  59. -- we map the indent variations to make it consistent
  60. indent = indent and indent:gsub("\t",' ') or ''
  61.  
  62. if self.state == STARTED then
  63. if content and #content then
  64. local body
  65. self.indent = indent
  66. local hmark, hcontent = content:match('^(#+)%s*(%S.+)')
  67. if hmark and #hmark then
  68. content=hcontent
  69. local hurl = concat{'#',self:slugify(self.doc.name),'_',self:slugify(content)}
  70. self.doc.toc[#(self.doc.toc) + 1] = concat{
  71. string.rep(' ',#hmark - 1),
  72. #hmark <= 2 and '1. ' or '* ',
  73. '[```',content,'```](',hurl,')\n'
  74. }
  75. body = {hmark,hmark and ' ','``',content,'`` {',hurl,"}\n\n"}
  76. else
  77. body = {content,'\n'}
  78. end
  79. self.doc.body[#(self.doc.body) + 1] = concat(body)
  80.  
  81. else
  82. self.doc.body[#(self.doc.body) + 1] = "\n"
  83. end
  84. self.state = WRITING
  85. return true
  86. elseif self.state == WRITING then
  87. if content then
  88. self.doc.body[#(self.doc.body) + 1] = concat{string.rep(' ',#(indent or '') - #self.indent),content,"\n"}
  89. else
  90. self.doc.body[#(self.doc.body) + 1] = "\n"
  91. end
  92. return true
  93. end
  94.  
  95. return false
  96. end
  97.  
  98. function p:excerptClose(line)
  99. local m = line:match('%]'..self._cmtLvl..'%]')
  100. if self.state ~= ENDED and m then
  101. self.doc.body[#(self.doc.body) + 1] = ''
  102. self.state = ENDED
  103. return true
  104. end
  105. return false
  106. end
  107.  
  108. function p:file(f)
  109. -- memoize init.lua inside directory
  110. if self.processed[f] then
  111. return
  112. else
  113. f = lfs.attributes(f).mode == 'directory' and f..'/init.lua' or f
  114. self.processed[f]=1
  115. end
  116.  
  117. -- read each file line
  118. local fattr = lfs.attributes(f)
  119. local _ = false
  120.  
  121. if fattr and fattr.mode == 'file' then
  122. self._cmtLvl = ''
  123. self.state = ENDED
  124. for line in fread(f) do
  125. _ = self:excerptClose(line) or self:excerptOpen(line) or self:excerptBody(line)
  126. end
  127. end
  128. end
  129.  
  130. function p.addTimestamp(d)
  131. d[#(d) + 1]='\n----------\n'
  132. d[#(d) + 1]='Last update: '..os.date('%F %T %z')
  133. end
  134.  
  135. --TODO: Needs a way system independent do get list of files
  136. for pathItem in pexec('find .|sort') do
  137. p:file(pathItem)
  138. end
  139. lfs.mkdir(targetDir)
  140. for i,v in pairs(docs) do
  141. local f = io.open(concat{targetDir,'/',i,'.md'},'w+')
  142. p.addTimestamp(v.body)
  143. v.body=concat(v.body):gsub('\n\n+','\n\n')
  144. f:write(concat(v.toc),'\n\n',v.body)
  145. f:close()
  146. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement