You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

markdown_test.go 20 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. package markdown_test
  2. import (
  3. "fmt"
  4. "strconv"
  5. "testing"
  6. "strings"
  7. . "code.gitea.io/gitea/modules/markdown"
  8. "code.gitea.io/gitea/modules/setting"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. const AppURL = "http://localhost:3000/"
  12. const Repo = "gogits/gogs"
  13. const AppSubURL = AppURL + Repo + "/"
  14. var numericMetas = map[string]string{
  15. "format": "https://someurl.com/{user}/{repo}/{index}",
  16. "user": "someUser",
  17. "repo": "someRepo",
  18. "style": IssueNameStyleNumeric,
  19. }
  20. var alphanumericMetas = map[string]string{
  21. "format": "https://someurl.com/{user}/{repo}/{index}",
  22. "user": "someUser",
  23. "repo": "someRepo",
  24. "style": IssueNameStyleAlphanumeric,
  25. }
  26. // numericLink an HTML to a numeric-style issue
  27. func numericIssueLink(baseURL string, index int) string {
  28. return link(URLJoin(baseURL, strconv.Itoa(index)), fmt.Sprintf("#%d", index))
  29. }
  30. // alphanumLink an HTML link to an alphanumeric-style issue
  31. func alphanumIssueLink(baseURL string, name string) string {
  32. return link(URLJoin(baseURL, name), name)
  33. }
  34. // urlContentsLink an HTML link whose contents is the target URL
  35. func urlContentsLink(href string) string {
  36. return link(href, href)
  37. }
  38. // link an HTML link
  39. func link(href, contents string) string {
  40. return fmt.Sprintf("<a href=\"%s\">%s</a>", href, contents)
  41. }
  42. func testRenderIssueIndexPattern(t *testing.T, input, expected string, metas map[string]string) {
  43. assert.Equal(t, expected,
  44. string(RenderIssueIndexPattern([]byte(input), AppSubURL, metas)))
  45. }
  46. func TestRenderIssueIndexPattern(t *testing.T) {
  47. // numeric: render inputs without valid mentions
  48. test := func(s string) {
  49. testRenderIssueIndexPattern(t, s, s, nil)
  50. testRenderIssueIndexPattern(t, s, s, numericMetas)
  51. }
  52. // should not render anything when there are no mentions
  53. test("")
  54. test("this is a test")
  55. test("test 123 123 1234")
  56. test("#")
  57. test("# # #")
  58. test("# 123")
  59. test("#abcd")
  60. test("##1234")
  61. test("test#1234")
  62. test("#1234test")
  63. test(" test #1234test")
  64. // should not render issue mention without leading space
  65. test("test#54321 issue")
  66. // should not render issue mention without trailing space
  67. test("test #54321issue")
  68. }
  69. func TestRenderIssueIndexPattern2(t *testing.T) {
  70. setting.AppURL = AppURL
  71. setting.AppSubURL = AppSubURL
  72. // numeric: render inputs with valid mentions
  73. test := func(s, expectedFmt string, indices ...int) {
  74. links := make([]interface{}, len(indices))
  75. for i, index := range indices {
  76. links[i] = numericIssueLink(URLJoin(setting.AppSubURL, "issues"), index)
  77. }
  78. expectedNil := fmt.Sprintf(expectedFmt, links...)
  79. testRenderIssueIndexPattern(t, s, expectedNil, nil)
  80. for i, index := range indices {
  81. links[i] = numericIssueLink("https://someurl.com/someUser/someRepo/", index)
  82. }
  83. expectedNum := fmt.Sprintf(expectedFmt, links...)
  84. testRenderIssueIndexPattern(t, s, expectedNum, numericMetas)
  85. }
  86. // should render freestanding mentions
  87. test("#1234 test", "%s test", 1234)
  88. test("test #8 issue", "test %s issue", 8)
  89. test("test issue #1234", "test issue %s", 1234)
  90. // should render mentions in parentheses
  91. test("(#54321 issue)", "(%s issue)", 54321)
  92. test("test (#9801 extra) issue", "test (%s extra) issue", 9801)
  93. test("test (#1)", "test (%s)", 1)
  94. // should render multiple issue mentions in the same line
  95. test("#54321 #1243", "%s %s", 54321, 1243)
  96. test("wow (#54321 #1243)", "wow (%s %s)", 54321, 1243)
  97. test("(#4)(#5)", "(%s)(%s)", 4, 5)
  98. test("#1 (#4321) test", "%s (%s) test", 1, 4321)
  99. }
  100. func TestRenderIssueIndexPattern3(t *testing.T) {
  101. setting.AppURL = AppURL
  102. setting.AppSubURL = AppSubURL
  103. // alphanumeric: render inputs without valid mentions
  104. test := func(s string) {
  105. testRenderIssueIndexPattern(t, s, s, alphanumericMetas)
  106. }
  107. test("")
  108. test("this is a test")
  109. test("test 123 123 1234")
  110. test("#")
  111. test("##1234")
  112. test("# 123")
  113. test("#abcd")
  114. test("test #123")
  115. test("abc-1234") // issue prefix must be capital
  116. test("ABc-1234") // issue prefix must be _all_ capital
  117. test("ABCDEFGHIJK-1234") // the limit is 10 characters in the prefix
  118. test("ABC1234") // dash is required
  119. test("test ABC- test") // number is required
  120. test("test -1234 test") // prefix is required
  121. test("testABC-123 test") // leading space is required
  122. test("test ABC-123test") // trailing space is required
  123. test("ABC-0123") // no leading zero
  124. }
  125. func TestRenderIssueIndexPattern4(t *testing.T) {
  126. setting.AppURL = AppURL
  127. setting.AppSubURL = AppSubURL
  128. // alphanumeric: render inputs with valid mentions
  129. test := func(s, expectedFmt string, names ...string) {
  130. links := make([]interface{}, len(names))
  131. for i, name := range names {
  132. links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", name)
  133. }
  134. expected := fmt.Sprintf(expectedFmt, links...)
  135. testRenderIssueIndexPattern(t, s, expected, alphanumericMetas)
  136. }
  137. test("OTT-1234 test", "%s test", "OTT-1234")
  138. test("test T-12 issue", "test %s issue", "T-12")
  139. test("test issue ABCDEFGHIJ-1234567890", "test issue %s", "ABCDEFGHIJ-1234567890")
  140. }
  141. func TestRenderer_AutoLink(t *testing.T) {
  142. setting.AppURL = AppURL
  143. setting.AppSubURL = AppSubURL
  144. SubURLNoProtocol := setting.AppSubURL[5:]
  145. test := func(input, expected string) {
  146. buffer := RenderSpecialLink([]byte(input), setting.AppSubURL, map[string]string{})
  147. assert.Equal(t, expected, string(buffer))
  148. }
  149. // render valid issue URLs
  150. test(URLJoin(setting.AppSubURL, "issues", "3333"),
  151. numericIssueLink(URLJoin(setting.AppSubURL, "issues"), 3333))
  152. // render external issue URLs
  153. tmp := "//1111/2222/ssss-issues/3333?param=blah&blahh=333"
  154. test("http:"+tmp,
  155. "<a href=\""+tmp+"\">#3333 <i class='comment icon'></i></a>")
  156. test("http://test.com/issues/33333", numericIssueLink("//test.com/issues", 33333))
  157. test("https://issues/333", numericIssueLink("//issues", 333))
  158. // render valid commit URLs
  159. tmp = URLJoin(SubURLNoProtocol, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae")
  160. test("http://"+tmp, "<a href=\""+tmp+"\">d8a994ef24</a>")
  161. tmp += "#diff-2"
  162. test("http://"+tmp, "<a href=\""+tmp+"\">d8a994ef24 (diff-2)</a>")
  163. // render other commit URLs
  164. tmp = "//external-link.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2"
  165. test("https:"+tmp, "<a href=\""+tmp+"\">d8a994ef24 (diff-2)</a>")
  166. }
  167. func TestRender_ShortLinks(t *testing.T) {
  168. setting.AppURL = AppURL
  169. setting.AppSubURL = AppSubURL
  170. test := func(input, expected string) {
  171. buffer := RenderString(input, setting.AppSubURL, nil)
  172. assert.Equal(t, expected, string(buffer))
  173. }
  174. var url = URLJoin(AppSubURL, "wiki", "Link")
  175. var imgurl = URLJoin(AppSubURL, "wiki", "raw", "Link.jpg")
  176. var favicon = "http://google.com/favicon.ico"
  177. test("[[Link]]", `<p><a href="`+url+`" rel="nofollow">Link</a></p>
  178. `)
  179. test("[[Link.jpg]]", `<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" alt="Link.jpg" title="Link.jpg"/></a></p>
  180. `)
  181. test("[["+favicon+"]]", `<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico"/></a></p>
  182. `)
  183. test("[[Name|Link]]", `<p><a href="`+url+`" rel="nofollow">Name</a></p>
  184. `)
  185. test("[[Name|Link.jpg]]", `<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" alt="Name" title="Name"/></a></p>
  186. `)
  187. test("[[Name|Link.jpg|alt=AltName]]", `<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" alt="AltName" title="AltName"/></a></p>
  188. `)
  189. test("[[Name|Link.jpg|title=Title]]", `<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" alt="Title" title="Title"/></a></p>
  190. `)
  191. test("[[Name|Link.jpg|alt=AltName|title=Title]]", `<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" alt="AltName" title="Title"/></a></p>
  192. `)
  193. test("[[Name|Link.jpg|alt=\"AltName\"|title='Title']]", `<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" alt="AltName" title="Title"/></a></p>
  194. `)
  195. }
  196. func TestRender_Commits(t *testing.T) {
  197. setting.AppURL = AppURL
  198. setting.AppSubURL = AppSubURL
  199. test := func(input, expected string) {
  200. buffer := RenderString(input, setting.AppSubURL, nil)
  201. assert.Equal(t, expected, string(buffer))
  202. }
  203. var sha = "b6dd6210eaebc915fd5be5579c58cce4da2e2579"
  204. var commit = URLJoin(AppSubURL, "commit", sha)
  205. var subtree = URLJoin(commit, "src")
  206. var tree = strings.Replace(subtree, "/commit/", "/tree/", -1)
  207. var src = strings.Replace(subtree, "/commit/", "/src/", -1)
  208. test(sha, `<p><a href="`+commit+`" rel="nofollow">b6dd6210ea</a></p>
  209. `)
  210. test(commit, `<p><a href="`+commit[5:]+`" rel="nofollow">b6dd6210ea</a></p>
  211. `)
  212. test(tree, `<p><a href="`+src[5:]+`" rel="nofollow">b6dd6210ea/src</a></p>
  213. `)
  214. }
  215. func TestRegExp_MentionPattern(t *testing.T) {
  216. trueTestCases := []string{
  217. "@Unknwon",
  218. "@ANT_123",
  219. "@xxx-DiN0-z-A..uru..s-xxx",
  220. " @lol ",
  221. " @Te/st",
  222. }
  223. falseTestCases := []string{
  224. "@ 0",
  225. "@ ",
  226. "@",
  227. "",
  228. "ABC",
  229. }
  230. for _, testCase := range trueTestCases {
  231. res := MentionPattern.MatchString(testCase)
  232. if !res {
  233. println()
  234. println(testCase)
  235. }
  236. assert.True(t, res)
  237. }
  238. for _, testCase := range falseTestCases {
  239. res := MentionPattern.MatchString(testCase)
  240. if res {
  241. println()
  242. println(testCase)
  243. }
  244. assert.False(t, res)
  245. }
  246. }
  247. func TestRegExp_IssueNumericPattern(t *testing.T) {
  248. trueTestCases := []string{
  249. "#1234",
  250. "#0",
  251. "#1234567890987654321",
  252. }
  253. falseTestCases := []string{
  254. "# 1234",
  255. "# 0",
  256. "# ",
  257. "#",
  258. "#ABC",
  259. "#1A2B",
  260. "",
  261. "ABC",
  262. }
  263. for _, testCase := range trueTestCases {
  264. assert.True(t, IssueNumericPattern.MatchString(testCase))
  265. }
  266. for _, testCase := range falseTestCases {
  267. assert.False(t, IssueNumericPattern.MatchString(testCase))
  268. }
  269. }
  270. func TestRegExp_IssueAlphanumericPattern(t *testing.T) {
  271. trueTestCases := []string{
  272. "ABC-1234",
  273. "A-1",
  274. "RC-80",
  275. "ABCDEFGHIJ-1234567890987654321234567890",
  276. }
  277. falseTestCases := []string{
  278. "RC-08",
  279. "PR-0",
  280. "ABCDEFGHIJK-1",
  281. "PR_1",
  282. "",
  283. "#ABC",
  284. "",
  285. "ABC",
  286. "GG-",
  287. "rm-1",
  288. }
  289. for _, testCase := range trueTestCases {
  290. assert.True(t, IssueAlphanumericPattern.MatchString(testCase))
  291. }
  292. for _, testCase := range falseTestCases {
  293. assert.False(t, IssueAlphanumericPattern.MatchString(testCase))
  294. }
  295. }
  296. func TestRegExp_Sha1CurrentPattern(t *testing.T) {
  297. trueTestCases := []string{
  298. "d8a994ef243349f321568f9e36d5c3f444b99cae",
  299. "abcdefabcdefabcdefabcdefabcdefabcdefabcd",
  300. }
  301. falseTestCases := []string{
  302. "test",
  303. "abcdefg",
  304. "abcdefghijklmnopqrstuvwxyzabcdefghijklmn",
  305. "abcdefghijklmnopqrstuvwxyzabcdefghijklmO",
  306. }
  307. for _, testCase := range trueTestCases {
  308. assert.True(t, Sha1CurrentPattern.MatchString(testCase))
  309. }
  310. for _, testCase := range falseTestCases {
  311. assert.False(t, Sha1CurrentPattern.MatchString(testCase))
  312. }
  313. }
  314. func TestRegExp_ShortLinkPattern(t *testing.T) {
  315. trueTestCases := []string{
  316. "[[stuff]]",
  317. "[[]]",
  318. "[[stuff|title=Difficult name with spaces*!]]",
  319. }
  320. falseTestCases := []string{
  321. "test",
  322. "abcdefg",
  323. "[[]",
  324. "[[",
  325. "[]",
  326. "]]",
  327. "abcdefghijklmnopqrstuvwxyz",
  328. }
  329. for _, testCase := range trueTestCases {
  330. assert.True(t, ShortLinkPattern.MatchString(testCase))
  331. }
  332. for _, testCase := range falseTestCases {
  333. assert.False(t, ShortLinkPattern.MatchString(testCase))
  334. }
  335. }
  336. func TestRegExp_AnySHA1Pattern(t *testing.T) {
  337. testCases := map[string][]string{
  338. "https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js#L2703": []string{
  339. "github.com",
  340. "jquery",
  341. "jquery",
  342. "blob",
  343. "a644101ed04d0beacea864ce805e0c4f86ba1cd1",
  344. "test/unit/event.js",
  345. "L2703",
  346. },
  347. "https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js": []string{
  348. "github.com",
  349. "jquery",
  350. "jquery",
  351. "blob",
  352. "a644101ed04d0beacea864ce805e0c4f86ba1cd1",
  353. "test/unit/event.js",
  354. "",
  355. },
  356. "https://github.com/jquery/jquery/commit/0705be475092aede1eddae01319ec931fb9c65fc": []string{
  357. "github.com",
  358. "jquery",
  359. "jquery",
  360. "commit",
  361. "0705be475092aede1eddae01319ec931fb9c65fc",
  362. "",
  363. "",
  364. },
  365. "https://github.com/jquery/jquery/tree/0705be475092aede1eddae01319ec931fb9c65fc/src": []string{
  366. "github.com",
  367. "jquery",
  368. "jquery",
  369. "tree",
  370. "0705be475092aede1eddae01319ec931fb9c65fc",
  371. "src",
  372. "",
  373. },
  374. "https://try.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2": []string{
  375. "try.gogs.io",
  376. "gogs",
  377. "gogs",
  378. "commit",
  379. "d8a994ef243349f321568f9e36d5c3f444b99cae",
  380. "",
  381. "diff-2",
  382. },
  383. }
  384. for k, v := range testCases {
  385. assert.Equal(t, AnySHA1Pattern.FindStringSubmatch(k)[1:], v)
  386. }
  387. }
  388. func TestRegExp_IssueFullPattern(t *testing.T) {
  389. testCases := map[string][]string{
  390. "https://github.com/gogits/gogs/pull/3244": []string{
  391. "github.com/gogits/gogs/pull/",
  392. "3244",
  393. "",
  394. "",
  395. },
  396. "https://github.com/gogits/gogs/issues/3247#issuecomment-231517079": []string{
  397. "github.com/gogits/gogs/issues/",
  398. "3247",
  399. "#issuecomment-231517079",
  400. "",
  401. },
  402. "https://try.gogs.io/gogs/gogs/issues/4#issue-685": []string{
  403. "try.gogs.io/gogs/gogs/issues/",
  404. "4",
  405. "#issue-685",
  406. "",
  407. },
  408. "https://youtrack.jetbrains.com/issue/JT-36485": []string{
  409. "youtrack.jetbrains.com/issue/",
  410. "JT-36485",
  411. "",
  412. "",
  413. },
  414. "https://youtrack.jetbrains.com/issue/JT-36485#comment=27-1508676": []string{
  415. "youtrack.jetbrains.com/issue/",
  416. "JT-36485",
  417. "#comment=27-1508676",
  418. "",
  419. },
  420. }
  421. for k, v := range testCases {
  422. assert.Equal(t, IssueFullPattern.FindStringSubmatch(k)[1:], v)
  423. }
  424. }
  425. func TestMisc_IsMarkdownFile(t *testing.T) {
  426. setting.Markdown.FileExtensions = []string{".md", ".markdown", ".mdown", ".mkd"}
  427. trueTestCases := []string{
  428. "test.md",
  429. "wow.MARKDOWN",
  430. "LOL.mDoWn",
  431. }
  432. falseTestCases := []string{
  433. "test",
  434. "abcdefg",
  435. "abcdefghijklmnopqrstuvwxyz",
  436. "test.md.test",
  437. }
  438. for _, testCase := range trueTestCases {
  439. assert.True(t, IsMarkdownFile(testCase))
  440. }
  441. for _, testCase := range falseTestCases {
  442. assert.False(t, IsMarkdownFile(testCase))
  443. }
  444. }
  445. func TestMisc_IsReadmeFile(t *testing.T) {
  446. trueTestCases := []string{
  447. "readme",
  448. "README",
  449. "readME.mdown",
  450. "README.md",
  451. }
  452. falseTestCases := []string{
  453. "test.md",
  454. "wow.MARKDOWN",
  455. "LOL.mDoWn",
  456. "test",
  457. "abcdefg",
  458. "abcdefghijklmnopqrstuvwxyz",
  459. "test.md.test",
  460. }
  461. for _, testCase := range trueTestCases {
  462. assert.True(t, IsReadmeFile(testCase))
  463. }
  464. for _, testCase := range falseTestCases {
  465. assert.False(t, IsReadmeFile(testCase))
  466. }
  467. }
  468. func TestMisc_IsSameDomain(t *testing.T) {
  469. setting.AppURL = AppURL
  470. setting.AppSubURL = AppSubURL
  471. var sha = "b6dd6210eaebc915fd5be5579c58cce4da2e2579"
  472. var commit = URLJoin(AppSubURL, "commit", sha)
  473. assert.True(t, IsSameDomain(commit))
  474. assert.False(t, IsSameDomain("http://google.com/ncr"))
  475. assert.False(t, IsSameDomain("favicon.ico"))
  476. }
  477. // Test cases without ambiguous links
  478. var sameCases = []string{
  479. // dear imgui wiki markdown extract: special wiki syntax
  480. `Wiki! Enjoy :)
  481. - [[Links, Language bindings, Engine bindings|Links]]
  482. - [[Tips]]
  483. Ideas and codes
  484. - Bezier widget (by @r-lyeh) https://github.com/ocornut/imgui/issues/786
  485. - Node graph editors https://github.com/ocornut/imgui/issues/306
  486. - [[Memory Editor|memory_editor_example]]
  487. - [[Plot var helper|plot_var_example]]`,
  488. // rendered
  489. `<p>Wiki! Enjoy :)</p>
  490. <ul>
  491. <li><a href="` + AppSubURL + `wiki/Links" rel="nofollow">Links, Language bindings, Engine bindings</a></li>
  492. <li><a href="` + AppSubURL + `wiki/Tips" rel="nofollow">Tips</a></li>
  493. </ul>
  494. <p>Ideas and codes</p>
  495. <ul>
  496. <li>Bezier widget (by <a href="` + AppURL + `r-lyeh" rel="nofollow">@r-lyeh</a>)<a href="` + AppSubURL + `issues/786" rel="nofollow">#786</a></li>
  497. <li>Node graph editors<a href="` + AppSubURL + `issues/306" rel="nofollow">#306</a></li>
  498. <li><a href="` + AppSubURL + `wiki/memory_editor_example" rel="nofollow">Memory Editor</a></li>
  499. <li><a href="` + AppSubURL + `wiki/plot_var_example" rel="nofollow">Plot var helper</a></li>
  500. </ul>
  501. `,
  502. // wine-staging wiki home extract: tables, special wiki syntax, images
  503. `## What is Wine Staging?
  504. **Wine Staging** on website [wine-staging.com](http://wine-staging.com).
  505. ## Quick Links
  506. Here are some links to the most important topics. You can find the full list of pages at the sidebar.
  507. | [[images/icon-install.png]] | [[Installation]] |
  508. |--------------------------------|----------------------------------------------------------|
  509. | [[images/icon-usage.png]] | [[Usage]] |
  510. | [[images/icon-config.png]] | [[Configuration]] |
  511. | [[images/icon-bug.png]] | [Bugs](http://bugs.wine-staging.com) |
  512. `,
  513. // rendered
  514. `<h2>What is Wine Staging?</h2>
  515. <p><strong>Wine Staging</strong> on website <a href="http://wine-staging.com" rel="nofollow">wine-staging.com</a>.</p>
  516. <h2>Quick Links</h2>
  517. <p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>
  518. <table>
  519. <thead>
  520. <tr>
  521. <th><a href="` + AppSubURL + `wiki/raw/images%2Ficon-install.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images%2Ficon-install.png" alt="images/icon-install.png" title="icon-install.png"/></a></th>
  522. <th><a href="` + AppSubURL + `wiki/Installation" rel="nofollow">Installation</a></th>
  523. </tr>
  524. </thead>
  525. <tbody>
  526. <tr>
  527. <td><a href="` + AppSubURL + `wiki/raw/images%2Ficon-usage.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images%2Ficon-usage.png" alt="images/icon-usage.png" title="icon-usage.png"/></a></td>
  528. <td><a href="` + AppSubURL + `wiki/Usage" rel="nofollow">Usage</a></td>
  529. </tr>
  530. <tr>
  531. <td><a href="` + AppSubURL + `wiki/raw/images%2Ficon-config.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images%2Ficon-config.png" alt="images/icon-config.png" title="icon-config.png"/></a></td>
  532. <td><a href="` + AppSubURL + `wiki/Configuration" rel="nofollow">Configuration</a></td>
  533. </tr>
  534. <tr>
  535. <td><a href="` + AppSubURL + `wiki/raw/images%2Ficon-bug.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images%2Ficon-bug.png" alt="images/icon-bug.png" title="icon-bug.png"/></a></td>
  536. <td><a href="http://bugs.wine-staging.com" rel="nofollow">Bugs</a></td>
  537. </tr>
  538. </tbody>
  539. </table>
  540. `,
  541. // libgdx wiki page: inline images with special syntax
  542. `[Excelsior JET](http://www.excelsiorjet.com/) allows you to create native executables for Windows, Linux and Mac OS X.
  543. 1. [Package your libGDX application](https://github.com/libgdx/libgdx/wiki/Gradle-on-the-Commandline#packaging-for-the-desktop)
  544. [[images/1.png]]
  545. 2. Perform a test run by hitting the Run! button.
  546. [[images/2.png]]`,
  547. // rendered
  548. `<p><a href="http://www.excelsiorjet.com/" rel="nofollow">Excelsior JET</a> allows you to create native executables for Windows, Linux and Mac OS X.</p>
  549. <ol>
  550. <li><a href="https://github.com/libgdx/libgdx/wiki/Gradle-on-the-Commandline#packaging-for-the-desktop" rel="nofollow">Package your libGDX application</a>
  551. <a href="` + AppSubURL + `wiki/raw/images%2F1.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images%2F1.png" alt="images/1.png" title="1.png"/></a></li>
  552. <li>Perform a test run by hitting the Run! button.
  553. <a href="` + AppSubURL + `wiki/raw/images%2F2.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images%2F2.png" alt="images/2.png" title="2.png"/></a></li>
  554. </ol>
  555. `,
  556. }
  557. func TestTotal_RenderString(t *testing.T) {
  558. for i := 0; i < len(sameCases); i += 2 {
  559. line := RenderString(sameCases[i], AppSubURL, map[string]string{})
  560. assert.Equal(t, sameCases[i+1], line)
  561. }
  562. testCases := []string{}
  563. for i := 0; i < len(testCases); i += 2 {
  564. line := RenderString(testCases[i], AppSubURL, map[string]string{})
  565. assert.Equal(t, testCases[i+1], line)
  566. }
  567. }
  568. func TestTotal_RenderWiki(t *testing.T) {
  569. for i := 0; i < len(sameCases); i += 2 {
  570. line := RenderWiki([]byte(sameCases[i]), AppSubURL, map[string]string{})
  571. assert.Equal(t, sameCases[i+1], line)
  572. }
  573. testCases := []string{
  574. // Guard wiki sidebar: special syntax
  575. `[[Guardfile-DSL / Configuring-Guard|Guardfile-DSL---Configuring-Guard]]`,
  576. // rendered
  577. `<p><a href="` + AppSubURL + `wiki/Guardfile-DSL---Configuring-Guard" rel="nofollow">Guardfile-DSL / Configuring-Guard</a></p>
  578. `,
  579. // special syntax
  580. `[[Name|Link]]`,
  581. // rendered
  582. `<p><a href="` + AppSubURL + `wiki/Link" rel="nofollow">Name</a></p>
  583. `,
  584. }
  585. for i := 0; i < len(testCases); i += 2 {
  586. line := RenderWiki([]byte(testCases[i]), AppSubURL, map[string]string{})
  587. assert.Equal(t, testCases[i+1], line)
  588. }
  589. }