build.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. -- imports
  2. import("devel.git")
  3. import("core.base.semver")
  4. function mtime(file)
  5. return os.date("%Y-%m-%dT%H:%M:%S+08:00", os.mtime(file))
  6. end
  7. function header(url)
  8. return format([[
  9. <!DOCTYPE html>
  10. <html lang="en">
  11. <head>
  12. <meta charset="UTF-8">
  13. <title>xrepo</title>
  14. <link rel="icon" href="/assets/img/favicon.ico">
  15. <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  16. <meta name="description" content="Description">
  17. <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  18. <link href="//cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" rel="stylesheet">
  19. <style>
  20. .markdown-body {
  21. box-sizing: border-box;
  22. min-width: 200px;
  23. max-width: 980px;
  24. margin: 0 auto;
  25. padding: 45px;
  26. }
  27. @media (max-width: 767px) {
  28. .markdown-body {
  29. padding: 15px;
  30. }
  31. }
  32. </style>
  33. </head>
  34. <body>
  35. <article class="markdown-body">
  36. <h4>This is a mirror page, please see the original page: </h4><a href="%s">%s</a>
  37. <div id="wwads-panel" class="wwads-cn wwads-vertical wwads-sticky" data-id="239" style="max-width:180px;bottom:20px;right:20px;width:200px;height:260px;background:#fff;position:fixed"></div>
  38. </br>
  39. ]], url, url)
  40. end
  41. function tailer()
  42. return [[
  43. </article>
  44. </body>
  45. </html>]]
  46. end
  47. function ads()
  48. return [[
  49. <script type="text/javascript" charset="UTF-8" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
  50. <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
  51. <style>
  52. #carbonads {
  53. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
  54. Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
  55. }
  56. #carbonads {
  57. display: flex;
  58. max-width: 330px;
  59. background-color: hsl(0, 0%, 98%);
  60. box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
  61. }
  62. #carbonads a {
  63. color: inherit;
  64. text-decoration: none;
  65. }
  66. #carbonads a:hover {
  67. color: inherit;
  68. }
  69. #carbonads span {
  70. position: relative;
  71. display: block;
  72. overflow: hidden;
  73. }
  74. #carbonads .carbon-wrap {
  75. display: flex;
  76. }
  77. .carbon-img {
  78. display: block;
  79. margin: 0;
  80. line-height: 1;
  81. }
  82. .carbon-img img {
  83. display: block;
  84. }
  85. .carbon-text {
  86. font-size: 13px;
  87. padding: 10px;
  88. line-height: 1.5;
  89. text-align: left;
  90. }
  91. .carbon-poweredby {
  92. display: block;
  93. padding: 8px 10px;
  94. background: repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4);
  95. text-align: center;
  96. text-transform: uppercase;
  97. letter-spacing: .5px;
  98. font-weight: 600;
  99. font-size: 9px;
  100. line-height: 1;
  101. }
  102. </style>
  103. ]]
  104. end
  105. -- fix links
  106. function _fixlinks(htmldata)
  107. -- <a href="/manual/builtin_modules?id=osmv">os.mv</a>
  108. -- => <a href="/mirror/manual/builtin_modules.html#osmv">os.mv</a>
  109. htmldata = htmldata:gsub("(href=\"(.-)\")", function(_, href)
  110. if href:startswith("/") and not href:startswith("/#/") then
  111. local splitinfo = href:split('?', {plain = true})
  112. local url = splitinfo[1]
  113. href = "/mirror" .. url .. ".html"
  114. if splitinfo[2] then
  115. local anchor = splitinfo[2]:gsub("id=", "")
  116. href = href .. "#" .. anchor
  117. end
  118. print(" -> fix %s", href)
  119. end
  120. return "href=\"" .. href .. "\""
  121. end)
  122. -- <h4 id="os-rm">os.rm</h4>
  123. -- => <h4 id="osrm">os.rm</h4>
  124. htmldata = htmldata:gsub("(id=\"(.-)\")", function(_, id)
  125. id = id:gsub("%-", "")
  126. return "id=\"" .. id .. "\""
  127. end)
  128. return htmldata
  129. end
  130. -- generate mirror files and sitemap.xml
  131. -- we need install https://github.com/cwjohan/markdown-to-html first
  132. -- npm install markdown-to-html -g
  133. --
  134. -- Or use showdown-cli https://github.com/showdownjs/showdown
  135. --
  136. function build_mirror_files()
  137. local siteroot = "https://xrepo.xmake.io"
  138. local mirrordir = "mirror"
  139. local sitemap = io.open("sitemap.xml", 'w')
  140. sitemap:print([[
  141. <?xml version="1.0" encoding="UTF-8"?>
  142. <urlset
  143. xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  144. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  145. xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
  146. http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
  147. ]])
  148. sitemap:print([[
  149. <url>
  150. <loc>%s</loc>
  151. <lastmod>%s</lastmod>
  152. </url>
  153. ]], siteroot, mtime("index.html"))
  154. os.rm(mirrordir)
  155. for _, markdown in ipairs(os.files("**.md")) do
  156. local basename = path.basename(markdown)
  157. if not basename:startswith("_") then
  158. -- get the raw url
  159. if basename == "README" then
  160. basename = ""
  161. end
  162. local url = siteroot .. '/mirror'
  163. local rawurl = siteroot .. '/#'
  164. local dir = path.directory(markdown)
  165. if dir ~= '.' then
  166. rawurl = rawurl .. '/' .. dir
  167. url = url .. '/' .. dir
  168. end
  169. rawurl = rawurl .. '/' .. basename
  170. url = url .. '/' .. (basename == "" and "index.html" or (basename .. ".html"))
  171. -- generate html file
  172. local htmlfile = path.join(mirrordir, dir, basename == "" and "index.html" or (basename .. ".html"))
  173. local htmldata = os.iorunv("markdown", {markdown})
  174. local f = io.open(htmlfile, 'w')
  175. if f then
  176. f:write(header(rawurl))
  177. f:write(ads())
  178. htmldata = htmldata:gsub("&%a-;", function (w)
  179. local maps = {["&lt;"] = "<", ["&gt;"] = ">", ["&quot;"] = "\""}
  180. return maps[w]
  181. end)
  182. f:write(_fixlinks(htmldata))
  183. f:write(tailer())
  184. f:close()
  185. end
  186. --[[
  187. local tmpfile = os.tmpfile()
  188. os.mkdir(path.directory(tmpfile))
  189. os.execv("showdown", {"makehtml", "-i", markdown, "-o", tmpfile})
  190. local f = io.open(htmlfile, 'w')
  191. if f then
  192. f:write(header(rawurl))
  193. f:write(ads())
  194. f:write(_fixlinks(io.readfile(tmpfile)))
  195. f:write(tailer())
  196. f:close()
  197. end
  198. os.rm(tmpfile)]]
  199. print("build %s => %s, %s", markdown, htmlfile, mtime(htmlfile))
  200. print("url %s -> %s", url, rawurl)
  201. -- generate sitemap
  202. sitemap:print([[
  203. <url>
  204. <loc>%s</loc>
  205. <lastmod>%s</lastmod>
  206. </url>
  207. ]], url, mtime(htmlfile))
  208. end
  209. end
  210. sitemap:print("</urlset>")
  211. sitemap:close()
  212. end
  213. -- write package
  214. function write_package(file, pkg, plat, archs)
  215. local name = pkg:name()
  216. local homepage = pkg:get("homepage")
  217. local license = pkg:get("license")
  218. local versions = pkg:versions()
  219. local xmakefile = ("https://github.com/xmake-io/xmake-repo/blob/master/packages/%s/%s/xmake.lua"):format(name:sub(1, 1), name)
  220. file:print("### %s (%s)", name, plat)
  221. file:print("")
  222. file:print("")
  223. file:print("| Description | *%s* |", pkg:description())
  224. file:print("| -- | -- |")
  225. file:print("| Homepage | [%s](%s) |", homepage, homepage)
  226. if license then
  227. file:print("| License | %s |", license)
  228. end
  229. archs = table.copy(archs)
  230. table.sort(archs)
  231. table.sort(versions, function (a, b)
  232. if semver.is_valid(a) and semver.is_valid(b) then
  233. return semver.compare(a, b) < 0
  234. else
  235. return a < b
  236. end
  237. end)
  238. file:print("| Versions | %s |", table.concat(versions, ", "))
  239. file:print("| Architectures | %s |", table.concat(archs, ", "))
  240. file:print("| Definition | [%s/xmake.lua](%s) |", name, xmakefile)
  241. file:print("")
  242. file:print("##### Install command")
  243. file:print("")
  244. file:print("```console")
  245. if plat == "android" then
  246. file:print("xrepo install -p android [--ndk=/xxx] %s", name)
  247. elseif plat == "mingw" then
  248. file:print("xrepo install -p mingw [--mingw=/xxx] %s", name)
  249. elseif plat == "iphoneos" then
  250. file:print("xrepo install -p iphoneos %s", name)
  251. elseif plat == "cross" then
  252. file:print("xrepo install -p cross [--sdk=/xxx] %s", name)
  253. elseif plat == "wasm" then
  254. file:print("xrepo install -p wasm %s", name)
  255. else
  256. file:print("xrepo install %s", name)
  257. end
  258. file:print("```")
  259. file:print("")
  260. file:print("##### Integration in the project (xmake.lua)")
  261. file:print("")
  262. file:print("```lua")
  263. file:print("add_requires(\"%s\")", name)
  264. file:print("```")
  265. file:print("")
  266. file:print("")
  267. end
  268. -- get latest added packages
  269. -- git -c pager.log=false log --diff-filter=A --stat --max-count=5 --format=%aD
  270. function latest_packages()
  271. local latest = {}
  272. local results = os.iorunv("git -c pager.log=false log --diff-filter=A --stat --max-count=5 --format=%aD")
  273. if results then
  274. for _, line in ipairs(results:split('\n', {plain = true})) do
  275. line = line:split('|')[1]
  276. line = line:trim()
  277. if line:endswith("xmake.lua") then
  278. table.insert(latest, path.filename(path.directory(line)))
  279. end
  280. end
  281. end
  282. return table.slice(latest, 1, 3)
  283. end
  284. -- build packages
  285. function build_packages()
  286. -- clone xmake-repo
  287. local url = "https://github.com/xmake-io/xmake-repo"
  288. local repodir = path.join(os.tmpdir(), "xrepo-docs", "xmake-repo")
  289. print("clone %s => %s", url, repodir)
  290. os.tryrm(repodir)
  291. git.clone(url, {outputdir = repodir})
  292. -- load packages
  293. local oldir = os.cd(repodir)
  294. local packages = import("scripts.packages", {rootdir = repodir, anonymous = true})()
  295. local latest = latest_packages()
  296. os.cd(oldir)
  297. -- get total packages
  298. local total_packages = {}
  299. for _, pkgs in pairs(packages) do
  300. for _, pkg in ipairs(pkgs) do
  301. table.insert(total_packages, pkg.name)
  302. end
  303. end
  304. total_packages = table.unique(total_packages)
  305. -- generate _sidebar.md
  306. print("generate _sidebar.md")
  307. local sidebar = io.open("_sidebar.md", "w")
  308. sidebar:print("- Getting Started")
  309. sidebar:print(" - [Sponsor](https://xmake.io/#/about/sponsor)")
  310. sidebar:print(" - [Quick Start](getting_started.md)")
  311. sidebar:print("- Packages (%s)", #total_packages)
  312. local plats = table.keys(packages)
  313. table.sort(plats)
  314. for _, plat in ipairs(plats) do
  315. sidebar:print(" - [%s](packages/%s.md)", plat, plat)
  316. end
  317. sidebar:close()
  318. -- generate zh-cn/_sidebar.md
  319. print("generate zh-cn/_sidebar.md")
  320. local sidebar = io.open("zh-cn/_sidebar.md", "w")
  321. sidebar:print("- 快速入门")
  322. sidebar:print(" - [赞助](https://xmake.io/#/zh-cn/about/sponsor)")
  323. sidebar:print(" - [快速上手](zh-cn/getting_started.md)")
  324. sidebar:print("- 包列表 (%s)", #total_packages)
  325. for _, plat in ipairs(plats) do
  326. sidebar:print(" - [%s](packages/%s.md)", plat, plat)
  327. end
  328. sidebar:close()
  329. -- generate packages/*.md
  330. print("generate packages/*.md")
  331. for _, plat in ipairs(plats) do
  332. local pkgs = packages[plat]
  333. local list = {}
  334. for _, pkg in ipairs(pkgs) do
  335. local key = pkg.name:sub(1, 1)
  336. list[key] = list[key] or {}
  337. table.insert(list[key], pkg)
  338. end
  339. local keys = table.keys(list)
  340. table.sort(keys)
  341. local file = io.open(path.join("packages", plat .. ".md"), "w")
  342. for _, key in ipairs(keys) do
  343. file:print("## %s", key)
  344. for _, pkg in ipairs(list[key]) do
  345. write_package(file, pkg.instance, plat, pkg.archs)
  346. end
  347. file:print("")
  348. end
  349. file:close()
  350. end
  351. -- generate latest added packages
  352. io.gsub("_coverpage.md", "%*%*Recently added:.*%*%*", "**Recently added: " .. table.concat(latest, ", ") .. "**")
  353. io.gsub("zh-cn/_coverpage.md", "%*%*Recently added:.*%*%*", "**Recently added: " .. table.concat(latest, ", ") .. "**")
  354. end
  355. -- main entry
  356. function main()
  357. os.cd(os.scriptdir())
  358. build_packages()
  359. build_mirror_files()
  360. end