Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#47 Fixed the function to wrap img in figure tag #71

Merged
merged 1 commit into from
Feb 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions docs/vfm.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Vivliostyle Flavored Markdown (VFM), a Markdown syntax optimized for book author
- [Code](#code)
- [with caption](#with-caption)
- [Image](#image)
- [with caption](#with-caption-1)
- [with caption and single line](#with-caption-and-single-line)
- [Ruby](#ruby)
- [Sectionization](#sectionization)
- [Plain section](#plain-section)
Expand Down Expand Up @@ -125,14 +125,22 @@ img {
}
```

### with caption
### with caption and single line

<Badge type="warning">PRE-RELEASE</Badge>

Wraps an image written as a single line and with a caption in `<figure>`.

If specify attributes for the image, the `id` is moved to `<figure>` and everything else is copied except for` <img> `specific (such as `src`).

**VFM**

```md
![Figure 1](./fig1.png)

![Figure 2](./fig2.png "Figure 2"){id="image" data-sample="sample"}

text ![Figure 3](./fig3.png)
```

**HTML**
Expand All @@ -142,6 +150,11 @@ img {
<img src="./fig1.png" alt="Figure 1" />
<figcaption>Figure 1</figcaption>
</figure>
<figure id="image" title="Figure 2" data-sample="sample">
<img src="./fig2.png" alt="caption" title="Figure 2" data-sample="sample">
<figcaption>Figure 2</figcaption>
</figure>
<p>text <img src="./fig3.png" alt="Figure 3"></p>
```

**CSS**
Expand Down Expand Up @@ -407,18 +420,24 @@ VFM は出版物の執筆に適した Markdown 方言であり、Vivliostyle プ
```html
<!-- hardLineBreaks: true -->
<p>はじめまして。</p>
<p>Vivliostyle Flavored Markdown(略して VFM)の世界へようこそ。<br>
VFM は出版物の執筆に適した Markdown 方言であり、Vivliostyle プロジェクトのために策定・実装されました。</p>
<p>
Vivliostyle Flavored Markdown(略して VFM)の世界へようこそ。<br />
VFM は出版物の執筆に適した Markdown 方言であり、Vivliostyle
プロジェクトのために策定・実装されました。
</p>

<!-- hardLineBreaks: false (Default) -->
<p>はじめまして。</p>
<p>Vivliostyle Flavored Markdown(略して VFM)の世界へようこそ。
VFM は出版物の執筆に適した Markdown 方言であり、Vivliostyle プロジェクトのために策定・実装されました。</p>
<p>
Vivliostyle Flavored Markdown(略して VFM)の世界へようこそ。 VFM
は出版物の執筆に適した Markdown 方言であり、Vivliostyle
プロジェクトのために策定・実装されました。
</p>
```

**CSS**

```css
p {
}
```
```
69 changes: 62 additions & 7 deletions src/plugins/figure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,59 @@ import { Node, Parent } from 'unist';
import visit from 'unist-util-visit';
import { HastNode } from './hastnode';

/**
* Check if the specified property is `<img>` specific.
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element
* @param name Property name.
* @returns If the specified property is `true`.
*/
const isImgProperty = (name: string): boolean => {
switch (name) {
case 'alt':
case 'src':
case 'srcset':
case 'sizes':
case 'crossorigin':
case 'usemap':
case 'ismap':
case 'width':
case 'height':
case 'referrerpolicy':
case 'decoding':
case 'loading':
return true;

default:
return false;
}
};

/**
* Wrap the single line `<img>` in `<figure>` and generate `<figcaption>` from the `alt` attribute.
*
* A single line `<img>` is a child of `<p>` with no sibling elements. Also, `<figure>` cannot be a child of `<p>`. So convert the parent `<p>` to `<figure>`.
*
* Also, of the attributes of `<img>`,` id` is moved to `<figure>`, and the others are copied except for `<img>` specific (such as `src`).
* @param img `<img>` tag.
* @param parent `<p>` tag.
*/
const wrapFigureImg = (img: HastNode, parent: HastNode) => {
parent.tagName = 'figure';
parent.children.push(h('figcaption', img.properties.alt));

// Move to parent because `id` attribute is unique
if (img.properties.id) {
parent.properties.id = img.properties.id;
delete img.properties.id;
}

for (const key of Object.keys(img.properties)) {
if (!isImgProperty(key)) {
parent.properties[key] = img.properties[key];
}
}
};

export const hast = () => (tree: Node) => {
visit<HastNode>(tree, 'element', (node, index, parent) => {
// handle captioned code block
Expand All @@ -20,13 +73,15 @@ export const hast = () => (tree: Node) => {
return;
}

// handle captioned img
if (is(node, 'img') && node.properties.alt) {
(parent as Parent).children[index] = h(
'figure',
node,
h('figcaption', node.properties.alt),
);
// handle captioned and single line (like a block) img
if (
is(node, 'img') &&
node.properties.alt &&
parent &&
parent.tagName === 'p' &&
parent.children.length === 1
) {
wrapFigureImg(node, parent as HastNode);
}
});
};
48 changes: 47 additions & 1 deletion tests/remark2rehype/figure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ it(
url: "./img.png"
alt: "caption"
`,
`<p><figure><img src="./img.png" alt="caption"><figcaption>caption</figcaption></figure></p>`,
`<figure><img src="./img.png" alt="caption"><figcaption>caption</figcaption></figure>`,
),
);

Expand All @@ -32,3 +32,49 @@ it(
`<p><img src="./img.png"></p>`,
),
);

it(
'Only single line',
buildProcessorTestingCode(
stripIndent`
![caption](./img.png)

text ![caption](./img.png)
`,
stripIndent`
root[2]
├─0 paragraph[1]
│ └─0 image
│ title: null
│ url: "./img.png"
│ alt: "caption"
└─1 paragraph[2]
├─0 text "text "
└─1 image
title: null
url: "./img.png"
alt: "caption"
`,
stripIndent`
<figure><img src="./img.png" alt="caption"><figcaption>caption</figcaption></figure>
<p>text <img src="./img.png" alt="caption"></p>
`,
),
);

it(
'Attributes',
buildProcessorTestingCode(
`![caption](./img.png "title"){id="image" data-sample="sample"}`,
stripIndent`
root[1]
└─0 paragraph[1]
└─0 image
title: "title"
url: "./img.png"
alt: "caption"
data: {"hProperties":{"id":"image","data-sample":"sample"}}
`,
`<figure id="image" title="title" data-sample="sample"><img src="./img.png" alt="caption" title="title" data-sample="sample"><figcaption>caption</figcaption></figure>`,
),
);