@adobe/helix-html-pipeline 1.6.0 → 2.0.2

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.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,48 @@
1
- # [1.6.0](https://github.com/adobe/helix-html-pipeline/compare/v1.5.8...v1.6.0) (2022-05-25)
1
+ ## [2.0.2](https://github.com/adobe/helix-html-pipeline/compare/v2.0.1...v2.0.2) (2022-05-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **deps:** update external fixes ([#65](https://github.com/adobe/helix-html-pipeline/issues/65)) ([0994581](https://github.com/adobe/helix-html-pipeline/commit/09945810ee3969350b6053d49d1614c1e9051eba))
7
+
8
+ ## [2.0.1](https://github.com/adobe/helix-html-pipeline/compare/v2.0.0...v2.0.1) (2022-05-25)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * querystring is deprecated ([d693319](https://github.com/adobe/helix-html-pipeline/commit/d6933197e928da452712bcfb2c8a42cdefe2bf2c))
14
+ * respect fragments and querystring during link-rewrite ([44e00d4](https://github.com/adobe/helix-html-pipeline/commit/44e00d49293df392f4dec7eafee1abc60743ff79))
15
+
16
+ # [2.0.0](https://github.com/adobe/helix-html-pipeline/compare/v1.5.8...v2.0.0) (2022-05-25)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * add link rewriting ([bde5fb6](https://github.com/adobe/helix-html-pipeline/commit/bde5fb6a15fcac24887897c0134d524677730741))
22
+ * clean up empty paragraphs ([30547b7](https://github.com/adobe/helix-html-pipeline/commit/30547b7cca7869bd791bfa0b5fee7b23d8548798))
23
+ * create <picture> tags ([88c1ab9](https://github.com/adobe/helix-html-pipeline/commit/88c1ab96c335a60092b8fcbe60de2d2e061809bf))
24
+ * detect and fix wrong dimensions fragment ([e0df3dc](https://github.com/adobe/helix-html-pipeline/commit/e0df3dc6bfa0c2f3acf771f8cea95f5237eddb00))
25
+ * improve block css class names ([ff05d3c](https://github.com/adobe/helix-html-pipeline/commit/ff05d3c38d92126ea65573d33639453ea5aaa5e6))
26
+ * preserve table-cell align attributes as data-attribures ([c5a5c1a](https://github.com/adobe/helix-html-pipeline/commit/c5a5c1aea3148c7ad44e44f40e7dd7b8eca19566))
27
+ * pretty-print html ([529facf](https://github.com/adobe/helix-html-pipeline/commit/529facf416a07e8a5050ec1a614eec23f9249efc))
28
+ * replace icon svgs with spans ([55aeeeb](https://github.com/adobe/helix-html-pipeline/commit/55aeeeb03578eef0ece877669969729e1ce68855))
29
+ * unwrap img inside em/strong ([dbc6a82](https://github.com/adobe/helix-html-pipeline/commit/dbc6a8204193aa7c79fda05024fe3d8f40093443))
2
30
 
3
31
 
4
32
  ### Features
5
33
 
6
- * adding maintenance branch ([ce43691](https://github.com/adobe/helix-html-pipeline/commit/ce43691b0ed7ef39ae137027c5eb3046812d46f6))
34
+ * Breaking changes for 2022-05 ([f2d1523](https://github.com/adobe/helix-html-pipeline/commit/f2d1523d21eb2b9a57bdd658526c7a9ee8bd8056))
35
+
36
+
37
+ ### BREAKING CHANGES
38
+
39
+ * icons: are now replaced with <span> elements
40
+ * the format of the css class names changed
41
+ * dom changes
42
+ * picture dom changed
43
+ * all links to media and same hlx sites are relativized
44
+ * empty <p></p> tags now properly sourround the following element, eg pictures
45
+ * inter-element whitespace changes
7
46
 
8
47
  ## [1.5.8](https://github.com/adobe/helix-html-pipeline/compare/v1.5.7...v1.5.8) (2022-05-19)
9
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-html-pipeline",
3
- "version": "1.6.0",
3
+ "version": "2.0.2",
4
4
  "description": "Helix HTML Pipeline",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -34,7 +34,7 @@
34
34
  "@adobe/helix-shared-utils": "2.0.10",
35
35
  "github-slugger": "1.4.0",
36
36
  "hast-util-raw": "7.2.1",
37
- "hast-util-select": "5.0.1",
37
+ "hast-util-select": "5.0.2",
38
38
  "hast-util-to-html": "8.0.3",
39
39
  "hast-util-to-string": "2.0.0",
40
40
  "hastscript": "7.0.2",
@@ -52,7 +52,6 @@
52
52
  "micromark-util-combine-extensions": "1.0.0",
53
53
  "mime": "3.0.0",
54
54
  "rehype-format": "4.0.1",
55
- "rehype-minify-whitespace": "5.0.1",
56
55
  "rehype-parse": "8.0.4",
57
56
  "remark-parse": "10.0.1",
58
57
  "strip-markdown": "5.0.0",
@@ -61,7 +60,8 @@
61
60
  "unist-util-remove": "3.1.0",
62
61
  "unist-util-remove-position": "4.0.1",
63
62
  "unist-util-select": "4.0.1",
64
- "unist-util-visit": "4.1.0"
63
+ "unist-util-visit": "4.1.0",
64
+ "unist-util-visit-parents": "5.1.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@adobe/eslint-config-helix": "1.3.2",
@@ -69,8 +69,8 @@
69
69
  "@semantic-release/changelog": "6.0.1",
70
70
  "@semantic-release/git": "10.0.1",
71
71
  "@semantic-release/npm": "9.0.1",
72
- "c8": "7.11.2",
73
- "eslint": "8.15.0",
72
+ "c8": "7.11.3",
73
+ "eslint": "8.16.0",
74
74
  "eslint-plugin-header": "3.1.1",
75
75
  "eslint-plugin-import": "2.26.0",
76
76
  "esmock": "1.7.5",
@@ -79,7 +79,7 @@
79
79
  "jsdoc-to-markdown": "7.1.1",
80
80
  "jsdom": "19.0.0",
81
81
  "junit-report-builder": "3.0.0",
82
- "lint-staged": "12.4.1",
82
+ "lint-staged": "12.4.2",
83
83
  "mocha": "10.0.0",
84
84
  "mocha-multi-reporters": "1.5.1",
85
85
  "remark-gfm": "3.0.1",
package/src/html-pipe.js CHANGED
@@ -25,7 +25,7 @@ import parseMarkdown from './steps/parse-markdown.js';
25
25
  import removeHlxProps from './steps/removeHlxProps.js';
26
26
  import render from './steps/render.js';
27
27
  import renderCode from './steps/render-code.js';
28
- import rewriteBlobImages from './steps/rewrite-blob-images.js';
28
+ import rewriteUrls from './steps/rewrite-urls.js';
29
29
  import rewriteIcons from './steps/rewrite-icons.js';
30
30
  import setXSurrogateKeyHeader from './steps/set-x-surrogate-key-header.js';
31
31
  import setCustomResponseHeaders from './steps/set-custom-response-headers.js';
@@ -94,7 +94,7 @@ export async function htmlPipe(state, req) {
94
94
  await getMetadata(state); // this one extracts the metadata from the mdast
95
95
  await unwrapSoleImages(state);
96
96
  await html(state);
97
- await rewriteBlobImages(state);
97
+ await rewriteUrls(state);
98
98
  await rewriteIcons(state);
99
99
  await fixSections(state);
100
100
  await createPageBlocks(state);
@@ -12,7 +12,7 @@
12
12
  import { h } from 'hastscript';
13
13
  import { selectAll, select } from 'hast-util-select';
14
14
  import { toString } from 'hast-util-to-string';
15
- import { toClassName } from './utils.js';
15
+ import { toBlockCSSClassNames } from './utils.js';
16
16
  import { replace, childNodes } from '../utils/hast-utils.js';
17
17
 
18
18
  /**
@@ -44,20 +44,17 @@ function tableToDivs($table) {
44
44
  }
45
45
 
46
46
  // get columns names
47
- const clazz = $headerCols
48
- .map((e) => toClassName(toString(e)))
49
- .filter((c) => !!c)
50
- .join('-');
51
- if (clazz) {
52
- $cards.properties.className = [clazz];
53
- }
47
+ $cards.properties.className = toBlockCSSClassNames(toString($headerCols[0]));
54
48
 
55
49
  // construct page block
56
50
  for (const $row of $rows) {
57
51
  const $card = h('div');
58
52
  for (const $cell of childNodes($row)) {
59
53
  // convert to div
60
- $card.children.push(h('div', $cell.children));
54
+ $card.children.push(h('div', {
55
+ 'data-align': $cell.properties.align,
56
+ 'data-valign': $cell.properties.vAlign,
57
+ }, $cell.children));
61
58
  }
62
59
  $cards.children.push($card);
63
60
  }
@@ -9,10 +9,65 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
+ import mime from 'mime';
12
13
  import { h } from 'hastscript';
13
- import { selectAll } from 'hast-util-select';
14
- import { replace } from '../utils/hast-utils.js';
15
- import { optimizeImageURL } from './utils.js';
14
+ import { visitParents } from 'unist-util-visit-parents';
15
+
16
+ const BREAK_POINTS = [
17
+ { media: '(min-width: 400px)', width: '2000' },
18
+ { width: '750' },
19
+ ];
20
+
21
+ export function createOptimizedPicture(src, alt = '', eager = false) {
22
+ const url = new URL(src, 'https://localhost/');
23
+ const { pathname, hash = '' } = url;
24
+ const props = new URLSearchParams(hash.substring(1));
25
+ // detect bug in media handler that created fragments like `width=800&width=600`
26
+ // eslint-disable-next-line prefer-const
27
+ let [width, height] = props.getAll('width');
28
+ if (props.has('height')) {
29
+ height = props.get('height');
30
+ }
31
+ const ext = pathname.substring(pathname.lastIndexOf('.') + 1);
32
+ const type = mime.getType(pathname);
33
+
34
+ const variants = [
35
+ ...BREAK_POINTS.map((br) => ({
36
+ ...br,
37
+ ext: 'webply',
38
+ type: 'image/webp',
39
+ })),
40
+ ...BREAK_POINTS.map((br) => ({
41
+ ...br,
42
+ ext,
43
+ type,
44
+ }))];
45
+
46
+ const sources = variants.map((v, i) => {
47
+ const srcset = `.${pathname}?width=${v.width}&format=${v.ext}&optimize=medium`;
48
+ if (i < variants.length - 1) {
49
+ return h('source', {
50
+ type: v.type,
51
+ srcset,
52
+ media: v.media,
53
+ });
54
+ }
55
+ return h('img', {
56
+ loading: eager ? 'eager' : 'lazy',
57
+ alt,
58
+ type: v.type,
59
+ src: srcset,
60
+ width,
61
+ height,
62
+ });
63
+ });
64
+
65
+ return h('picture', sources);
66
+ }
67
+
68
+ function isMediaImage(node) {
69
+ return node.tagName === 'img' && node.properties?.src.startsWith('./media_');
70
+ }
16
71
 
17
72
  /**
18
73
  * Converts imgs to pictures
@@ -22,18 +77,22 @@ import { optimizeImageURL } from './utils.js';
22
77
  export default async function createPictures({ content }) {
23
78
  const { hast } = content;
24
79
 
25
- // transform <img> to <picture>
26
- selectAll('img[src^="./media_"]', hast).forEach((img, i) => {
27
- const { src } = img.properties;
28
- const source = h('source');
29
- source.properties.media = '(max-width: 400px)';
30
- source.properties.srcset = optimizeImageURL(src, 750);
31
-
32
- const picture = h('picture', source);
33
- img.properties.loading = i > 0 ? 'lazy' : 'eager';
34
- img.properties.src = optimizeImageURL(src, 2000);
80
+ let first = true;
81
+ visitParents(hast, isMediaImage, (img, parents) => {
82
+ const { src, alt } = img.properties;
83
+ const picture = createOptimizedPicture(src, alt, first);
84
+ first = false;
35
85
 
36
- replace(hast, img, picture);
37
- picture.children.push(img);
86
+ // check if parent has style and unwrap if needed
87
+ const parent = parents[parents.length - 1];
88
+ const parentTag = parent.tagName;
89
+ if (parentTag === 'em' || parentTag === 'strong') {
90
+ const grand = parents[parents.length - 2];
91
+ const idx = grand.children.indexOf(parent);
92
+ grand.children[idx] = picture;
93
+ } else {
94
+ const idx = parent.children.indexOf(img);
95
+ parent.children[idx] = picture;
96
+ }
38
97
  });
39
98
  }
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { select, selectAll } from 'unist-util-select';
13
13
  import { toString as plain } from 'mdast-util-to-string';
14
- import { rewriteBlobLink } from './utils.js';
14
+ import { rewriteUrl } from './utils.js';
15
15
 
16
16
  function yaml(section) {
17
17
  section.meta = selectAll('yaml', section)
@@ -35,12 +35,12 @@ function intro(section) {
35
35
  section.intro = para ? plain(para) : '';
36
36
  }
37
37
 
38
- function image(section) {
38
+ function image(section, state) {
39
39
  // selects the most prominent image of the section
40
40
  // TODO: get a better measure of prominence than "first"
41
41
  const img = select('image', section);
42
42
  if (img) {
43
- section.image = rewriteBlobLink(img.url);
43
+ section.image = rewriteUrl(state, img.url);
44
44
  }
45
45
  }
46
46
 
@@ -157,7 +157,7 @@ export default function getMetadata(state) {
157
157
  }
158
158
 
159
159
  [yaml, title, intro, image, sectiontype, fallback].forEach((fn) => {
160
- sections.forEach(fn);
160
+ sections.forEach((section) => fn(section, state));
161
161
  });
162
162
 
163
163
  const img = sections.filter((section) => section.image)[0];
@@ -10,15 +10,16 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
  /* eslint-disable no-param-reassign */
13
- import { h, s } from 'hastscript';
13
+ import { h } from 'hastscript';
14
14
  import { CONTINUE, visit } from 'unist-util-visit';
15
15
 
16
- const REGEXP_ICON = /:(#?[a-zA-Z_-]+[a-zA-Z0-9]*):/g;
16
+ const REGEXP_ICON = /:(#?[a-z_-]+[a-z\d]*):/gi;
17
17
 
18
18
  /**
19
- * Create a <img> or <svg> icon dom element eg:
20
- * `<img class="icon icon-smile" src="/icons/smile.svg"/>` or
21
- * `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-smile"><use href="/icons.svg#smile"></use></svg>`
19
+ * Create a <span> icon element:
20
+ *
21
+ * `<span class="icon icon-smile"></span>`
22
+ *
22
23
  * @param {string} value the identifier of the icon
23
24
  */
24
25
  function createIcon(value) {
@@ -26,14 +27,12 @@ function createIcon(value) {
26
27
 
27
28
  // icon starts with #
28
29
  if (name.startsWith('%23')) {
30
+ // todo: still support sprite sheets?
29
31
  name = name.substring(3);
30
- return s('svg', { class: `icon icon-${name}` }, [
31
- s('use', { href: `/icons.svg#${name}` }),
32
- ]);
33
32
  }
34
33
 
35
- // create normal image
36
- return h('img', { class: `icon icon-${name}`, src: `/icons/${name}.svg`, alt: `${name} icon` });
34
+ // create normal span
35
+ return h('span', { className: ['icon', `icon-${name}`] });
37
36
  }
38
37
 
39
38
  /**
@@ -9,18 +9,30 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- import { selectAll } from 'hast-util-select';
13
- import { rewriteBlobLink } from './utils.js';
12
+
13
+ import { CONTINUE, visit } from 'unist-util-visit';
14
+ import { rewriteUrl } from './utils.js';
14
15
 
15
16
  /**
16
- * Rewrite blob store image URLs to /hlx_* URLs
17
- *
18
- * @type PipelineStep
19
- * @param content
17
+ * Rewrites all A and IMG urls
18
+ * @param {PipelineState} state
20
19
  */
21
- export default function rewrite({ content }) {
22
- const { hast } = content;
23
- selectAll('img', hast).forEach((img) => {
24
- img.properties.src = rewriteBlobLink(img.properties.src);
20
+ export default async function rewriteUrls(state) {
21
+ const { content: { hast } } = state;
22
+
23
+ const els = {
24
+ a: 'href',
25
+ img: 'src',
26
+ };
27
+
28
+ visit(hast, (node) => {
29
+ if (node.type !== 'element') {
30
+ return CONTINUE;
31
+ }
32
+ const attr = els[node.tagName];
33
+ if (attr) {
34
+ node.properties[attr] = rewriteUrl(state, node.properties[attr]);
35
+ }
36
+ return CONTINUE;
25
37
  });
26
38
  }
@@ -10,9 +10,7 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
  import { toHtml } from 'hast-util-to-html';
13
- // import rehypeFormat from 'rehype-format';
14
- import rehypeMinifyWhitespace from 'rehype-minify-whitespace';
15
- import { visit } from 'unist-util-visit';
13
+ import rehypeFormat from 'rehype-format';
16
14
 
17
15
  /**
18
16
  * Serializes the response document to HTML
@@ -30,28 +28,7 @@ export default function stringify(state, req, res) {
30
28
  if (!doc) {
31
29
  throw Error('no response document');
32
30
  }
33
-
34
- // TODO: for the next breaking release, pretty print the HTML with rehypeFormat.
35
- // TODO: but for backward compatibility, output all on 1 line.
36
- // rehypeFormat()(doc);
37
-
38
- // due to a bug in rehype-minify-whitespace, script content is also minified to 1 line, which
39
- // can result in errors https://github.com/rehypejs/rehype-minify/issues/44
40
- // so we 'save' all text first and revert it afterwards
41
- visit(doc, (node) => {
42
- if (node.tagName === 'script' && node.children[0]?.type === 'text') {
43
- node.children[0].savedValue = node.children[0].value;
44
- }
45
- });
46
-
47
- rehypeMinifyWhitespace()(doc);
48
-
49
- visit(doc, (node) => {
50
- if (node.tagName === 'script' && node.children[0]?.type === 'text') {
51
- node.children[0].value = node.children[0].savedValue;
52
- delete node.children[0].savedValue;
53
- }
54
- });
31
+ rehypeFormat()(doc);
55
32
 
56
33
  res.body = toHtml(doc, {
57
34
  upperDoctype: true,
@@ -14,6 +14,8 @@ const AZURE_BLOB_REGEXP = /^https:\/\/hlx\.blob\.core\.windows\.net\/external\//
14
14
 
15
15
  const MEDIA_BLOB_REGEXP = /^https:\/\/.*\.hlx3?\.(live|page)\/media_.*/;
16
16
 
17
+ const HELIX_URL_REGEXP = /^https:\/\/.*\.hlx3?\.(live|page)\/.*/;
18
+
17
19
  /**
18
20
  * Returns the original host name from the request to the outer CDN.
19
21
  * @param {object} headers The request headers
@@ -64,15 +66,39 @@ export function wrapContent($parent, $node) {
64
66
  }
65
67
 
66
68
  /**
67
- * Converts all non-valid-css-classname characters to `-`.
69
+ * Converts the given text to an array of CSS class names:
70
+ * - extracts the list of options (given as CSV in braces at the end)
71
+ * - collapses all consecutive invalid-css name characters to a single `-`
72
+ * - removes leading and trailing `-`
73
+ * - converts all names to lowercase
74
+ *
75
+ * @examples
76
+ * Columns (fullsize center) --> columns fullsize-center
77
+ * Columns (fullsize, center) --> columns fullsize center
78
+ * Joe's Pizza! (small) -> joe-s-pizza small
79
+ *
68
80
  * @param {string} text input text
69
- * @returns {string} the css class name
81
+ * @returns {string[]} the array of CSS class names
70
82
  */
71
- export function toClassName(text) {
72
- return text
73
- .trim()
83
+ export function toBlockCSSClassNames(text) {
84
+ if (!text) {
85
+ return [];
86
+ }
87
+ const names = [];
88
+ const idx = text.lastIndexOf('(');
89
+ if (idx >= 0) {
90
+ names.push(text.substring(0, idx));
91
+ names.push(...text.substring(idx + 1).split(','));
92
+ } else {
93
+ names.push(text);
94
+ }
95
+
96
+ return names.map((name) => name
74
97
  .toLowerCase()
75
- .replace(/[^0-9a-z]/gi, '-');
98
+ .replace(/[^0-9a-z]+/g, '-')
99
+ .replace(/^-+/, '')
100
+ .replace(/-+$/, ''))
101
+ .filter((name) => !!name);
76
102
  }
77
103
 
78
104
  /**
@@ -150,19 +176,50 @@ export function getAbsoluteUrl(headers, url) {
150
176
  }
151
177
 
152
178
  /**
153
- * Rewrite a blog image link. if the link is not a blog image link, it is returned as-is.
154
- * @param {string} src the image source
155
- * @returns {string} the new source
179
+ * Rewrites the media, helix or external url. Returns the original if not rewritten.
180
+ * @param {PipelineState} state
181
+ * @param {string} url
182
+ * @returns {string|null}
156
183
  */
157
- export function rewriteBlobLink(src) {
158
- if (AZURE_BLOB_REGEXP.test(src)) {
159
- const { pathname, hash } = new URL(src);
184
+ export function rewriteUrl(state, url) {
185
+ if (!url) {
186
+ return url;
187
+ }
188
+
189
+ if (AZURE_BLOB_REGEXP.test(url)) {
190
+ const { pathname, hash } = new URL(url);
160
191
  const filename = pathname.split('/').pop();
161
- const extension = hash.split('?').shift().split('.').pop() || 'jpg';
162
- return `./media_${filename}.${extension}`;
163
- } else if (MEDIA_BLOB_REGEXP.test(src)) {
164
- const { pathname } = new URL(src);
165
- return `.${pathname}`; // don't append fragment until picture tag supports width/height
192
+ const [name, props] = hash.split('?');
193
+ const extension = name.split('.').pop() || 'jpg';
194
+ const newHash = props ? `#${props}` : '';
195
+ return `./media_${filename}.${extension}${newHash}`;
166
196
  }
167
- return src;
197
+
198
+ if (MEDIA_BLOB_REGEXP.test(url)) {
199
+ const { pathname, hash } = new URL(url);
200
+ return `.${pathname}${hash}`;
201
+ }
202
+
203
+ if (HELIX_URL_REGEXP.test(url)) {
204
+ const { pathname, hash, search } = new URL(url);
205
+ if (hash && pathname === state.info?.path) {
206
+ return hash;
207
+ }
208
+ return `${pathname}${search}${hash}`;
209
+ }
210
+
211
+ // todo: read host from contentbus config
212
+ if (state.config?.host) {
213
+ const {
214
+ host, pathname, search, hash,
215
+ } = new URL(url);
216
+ if (host === state.config.host) {
217
+ if (hash && pathname === state.info?.path) {
218
+ return hash;
219
+ }
220
+ return `${pathname}${search}${hash}`;
221
+ }
222
+ }
223
+
224
+ return url;
168
225
  }
@@ -14,7 +14,7 @@ import { toString } from 'mdast-util-to-string';
14
14
  import strip from 'strip-markdown';
15
15
 
16
16
  /**
17
- *Injects heading identifiers during the MDAST to VDOM transformation.
17
+ * Injects heading identifiers during the MDAST to VDOM transformation.
18
18
  */
19
19
  export default function heading(slugger) {
20
20
  return function handler(h, node) {
@@ -11,7 +11,6 @@
11
11
  */
12
12
  import { toHast as mdast2hast, defaultHandlers } from 'mdast-util-to-hast';
13
13
  import { raw } from 'hast-util-raw';
14
- import { visit, CONTINUE } from 'unist-util-visit';
15
14
 
16
15
  import section from './section-handler.js';
17
16
  import heading from './heading-handler.js';
@@ -32,29 +31,5 @@ export default function getHast(mdast, slugger) {
32
31
  allowDangerousHtml: true,
33
32
  });
34
33
 
35
- // TODO: remove for cleanup
36
- // the following recreates a bug with the old vdom transformer that would create a
37
- // <p></p> for all raw `<p>` before a block with void elements.
38
- visit(hast, (node, idx, parent) => {
39
- if (node.type !== 'raw' || node.value !== '<p>') {
40
- return CONTINUE;
41
- }
42
- // check if any other raw empty nodes follow until the </p>
43
- for (let i = idx + 1; i < parent.children.length; i += 1) {
44
- const next = parent.children[i];
45
- if (next.type === 'raw') {
46
- if (next.value === '</p>') {
47
- return i + 1;
48
- }
49
- if (next.value === '<br>' || next.value.startsWith('<img ')) {
50
- node.value = '<p></p>';
51
- return i + 1;
52
- }
53
- }
54
- }
55
- /* c8 ignore next */
56
- return CONTINUE;
57
- });
58
-
59
34
  return raw(hast);
60
35
  }