Linker.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. const types = {
  2. markdownLink: 'mdLink',
  3. growiLink: 'growiLink',
  4. pukiwikiLink: 'pukiwikiLink',
  5. }
  6. // const isApplyPukiwikiLikeLinkerPlugin = window.growiRenderer.preProcessors.some(process => process.constructor.name === 'PukiwikiLikeLinker');
  7. const isApplyPukiwikiLikeLinkerPlugin = true;
  8. export default class Linker {
  9. constructor(type, label, link) {
  10. this.type = type;
  11. this.label = label;
  12. this.link = link;
  13. }
  14. // create an instance of Linker from string
  15. static fromMarkdownString(str) {
  16. // if str doesn't mean a linker, create a link whose label is str
  17. let label=str;
  18. let link='';
  19. let type=types.markdownLink;
  20. // pukiwiki
  21. // https://regex101.com/r/2fNmUN/1
  22. if (str.match(/^\[\[.*\]\]$/) && isApplyPukiwikiLikeLinkerPlugin) {
  23. type = types.pukiwikiLink;
  24. const value = str.slice(2, -2);
  25. const indexOfSplit = value.lastIndexOf('>');
  26. if (indexOfSplit < 0) {
  27. label = value;
  28. link = value;
  29. }
  30. label = value.slice(0, indexOfSplit);
  31. link = value.slice(indexOfSplit + 1);
  32. }
  33. // growi
  34. // https://regex101.com/r/DJfkYf/1
  35. else if (str.match(/^\[\/.*\]$/)) {
  36. type = types.growiLink;
  37. const value = str.slice(1, -1);
  38. label = value;
  39. link = value;
  40. }
  41. // markdown
  42. // https://regex101.com/r/DZCKP3/1
  43. else if (str.match(/^\[.*\]\(.*\)$/)) {
  44. type = types.markdownLink;
  45. const value = str.slice(1, -1);
  46. const indexOfSplit = value.lastIndexOf('](');
  47. label = value.slice(0, indexOfSplit);
  48. link = value.slice(indexOfSplit + 2);
  49. }
  50. return new Linker(type, label, link);
  51. }
  52. // create an instance of Linker from text with index
  53. static fromLineWithIndex(line, index) {
  54. const { beginningOfLink, endOfLink } = this.getBeginningAndEndIndexOfLink(line, index);
  55. // if index is in a link, extract it from line
  56. let linkStr = '';
  57. if (beginningOfLink >= 0 && endOfLink >= 0) {
  58. linkStr = line.substring(beginningOfLink, endOfLink);
  59. }
  60. return this.fromMarkdownString(linkStr);
  61. }
  62. // return beginning and end indexies of link
  63. // if index is not in a link, return { beginningOfLink: -1, endOfLink: -1 }
  64. static getBeginningAndEndIndexOfLink(line, index) {
  65. let beginningOfLink, endOfLink;
  66. // pukiwiki link ('[[link]]')
  67. if (isApplyPukiwikiLikeLinkerPlugin) {
  68. [beginningOfLink, endOfLink] = this.getBeginningAndEndIndexWithPrefixAndSuffix(line, index, '[[', ']]');
  69. }
  70. // if index is not in a pukiwiki link
  71. // growi link ('[/link]')
  72. if (beginningOfLink < 0 || endOfLink < 0 || beginningOfLink > index || endOfLink < index){
  73. [beginningOfLink, endOfLink] = this.getBeginningAndEndIndexWithPrefixAndSuffix(line, index, '[/', ']');
  74. }
  75. // and if index is not in a growi link
  76. // markdown link ('[label](link)')
  77. if (beginningOfLink < 0 || endOfLink < 0 || beginningOfLink > index || endOfLink < index){
  78. [beginningOfLink, endOfLink] = this.getBeginningAndEndIndexWithPrefixAndSuffix(line, index, '[', ')', '](');
  79. }
  80. // and if index is not in a markdown link
  81. // return { beginningOfLink: -1, endOfLink: -1 }
  82. if (beginningOfLink < 0 || endOfLink < 0 || beginningOfLink > index || endOfLink < index) {
  83. [beginningOfLink, endOfLink] = [-1, -1];
  84. };
  85. return { beginningOfLink, endOfLink };
  86. }
  87. // return begin and end indexies as array only when index is between prefix and suffix and link contains containText.
  88. static getBeginningAndEndIndexWithPrefixAndSuffix(line, index, prefix, suffix, containText='') {
  89. const beginningIndex = line.lastIndexOf(prefix, index);
  90. const IndexOfContainText = line.indexOf(containText, beginningIndex + prefix.length);
  91. const endIndex = line.indexOf(suffix, IndexOfContainText + containText.length);
  92. if (beginningIndex < 0 || IndexOfContainText < 0 || endIndex < 0) {
  93. return [-1, -1];
  94. }
  95. return [beginningIndex, endIndex + suffix.length];
  96. }
  97. }