@ecency/render-helper 2.2.14 → 2.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAiC;AACjC,6DAA0C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAiC;AACjC,6DAA0C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecency/render-helper",
3
- "version": "2.2.14",
3
+ "version": "2.2.17",
4
4
  "description": "Markdown+Html Render helper",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -1,4 +1,5 @@
1
1
  export * from './white-list.const'
2
+ export * from './section-list.const'
2
3
  export * from './regexes.const'
3
4
  export * from './allowed-attributes.const'
4
5
  export * from './dom-parser.const'
@@ -8,7 +8,7 @@ export const MENTION_REGEX = /^https?:\/\/(.*)\/(@[\w.\d-]+)$/i
8
8
  export const TOPIC_REGEX = /^https?:\/\/(.*)\/(trending|hot|created|promoted|muted|payout)\/(.*)$/i
9
9
  export const INTERNAL_MENTION_REGEX = /^\/@[\w.\d-]+$/i
10
10
  export const INTERNAL_TOPIC_REGEX = /^\/(trending|hot|created|promoted|muted|payout)\/(.*)$/i
11
- export const INTERNAL_POST_TAG_REGEX = /\/(.*)\/(@[\w.\d-]+)\/(.*)/i
11
+ export const INTERNAL_POST_TAG_REGEX = /(.*)\/(@[\w.\d-]+)\/(.*)/i
12
12
  export const INTERNAL_POST_REGEX = /^\/(@[\w.\d-]+)\/(.*)$/i
13
13
  export const CUSTOM_COMMUNITY_REGEX = /^https?:\/\/(.*)\/c\/(hive-\d+)(.*)/i
