@diplodoc/transform 4.34.0 → 4.35.0-beta1

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.
Files changed (44) hide show
  1. package/dist/css/_yfm-only.css.map +2 -2
  2. package/dist/css/_yfm-only.min.css.map +2 -2
  3. package/dist/css/base.css.map +2 -2
  4. package/dist/css/base.min.css.map +2 -2
  5. package/dist/css/print.css.map +2 -2
  6. package/dist/css/yfm.css.map +2 -2
  7. package/dist/css/yfm.min.css.map +2 -2
  8. package/dist/js/base.js +2 -2
  9. package/dist/js/base.js.map +1 -1
  10. package/dist/js/base.min.js +1 -1
  11. package/dist/js/base.min.js.map +2 -2
  12. package/dist/js/yfm.js +5 -5
  13. package/dist/js/yfm.js.map +1 -1
  14. package/dist/js/yfm.min.js +1 -1
  15. package/dist/js/yfm.min.js.map +2 -2
  16. package/lib/md.d.ts +2 -2
  17. package/lib/md.js +2 -2
  18. package/lib/plugins/csp.d.ts +6 -0
  19. package/lib/plugins/csp.js +26 -0
  20. package/lib/plugins/csp.js.map +1 -0
  21. package/lib/plugins/utils.d.ts +1 -0
  22. package/lib/plugins/utils.js +10 -1
  23. package/lib/plugins/utils.js.map +1 -1
  24. package/lib/plugins/video/const.d.ts +8 -1
  25. package/lib/plugins/video/const.js +4 -0
  26. package/lib/plugins/video/const.js.map +1 -1
  27. package/lib/plugins/video/index.js +10 -3
  28. package/lib/plugins/video/index.js.map +1 -1
  29. package/lib/plugins/video/parsers.d.ts +3 -1
  30. package/lib/plugins/video/parsers.js +59 -28
  31. package/lib/plugins/video/parsers.js.map +1 -1
  32. package/lib/plugins/video/types.d.ts +6 -27
  33. package/lib/plugins/video/utils.js +4 -0
  34. package/lib/plugins/video/utils.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/transform/index.ts +2 -2
  37. package/src/transform/md.ts +2 -2
  38. package/src/transform/plugins/changelog/collect.ts +2 -2
  39. package/src/transform/plugins/utils.ts +16 -0
  40. package/src/transform/plugins/video/const.ts +11 -0
  41. package/src/transform/plugins/video/index.ts +13 -3
  42. package/src/transform/plugins/video/parsers.ts +63 -28
  43. package/src/transform/plugins/video/types.ts +8 -7
  44. package/src/transform/plugins/video/utils.ts +4 -0
@@ -20,6 +20,10 @@ const videoUrl = (service, videoID, options) => {
20
20
  return `https://runtime.video.cloud.yandex.net/player/video/${videoID}`;
21
21
  case 'vk':
22
22
  return `https://vk.com/video_ext.php?${videoID}`;
23
+ case 'rutube':
24
+ return `https://rutube.ru/play/embed/${videoID}`;
25
+ case 'dzen':
26
+ return `https://dzen.ru/video/watch/${videoID}`;
23
27
  default:
24
28
  return service;
25
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/transform/plugins/video/utils.ts"],"names":[],"mappings":";;;AAEO,MAAM,QAAQ,GAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC9D,QAAQ,OAAO,EAAE;QACb,KAAK,SAAS;YACV,OAAO,iCAAiC,OAAO,EAAE,CAAC;QACtD,KAAK,OAAO;YACR,OAAO,kCAAkC,OAAO,EAAE,CAAC;QACvD,KAAK,MAAM;YACP,OAAO,qBAAqB,OAAO,UAAU,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACtE,KAAK,OAAO;YACR,OAAO,CACH,2BAA2B,OAAO,EAAE;gBACpC,8EAA8E;gBAC9E,+GAA+G;gBAC/G,0DAA0D,CAC7D,CAAC;QACN,KAAK,KAAK;YACN,OAAO,gDAAgD,OAAO,mBAAmB,CAAC;QACtF,KAAK,QAAQ;YACT,OAAO,uDAAuD,OAAO,EAAE,CAAC;QAC5E,KAAK,IAAI;YACL,OAAO,gCAAgC,OAAO,EAAE,CAAC;QACrD;YACI,OAAO,OAAO,CAAC;KACtB;AACL,CAAC,CAAC;AAxBW,QAAA,QAAQ,YAwBnB"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/transform/plugins/video/utils.ts"],"names":[],"mappings":";;;AAEO,MAAM,QAAQ,GAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC9D,QAAQ,OAAO,EAAE;QACb,KAAK,SAAS;YACV,OAAO,iCAAiC,OAAO,EAAE,CAAC;QACtD,KAAK,OAAO;YACR,OAAO,kCAAkC,OAAO,EAAE,CAAC;QACvD,KAAK,MAAM;YACP,OAAO,qBAAqB,OAAO,UAAU,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACtE,KAAK,OAAO;YACR,OAAO,CACH,2BAA2B,OAAO,EAAE;gBACpC,8EAA8E;gBAC9E,+GAA+G;gBAC/G,0DAA0D,CAC7D,CAAC;QACN,KAAK,KAAK;YACN,OAAO,gDAAgD,OAAO,mBAAmB,CAAC;QACtF,KAAK,QAAQ;YACT,OAAO,uDAAuD,OAAO,EAAE,CAAC;QAC5E,KAAK,IAAI;YACL,OAAO,gCAAgC,OAAO,EAAE,CAAC;QACrD,KAAK,QAAQ;YACT,OAAO,gCAAgC,OAAO,EAAE,CAAC;QACrD,KAAK,MAAM;YACP,OAAO,+BAA+B,OAAO,EAAE,CAAC;QACpD;YACI,OAAO,OAAO,CAAC;KACtB;AACL,CAAC,CAAC;AA5BW,QAAA,QAAQ,YA4BnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diplodoc/transform",
3
- "version": "4.34.0",
3
+ "version": "4.35.0-beta1",
4
4
  "description": "A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML",
