-
Notifications
You must be signed in to change notification settings - Fork 46
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
feat(imsize): rework image styling to get more control #549
Changes from 4 commits
bbf59b6
c5296a1
879e32d
648f539
d6ce8fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ export enum ImsizeAttr { | |
Title = 'title', | ||
Width = 'width', | ||
Height = 'height', | ||
Style = 'style', | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
import {PluginSimple} from 'markdown-it'; | ||
import {PluginWithOptions} from 'markdown-it'; | ||
|
||
import {imageWithSize} from './plugin'; | ||
import {ImsizeOptions, imageWithSize} from './plugin'; | ||
|
||
/** | ||
* Imsize plugin for markdown-it. | ||
* This plugin overloads original image renderer. | ||
* Forked from https://github.com/tatsy/markdown-it-imsize | ||
*/ | ||
|
||
const imsize: PluginSimple = (md) => { | ||
md.inline.ruler.before('emphasis', 'image', imageWithSize(md)); | ||
const imsize: PluginWithOptions<ImsizeOptions> = (md, opts) => { | ||
md.inline.ruler.before('emphasis', 'image', imageWithSize(md, opts)); | ||
}; | ||
|
||
export = imsize; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -5,7 +5,11 @@ import type Token from 'markdown-it/lib/token'; | |||||
import {ImsizeAttr} from './const'; | ||||||
import {parseImageSize} from './helpers'; | ||||||
|
||||||
export const imageWithSize = (md: MarkdownIt): ParserInline.RuleInline => { | ||||||
export type ImsizeOptions = { | ||||||
inlineSizeStyling?: boolean; | ||||||
}; | ||||||
|
||||||
export const imageWithSize = (md: MarkdownIt, opts?: ImsizeOptions): ParserInline.RuleInline => { | ||||||
// eslint-disable-next-line complexity | ||||||
return (state, silent) => { | ||||||
if (state.src.charCodeAt(state.pos) !== 0x21 /* ! */) { | ||||||
|
@@ -206,6 +210,33 @@ export const imageWithSize = (md: MarkdownIt): ParserInline.RuleInline => { | |||||
if (height !== '') { | ||||||
token.attrs.push([ImsizeAttr.Height, height]); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why we still need height and width attributes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. transform/src/transform/plugins/changelog/index.ts Lines 77 to 78 in bff7df9
Alas, that's why we still need it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also noticed complaints about incorrect image appearance when the height was not proportional. However, I did not see any requests for a stretched image or an image with extra frames. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The proportions of the image are calculated based on the height and width specified in the markup. If the container is larger than these dimensions, the image will maintain its original height and width. If the width of the container is less than the width of the image, the image's width will adjust to 100% of the container's width and the height will be adjusted proportionally based on the original height and width values from the markup. |
||||||
} | ||||||
|
||||||
if (opts?.inlineSizeStyling) { | ||||||
let style: string | undefined = ''; | ||||||
|
||||||
const widthWithPercent = width.includes('%'); | ||||||
const heightWithPercent = height.includes('%'); | ||||||
|
||||||
if (width !== '') { | ||||||
const widthString = widthWithPercent ? width : `${width}px`; | ||||||
style += `width: ${widthString};`; | ||||||
} | ||||||
|
||||||
if (height !== '') { | ||||||
if (width !== '' && !heightWithPercent && !widthWithPercent) { | ||||||
style += `aspect-ratio: ${width} / ${height};height: auto;`; | ||||||
state.env.forcedSanitizeCssWhiteList ??= {}; | ||||||
state.env.forcedSanitizeCssWhiteList['aspect-ratio'] = true; | ||||||
} else { | ||||||
const heightString = heightWithPercent ? height : `${height}px`; | ||||||
style += `height: ${heightString};`; | ||||||
} | ||||||
} | ||||||
|
||||||
if (style) { | ||||||
token.attrs.push([ImsizeAttr.Style, style]); | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
state.pos = pos; | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ import cssfilter from 'cssfilter'; | |
import * as cheerio from 'cheerio'; | ||
import css from 'css'; | ||
|
||
import {CssWhiteList} from './typings'; | ||
|
||
const htmlTags = [ | ||
'a', | ||
'abbr', | ||
|
@@ -492,8 +494,6 @@ const allowedTags = Array.from( | |
); | ||
const allowedAttributes = Array.from(new Set([...htmlAttrs, ...svgAttrs, ...yfmHtmlAttrs])); | ||
|
||
export type CssWhiteList = {[property: string]: boolean}; | ||
|
||
export interface SanitizeOptions extends sanitizeHtml.IOptions { | ||
cssWhiteList?: CssWhiteList; | ||
disableStyleSanitizer?: boolean; | ||
|
@@ -598,9 +598,20 @@ function sanitizeStyles(html: string, options: SanitizeOptions) { | |
return styles + content; | ||
} | ||
|
||
export default function sanitize(html: string, options?: SanitizeOptions) { | ||
export default function sanitize( | ||
html: string, | ||
options?: SanitizeOptions, | ||
forcedSanitizeCssWhiteList?: CssWhiteList, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
) { | ||
const sanitizeOptions = options || defaultOptions; | ||
|
||
if (forcedSanitizeCssWhiteList) { | ||
sanitizeOptions.cssWhiteList = { | ||
...sanitizeOptions.cssWhiteList, | ||
...forcedSanitizeCssWhiteList, | ||
}; | ||
} | ||
|
||
const needToSanitizeStyles = !(sanitizeOptions.disableStyleSanitizer ?? false); | ||
|
||
const modifiedHtml = needToSanitizeStyles ? sanitizeStyles(html, sanitizeOptions) : html; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
Coverage. Image with inlineStyling | ||
. | ||
 | ||
. | ||
<p><img src="x" alt="test" width="100" height="200" style="width: 100px;aspect-ratio: 100 / 200;height: auto;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="x" alt="test"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="x" alt="test" width="100" style="width: 100px;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="x" alt="test" height="200" style="height: 200px;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="x" alt="test" title="title" width="100" height="200" style="width: 100px;aspect-ratio: 100 / 200;height: auto;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p></p> | ||
. | ||
. | ||
 | ||
. | ||
<p></p> | ||
. | ||
. | ||
 | ||
. | ||
<p></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="http://this.is.test.jpg" alt="test" width="100" height="200" style="width: 100px;aspect-ratio: 100 / 200;height: auto;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="x" alt="test" width="100" height="200" style="width: 100px;aspect-ratio: 100 / 200;height: auto;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="test" alt="test" width="100%" style="width: 100%;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="test" alt="test" height="100%" style="height: 100%;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="test" alt="test" width="100%" height="100%" style="width: 100%;height: 100%;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="test" alt="test" width="100%" height="200" style="width: 100%;height: 200px;"></p> | ||
. | ||
. | ||
 | ||
. | ||
<p><img src="test" alt="test" width="100" height="100%" style="width: 100px;height: 100%;"></p> | ||
. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe better is
enableInlineStyling