14
14
  export const YOUTUBE_REGEX = /(?:youtube.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu.be\/)([^"&?\/\s]{11})/g
@@ -39,4 +39,5 @@ export const BRAND_NEW_TUBE_REGEX = /^https:\/\/brandnewtube\.com\/embed\/[a-z0-
39
39
  export const LOOM_REGEX = /^(https?:)?\/\/www.loom.com\/share\/(.*)/i
40
40
  export const LOOM_EMBED_REGEX = /^(https?:)?\/\/www.loom.com\/embed\/(.*)/i
41
41
  export const AUREAL_EMBED_REGEX = /^(https?:\/\/)?(www\.)?(?:aureal-embed)\.web\.app\/([0-9]+)/i
42
- export const ENTITY_REGEX = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/ig;
42
+ export const ENTITY_REGEX = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/ig
43
+ export const SECTION_REGEX = /\B(\#[\da-zA-Z-_]+\b)(?!;)/i
@@ -0,0 +1,15 @@
1
+ export const SECTION_LIST = [
2
+ 'wallet',
3
+ 'feed',
4
+ 'followers',
5
+ 'following',
6
+ 'points',
7
+ 'communities',
8
+ 'posts',
9
+ 'blog',
10
+ 'comments',
11
+ 'replies',
12
+ 'settings',
13
+ 'engine',
14
+ 'permissions'
15
+ ]
@@ -99,6 +99,30 @@ describe('Markdown2Html', () => {
99
99
  expect(markdown2Html(input)).toBe(expected)
100
100
  })
101
101
 
102
+ it('7.1- Should handle raw d.tube videos without thumbnail', () => {
103
+ const input = {
104
+ author: 'foo37.1',
105
+ permlink: 'bar37.1',
106
+ last_update: '2020-05-10T09:15:21',
107
+ body: 'https://d.tube/#!/v/techcoderx/QmVdEYicJwiTxSk2U9ER1Yc8Rumb1Nek4KynqAYGyQs7ga'
108
+ }
109
+ const expected = '<p><a class="markdown-video-link markdown-video-link-dtube" data-embed-src="https://emb.d.tube/#!/techcoderx/QmVdEYicJwiTxSk2U9ER1Yc8Rumb1Nek4KynqAYGyQs7ga"><span class="markdown-video-play"></span></a></p>'
110
+
111
+ expect(markdown2Html(input)).toBe(expected)
112
+ })
113
+
114
+ it('7.2- Should handle raw d.tube videos different format', () => {
115
+ const input = {
116
+ author: 'foo37.2',
117
+ permlink: 'bar37.2',
118
+ last_update: '2020-05-10T09:15:21',
119
+ body: 'https://d.tube/v/techcoderx/QmVdEYicJwiTxSk2U9ER1Yc8Rumb1Nek4KynqAYGyQs7ga'
120
+ }
121
+ const expected = '<p><a class="markdown-video-link markdown-video-link-dtube" data-embed-src="https://emb.d.tube/#!/techcoderx/QmVdEYicJwiTxSk2U9ER1Yc8Rumb1Nek4KynqAYGyQs7ga"><span class="markdown-video-play"></span></a></p>'
122
+
123
+ expect(markdown2Html(input)).toBe(expected)
124
+ })
125
+
102
126
  it('9- Should handle witnesses links', () => {
103
127
  const input = {
104
128
  author: 'foo39',
@@ -620,7 +644,7 @@ describe('Markdown2Html', () => {
620
644
  expect(markdown2Html(input)).toBe(expected)
621
645
  })
622
646
 
623
- it('43- Should handle dtube iframe', () => {
647
+ it('43 - Should handle dtube iframe', () => {
624
648
  const input = {
625
649
  author: 'foo343',
626
650
  permlink: 'bar343',
@@ -632,7 +656,7 @@ describe('Markdown2Html', () => {
632
656
  expect(markdown2Html(input)).toBe(expected)
633
657
  })
634
658
 
635
- it('44- Should handle vimm iframe', () => {
659
+ it('44 - Should handle vimm iframe', () => {
636
660
  const input = {
637
661
  author: 'foo344',
638
662
  permlink: 'bar344',
@@ -656,7 +680,7 @@ describe('Markdown2Html', () => {
656
680
  expect(markdown2Html(input)).toBe(expected)
657
681
  })
658
682
 
659
- it('46- Should handle copied md links', () => {
683
+ it('46 - Should handle copied md links', () => {
660
684
  const input = {
661
685
  author: 'foo346',
662
686
  permlink: 'bar346',
@@ -668,7 +692,7 @@ describe('Markdown2Html', () => {
668
692
  expect(markdown2Html(input)).toBe(expected)
669
693
  })
670
694
 
671
- it('47- Should handle internal links', () => {
695
+ it('47 - Should handle internal links', () => {
672
696
  const input = {
673
697
  author: 'foo347',
674
698
  permlink: 'bar347',
@@ -878,10 +902,10 @@ describe('Markdown2Html', () => {
878
902
  expect(markdown2Html(input, false)).toBe(expected)
879
903
  })
880
904
 
881
- it('65- Should handle youtube.com/embed videos', () => {
905
+ it('65 - Should handle youtube.com/embed videos', () => {
882
906
  const input = {
883
- author: 'foo329',
884
- permlink: 'bar329',
907
+ author: 'foo365',
908
+ permlink: 'bar365',
885
909
  last_update: '2019-05-10T09:15:21',
886
910
  body: 'https://www.youtube.com/embed/UuyS7YAkECA?start=295&autoplay=1'
887
911
  }
@@ -889,6 +913,42 @@ describe('Markdown2Html', () => {
889
913
 
890
914
  expect(markdown2Html(input)).toBe(expected)
891
915
  })
916
+
917
+ it('66 - Should handle internal links with params', () => {
918
+ const input = {
919
+ author: 'foo366',
920
+ permlink: 'bar366',
921
+ last_update: '2019-05-10T09:15:21',
922
+ body: 'direct link https://ecency.com/@ecency/faq?history'
923
+ }
924
+ const expected = '<p>direct link <a class=\"markdown-post-link\" data-tag=\"post\" data-author=\"ecency\" data-permlink=\"faq?history\">@ecency/faq?history</a></p>'
925
+
926
+ expect(markdown2Html(input)).toBe(expected)
927
+ })
928
+
929
+ it('67 - Should handle section links with params', () => {
930
+ const input = {
931
+ author: 'foo367',
932
+ permlink: 'bar367',
933
+ last_update: '2019-05-10T09:15:21',
934
+ body: 'direct link https://ecency.com/@ecency/posts?q=games'
935
+ }
936
+ const expected = '<p>direct link <a href=\"https://ecency.com/@ecency/posts?q=games\" class=\"markdown-profile-link\">@ecency/posts?q=games</a></p>'
937
+
938
+ expect(markdown2Html(input)).toBe(expected)
939
+ })
940
+
941
+ it('68 - Should handle section links', () => {
942
+ const input = {
943
+ author: 'foo368',
944
+ permlink: 'bar368',
945
+ last_update: '2019-05-10T09:15:21',
946
+ body: 'this is link [What is HIVE](#WhatHive) and locatino ## 1 <a data-id="WhatHive"></a>What is HIVE?'
947
+ }
948
+ const expected = '<p>this is link <a href=\"#WhatHive\" class=\"markdown-internal-link\">What is HIVE</a> and locatino ## 1 <a data-id=\"WhatHive\"></a>What is HIVE?</p>'
949
+
950
+ expect(markdown2Html(input, false)).toBe(expected)
951
+ })
892
952
  })
893
953
 
894
954
  describe("Rumble support", () => {
@@ -23,7 +23,9 @@ import {
23
23
  RUMBLE_REGEX,
24
24
  BRIGHTEON_REGEX,
25
25
  DOMParser,
26
- LOOM_REGEX
26
+ LOOM_REGEX,
27
+ SECTION_REGEX,
28
+ SECTION_LIST
27
29
  } from '../consts'
28
30
  import { getSerializedInnerHTML } from './get-inner-html.method'
29
31
  import { proxifyImageSrc } from '../proxify-image-src'
@@ -139,9 +141,10 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
139
141
  // If a tagged post and profile section links
140
142
  const tpostMatch = href.match(INTERNAL_POST_TAG_REGEX)
141
143
  if (
142
- (tpostMatch && WHITE_LIST.includes(tpostMatch[1].substring(1))) || (tpostMatch && tpostMatch.length === 4 && tpostMatch[1].indexOf('/') !== 0)
144
+ (tpostMatch && tpostMatch.length === 4 && WHITE_LIST.some(v => tpostMatch[1].includes(v))) || (tpostMatch && tpostMatch.length === 4 && tpostMatch[1].indexOf('/') == 0)
143
145
  ) {
144
- if (['wallet', 'feed', 'followers', 'following', 'points', 'communities', 'posts', 'blog', 'comments', 'replies', 'settings', 'engine'].includes(tpostMatch[3])) {
146
+ // check if permlink is section or section with params ?q=xyz
147
+ if (SECTION_LIST.some(v => tpostMatch[3].includes(v))) {
145
148
  el.setAttribute('class', 'markdown-profile-link')
146
149
  const author = tpostMatch[2].replace('@', '').toLowerCase()
147
150
  const section = tpostMatch[3]
@@ -158,13 +161,18 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
158
161
  }
159
162
  return
160
163
  } else {
161
- el.setAttribute('class', 'markdown-post-link')
162
-
164
+ // check if domain is not whitelist and does contain dot (not tag e.g. `/ecency`)
165
+ if (tpostMatch[1] && tpostMatch[1].includes('.') && !WHITE_LIST.some(v => tpostMatch[1].includes(v))) {
166
+ return
167
+ }
163
168
  let tag = 'post'
164
- if (!WHITE_LIST.includes(tpostMatch[1].substring(1))) {
169
+ // check if tag does exist and doesn't include dot likely word/tag
170
+ if (tpostMatch[1] && !tpostMatch[1].includes('.')) {
165
171
  [, tag] = tpostMatch
172
+ tag = tag.replace('/', '')
166
173
  }
167
174
 
175
+ el.setAttribute('class', 'markdown-post-link')
168
176
  const author = tpostMatch[2].replace('@', '')
169
177
  const permlink = tpostMatch[3]
170
178
  if (el.textContent === href) {
@@ -210,7 +218,7 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
210
218
  if (
211
219
  (cpostMatch && cpostMatch.length === 3 && cpostMatch[1].indexOf('@') === 0)
212
220
  ) {
213
- if (['wallet', 'feed', 'followers', 'following', 'points', 'communities', 'posts', 'blog', 'comments', 'replies', 'settings', 'engine'].includes(cpostMatch[2])) {
221
+ if (SECTION_LIST.some(v => cpostMatch[2].includes(v))) {
214
222
  el.setAttribute('class', 'markdown-profile-link')
215
223
  const author = cpostMatch[1].replace('@', '').toLowerCase()
216
224
  const section = cpostMatch[2]
@@ -539,37 +547,46 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
539
547
  // If a d.tube video
540
548
  match = href.match(D_TUBE_REGEX)
541
549
  if (match) {
542
- // Only d.tube links contains an image
543
- const imgEls = el.getElementsByTagName('img')
544
550
 
545
- if (imgEls.length === 1) {
551
+ // Only d.tube links contains an image
552
+ const imgEls = el.getElementsByTagName('img')
553
+
554
+ if (imgEls.length === 1 || el.textContent.trim() === href) {
546
555
  const e = D_TUBE_REGEX.exec(href)
547
556
  // e[2] = username, e[3] object id
548
557
  if (e[2] && e[3]) {
549
558
  el.setAttribute('class', 'markdown-video-link markdown-video-link-dtube')
550
559
  el.removeAttribute('href')
560
+
551
561
 
552
- const thumbnail = proxifyImageSrc(imgEls[0].getAttribute('src').replace(/\s+/g, ''), 0, 0, webp ? 'webp' : 'match')
553
562
  const videoHref = `https://emb.d.tube/#!/${e[2]}/${e[3]}`
554
563
 
555
564
  // el.setAttribute('data-video-href', videoHref)
556
565
  el.setAttribute('data-embed-src', videoHref)
557
566
 
558
- const thumbImg = el.ownerDocument.createElement('img')
559
- thumbImg.setAttribute('class', 'no-replace video-thumbnail')
560
- thumbImg.setAttribute('itemprop', 'thumbnailUrl')
561
-
562
- thumbImg.setAttribute('src', thumbnail)
567
+ //process thumb img element
568
+ if (imgEls.length === 1) {
569
+ const thumbnail = proxifyImageSrc(imgEls[0].getAttribute('src').replace(/\s+/g, ''), 0, 0, webp ? 'webp' : 'match')
570
+ const thumbImg = el.ownerDocument.createElement('img')
571
+
572
+ thumbImg.setAttribute('class', 'no-replace video-thumbnail')
573
+ thumbImg.setAttribute('itemprop', 'thumbnailUrl')
574
+
575
+ thumbImg.setAttribute('src', thumbnail)
576
+ el.appendChild(thumbImg)
577
+
578
+ // Remove image.
579
+ el.removeChild(imgEls[0])
580
+ } else {
581
+ el.textContent = '';
582
+ }
563
583
 
564
584
  const play = el.ownerDocument.createElement('span')
565
585
  play.setAttribute('class', 'markdown-video-play')
566
586
 
567
- el.appendChild(thumbImg)
587
+
568
588
  el.appendChild(play)
569
589
 
570
- // Remove image.
571
- el.removeChild(imgEls[0])
572
-
573
590
  return
574
591
  }
575
592
  }
@@ -581,6 +598,7 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
581
598
  if (e[2] && e[3]) {
582
599
  el.setAttribute('class', 'markdown-video-link markdown-video-link-dtube')
583
600
  el.removeAttribute('href')
601
+ el.textContent = '';
584
602
 
585
603
  const videoHref = `https://emb.d.tube/#!/${e[2]}/${e[3]}`
586
604
 
@@ -590,6 +608,7 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
590
608
  play.setAttribute('class', 'markdown-video-play')
591
609
 
592
610
  el.appendChild(play)
611
+
593
612
 
594
613
  return
595
614
  }
@@ -688,12 +707,12 @@ export function a(el: HTMLElement, forApp: boolean, webp: boolean): void {
688
707
  }
689
708
  el.removeAttribute('href')
690
709
  } else {
691
- const externalRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
692
- if(externalRegex.test(href)) {
710
+ const matchS = href.match(SECTION_REGEX)
711
+ if(matchS) {
712
+ el.setAttribute('class', 'markdown-internal-link');
713
+ } else {
693
714
  el.setAttribute('target', '_blank');
694
715
  el.setAttribute('rel', 'noopener');
695
- } else {
696
- el.setAttribute('class', 'markdown-internal-link')
697
716
  }
698
717
  }
699
718
  }
@@ -1,4 +1,4 @@
1
- import { IMG_REGEX } from '../consts'
1
+ import { IMG_REGEX, SECTION_LIST } from '../consts'
2
2
  import { proxifyImageSrc } from '../proxify-image-src'
3
3
 
4
4
  export function linkify(content: string, forApp: boolean, webp: boolean): string {
@@ -34,7 +34,7 @@ export function linkify(content: string, forApp: boolean, webp: boolean): string
34
34
  /((^|\s)(\/|)@[\w.\d-]+)\/(\S+)/gi, (match, u, p1, p2, p3) => {
35
35
  const uu = u.trim().toLowerCase().replace('/@','').replace('@','');
36
36
  const perm = p3;
37
- if (['wallet', 'feed', 'followers', 'following', 'points', 'communities', 'posts', 'blog', 'comments', 'replies', 'settings', 'engine'].includes(p3)) {
37
+ if (SECTION_LIST.some(v => p3.includes(v))) {
38
38
  const attrs = forApp ? `https://ecency.com/@${uu}/${perm}` : `href="/@${uu}/${perm}"`
39
39
  return ` <a class="markdown-profile-link" ${attrs}>@${uu}/${perm}</a>`
40
40
  } else {