5
5
  "keywords": [
6
6
  "markdown",
@@ -4,7 +4,7 @@ import {bold} from 'chalk';
4
4
 
5
5
  import {log} from './log';
6
6
  import liquidSnippet from './liquid';
7
- import initMarkdownit from './md';
7
+ import initMarkdownIt from './md';
8
8
 
9
9
  function applyLiquid(input: string, options: OptionsType) {
10
10
  const {
@@ -36,7 +36,7 @@ function emitResult(html: string, env: EnvType): OutputType {
36
36
  // eslint-disable-next-line consistent-return
37
37
  function transform(originInput: string, options: OptionsType = {}) {
38
38
  const input = applyLiquid(originInput, options);
39
- const {parse, compile, env} = initMarkdownit(options);
39
+ const {parse, compile, env} = initMarkdownIt(options);
40
40
 
41
41
  try {
42
42
  return emitResult(compile(parse(input)), env);
@@ -12,7 +12,7 @@ import extractTitle from './title';
12
12
  import getHeadings from './headings';
13
13
  import sanitizeHtml from './sanitize';
14
14
 
15
- function initMarkdownit(options: OptionsType) {
15
+ function initMarkdownIt(options: OptionsType) {
16
16
  const {
17
17
  allowHTML = false,
18
18
  linkify = false,
@@ -172,4 +172,4 @@ function initCompiler(md: MarkdownIt, options: OptionsType, env: EnvType) {
172
172
  };
173
173
  }
174
174
 
175
- export = initMarkdownit;
175
+ export = initMarkdownIt;
@@ -1,6 +1,6 @@
1
1
  import {bold} from 'chalk';
2
2
 
3
- import initMarkdownit from '../../md';
3
+ import initMarkdownIt from '../../md';
4
4
  import imsize from '../imsize';
5
5
  import {MarkdownItPluginOpts} from '../typings';
6
6
 
@@ -12,7 +12,7 @@ const BLOCK_START = '{% changelog %}';
12
12
  const BLOCK_END = '{% endchangelog %}';
13
13
 
14
14
  function parseChangelogs(str: string, path?: string) {
15
- const {parse, compile, env} = initMarkdownit({
15
+ const {parse, compile, env} = initMarkdownIt({
16
16
  plugins: [changelogPlugin, imsize],
17
17
  extractChangelogs: true,
18
18
  path,
@@ -37,3 +37,19 @@ export const сarriage = platform === 'win32' ? '\r\n' : '\n';
37
37
  export function generateID() {
38
38
  return Math.random().toString(36).substr(2, 8);
39
39
  }
40
+
41
+ export function append<T extends Record<string, []>, Key extends keyof T>(
42
+ target: T,
43
+ key: Key,
44
+ ...values: T[Key]
45
+ ) {
46
+ if (!target[key]) {
47
+ target[key] = values;
48
+
49
+ return;
50
+ }
51
+
52
+ values.forEach((value) => target[key].push(value));
53
+
54
+ return target;
55
+ }
@@ -11,8 +11,17 @@ export enum VideoService {
11
11
  Osf = 'osf',
12
12
  Yandex = 'yandex',
13
13
  Vk = 'vk',
14
+ Rutube = 'rutube',
15
+ Dzen = 'dzen',
14
16
  }
15
17
 
18
+ export type Service = {
19
+ csp?: Record<string, string[]>;
20
+ extract(url: string): string;
21
+ };
22
+
23
+ export type Services = [VideoService, Service][];
24
+
16
25
  export const defaults: VideoFullOptions = {
17
26
  url: videoUrl,
18
27
  youtube: {width: 640, height: 390},
@@ -22,4 +31,6 @@ export const defaults: VideoFullOptions = {
22
31
  osf: {width: '100%', height: '100%'},
23
32
  yandex: {width: 640, height: 390},
24
33
  vk: {width: 640, height: 390},
34
+ dzen: {width: 640, height: 390},
35
+ rutube: {width: 640, height: 390},
25
36
  };
@@ -5,6 +5,8 @@
5
5
  // Process @[osf](guid)
6
6
  // Process @[yandex](videoID)
7
7
  // Process @[vk](videoID)
8
+ // Process @[dzen](videoID)
9
+ // Process @[rutube](videoID)
8
10
 
9
11
  import type MarkdownIt from 'markdown-it';
10
12
  // eslint-disable-next-line no-duplicate-imports
@@ -13,6 +15,8 @@ import type ParserInline from 'markdown-it/lib/parser_inline';
13
15
  import type Renderer from 'markdown-it/lib/renderer';
14
16
  import type {VideoFullOptions, VideoPluginOptions, VideoToken} from './types';
15
17
 
18
+ import {append} from '../utils';
19
+
16
20
  import {parseVideoUrl} from './parsers';
17
21
  import {VideoService, defaults} from './const';
18
22
 
@@ -80,7 +84,7 @@ function tokenizeVideo(md: MarkdownIt, options: VideoFullOptions): Renderer.Rend
80
84
  }
81
85
 
82
86
  const EMBED_REGEX = /@\[([a-zA-Z].+)]\([\s]*(.*?)[\s]*[)]/im;
83
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
87
+
84
88
  function videoEmbed(md: MarkdownIt, _options: VideoFullOptions): ParserInline.RuleInline {
85
89
  return (state, silent) => {
86
90
  const theState = state;
@@ -100,12 +104,14 @@ function videoEmbed(md: MarkdownIt, _options: VideoFullOptions): ParserInline.Ru
100
104
  }
101
105
 
102
106
  const service = match[1];
103
- const videoID = parseVideoUrl(service, match[2]);
107
+ const parsed = parseVideoUrl(service, match[2]);
104
108
 
105
- if (videoID === false) {
109
+ if (parsed === false) {
106
110
  return false;
107
111
  }
108
112
 
113
+ const [videoID, csp] = parsed;
114
+
109
115
  const serviceStart = oldPos + 2;
110
116
  const serviceEnd = md.helpers.parseLinkLabel(state, oldPos + 1, false);
111
117
 
@@ -127,6 +133,10 @@ function videoEmbed(md: MarkdownIt, _options: VideoFullOptions): ParserInline.Ru
127
133
  }
128
134
 
129
135
  theState.pos += theState.src.indexOf(')', theState.pos);
136
+
137
+ state.env.meta ??= {};
138
+ append(state.env.meta, 'csp', csp);
139
+
130
140
  return true;
131
141
  };
132
142
  }
@@ -1,4 +1,4 @@
1
- import {VideoService} from './const';
1
+ import {Services} from './const';
2
2
 
3
3
  const ytRegex = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
4
4
  export function youtubeParser(url: string) {
@@ -39,45 +39,80 @@ export function yandexParser(url: string) {
39
39
  return match ? match[1] : url;
40
40
  }
41
41
 
42
- const vkRegex = /^https:\/\/vk.com\/video_ext\.php?(oid=[-\d]+&id=[-\d]+)/;
42
+ const vkRegex = /^https:\/\/vk\.com\/video_ext\.php\?(oid=[-\d]+&id=[-\d]+)/;
43
43
  export function vkParser(url: string) {
44
44
  const match = url.match(vkRegex);
45
45
  return match ? match[1] : url;
46
46
  }
47
47
 
48
- export function parseVideoUrl(service: string, url: string): string | false {
48
+ const rutubeRegex = /^https:\/\/rutube\.ru\/video\/([a-zA-Z0-9]+)\/?/;
49
+ export function rutubeParser(url: string) {
50
+ const match = url.match(rutubeRegex);
51
+ return match ? match[1] : url;
52
+ }
53
+
54
+ const dzenRegex = /^https:\/\/dzen\.ru\/video\/watch\/([a-zA-Z0-9]+)/;
55
+ export function dzenParser(url: string) {
56
+ const match = url.match(dzenRegex);
57
+ return match ? match[1] : url;
58
+ }
59
+
60
+ const supportedServices = Object.entries({
61
+ osf: {
62
+ extract: mfrParser,
63
+ },
64
+ prezi: {
65
+ extract: preziParser,
66
+ },
67
+ vimeo: {
68
+ extract: vimeoParser,
69
+ },
70
+ vine: {
71
+ extract: vineParser,
72
+ },
73
+ yandex: {
74
+ extract: yandexParser,
75
+ },
76
+ youtube: {
77
+ extract: youtubeParser,
78
+ },
79
+ vk: {
80
+ extract: vkParser,
81
+ csp: {
82
+ 'frame-src': 'https://vk.com/',
83
+ },
84
+ },
85
+ rutube: {
86
+ extract: rutubeParser,
87
+ csp: {
88
+ 'frame-src': 'https://rutube.ru/play/embed/',
89
+ },
90
+ },
91
+ dzen: {
92
+ extract: dzenParser,
93
+ csp: {
94
+ 'frame-src': 'https://dzen.ru/embed/',
95
+ },
96
+ },
97
+ }) as Services;
98
+
99
+ export function parseVideoUrl(service: string, url: string) {
49
100
  let videoID = '';
101
+ const normalizedService = service.toLowerCase();
102
+ const parsed = supportedServices.find(([name]) => name === normalizedService);
50
103
 
51
- switch (service.toLowerCase()) {
52
- case VideoService.YouTube:
53
- videoID = youtubeParser(url);
54
- break;
55
- case VideoService.Vimeo:
56
- videoID = vimeoParser(url);
57
- break;
58
- case VideoService.Vine:
59
- videoID = vineParser(url);
60
- break;
61
- case VideoService.Prezi:
62
- videoID = preziParser(url);
63
- break;
64
- case VideoService.Osf:
65
- videoID = mfrParser(url);
66
- break;
67
- case VideoService.Yandex:
68
- videoID = yandexParser(url);
69
- break;
70
- case VideoService.Vk:
71
- videoID = vkParser(url);
72
- break;
73
- default:
74
- return false;
104
+ if (!parsed) {
105
+ return false;
75
106
  }
76
107
 
108
+ const [, videoParser] = parsed;
109
+
110
+ videoID = videoParser.extract(url);
111
+
77
112
  // If the videoID field is empty, regex currently make it the close parenthesis.
78
113
  if (videoID === ')') {
79
114
  videoID = '';
80
115
  }
81
116
 
82
- return videoID;
117
+ return [videoID, videoParser.csp] as const;
83
118
  }
@@ -7,13 +7,14 @@ export type VideoToken = Token & {
7
7
  };
8
8
 
9
9
  export type VideoServicesOptions = {
10
- [VideoService.YouTube]: {width: number; height: number};
11
- [VideoService.Vimeo]: {width: number; height: number};
12
- [VideoService.Vine]: {width: number; height: number; embed: 'simple' | string};
13
- [VideoService.Prezi]: {width: number; height: number};
14
- [VideoService.Osf]: {width: string; height: string};
15
- [VideoService.Yandex]: {width: number; height: number};
16
- [VideoService.Vk]: {width: number; height: number};
10
+ [service in VideoService]: {
11
+ width: number | string;
12
+ height: number | string;
13
+ };
14
+ } & {
15
+ vine: {
16
+ embed: 'simple' | (string & {});
17
+ };
17
18
  };
18
19
 
19
20
  export type VideoFullOptions = VideoServicesOptions & {
@@ -21,6 +21,10 @@ export const videoUrl: VideoUrlFn = (service, videoID, options) => {
21
21
  return `https://runtime.video.cloud.yandex.net/player/video/${videoID}`;
22
22
  case 'vk':
23
23
  return `https://vk.com/video_ext.php?${videoID}`;
24
+ case 'rutube':
25
+ return `https://rutube.ru/play/embed/${videoID}`;
26
+ case 'dzen':
27
+ return `https://dzen.ru/video/watch/${videoID}`;
24
28
  default:
25
29
  return service;
26
30
  }