linkExpander.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. export default {
  2. install (Vue) {
  3. //Takes a HTML string then parses it and replaces appropriate
  4. //links with the relevant expansion
  5. //Returns a callback with the 'expanded' HTML string
  6. Vue.prototype.$linkExpander = function (HTML, cb) {
  7. let parsed = document.createElement('div');
  8. parsed.innerHTML = HTML;
  9. let expandPatterns = {
  10. 'wikipedia': {
  11. hostnameRegExp: /[a-z]+\.wikipedia\.org/,
  12. pathnameRegExp: /\/wiki\/.+/,
  13. getURL (link) {
  14. let page = link.pathname.split('/').slice(-1)[0];
  15. let countryVersion = link.hostname.split('.')[0];
  16. return `https://${countryVersion}.wikipedia.org/api/rest_v1/page/summary/${page}?redirect=true`;
  17. },
  18. getContent (link, data) {
  19. let content = data.extract.slice(0, 500).trim();
  20. return {
  21. title: data.titles.display,
  22. URL: data.content_urls.desktop.page,
  23. content: content.length > 500 ? content + '...' : content
  24. }
  25. }
  26. },
  27. 'github': {
  28. hostnameRegExp: /github\.com/,
  29. pathnameRegExp: /\/.+\/.+/,
  30. getURL (link) {
  31. return 'https://api.github.com/repos' + link.pathname;
  32. },
  33. getContent (link, data) {
  34. return {
  35. title: data.full_name,
  36. URL: data.html_url,
  37. content: data.description
  38. }
  39. }
  40. }
  41. };
  42. let links = Array
  43. .from(parsed.querySelectorAll('p a[href]'))
  44. .filter(a => {
  45. return (
  46. a.parentNode.parentNode === parsed &&
  47. a.parentNode.childNodes.length === 1 &&
  48. a.innerHTML === a.href
  49. )
  50. });
  51. let expandableLinks = {};
  52. links.forEach(link => {
  53. for(let expandName in expandPatterns) {
  54. let expand = expandPatterns[expandName];
  55. if(
  56. expand.hostnameRegExp.test(link.hostname) &&
  57. expand.pathnameRegExp.test(link.pathname)
  58. ) {
  59. if(!expandableLinks[expandName]) {
  60. expandableLinks[expandName] = [];
  61. }
  62. expandableLinks[expandName].push(link);
  63. break;
  64. }
  65. }
  66. });
  67. for(let expandName in expandableLinks) {
  68. let expandPattern = expandPatterns[expandName];
  69. expandableLinks[expandName].forEach(link => {
  70. let URL = expandPattern.getURL(link);
  71. Vue.axios
  72. .get(URL)
  73. .then(res => {
  74. let content = expandPattern.getContent(link, res.data);
  75. let h = document.createElement.bind(document);
  76. let div = h('div');
  77. let h2 = h('h2');
  78. let a = h('a');
  79. let span = h('span');
  80. let textNode = document.createTextNode(content.content);
  81. a.textContent = content.title;
  82. a.href = content.URL;
  83. a.setAttribute('target', '_blank');
  84. a.setAttribute('rel', 'noopener noreferrer');
  85. span.textContent = 'from ' + link.hostname;
  86. h2.appendChild(a);
  87. h2.appendChild(span);
  88. div.appendChild(h2)
  89. div.appendChild(textNode)
  90. div.classList.add('expanded_link');
  91. link.parentNode.replaceChild(div, link);
  92. completedAPICall();
  93. })
  94. .catch(completedAPICall);
  95. });
  96. }
  97. let completed = 0;
  98. let completedAPICall = () => {
  99. completed++;
  100. if(completed === links.length) {
  101. cb(parsed.innerHTML);
  102. }
  103. }
  104. }
  105. }
  106. }