Skip to content

Commit

Permalink
Added attribute caching to img
Browse files Browse the repository at this point in the history
  • Loading branch information
mjasikowski committed Sep 25, 2024
1 parent 7c97955 commit 6ce6391
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 deletions.
2 changes: 1 addition & 1 deletion __tests__/ExpensiMark-HTML-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2102,7 +2102,7 @@ describe('Video markdown conversion to html tag', () => {
const resultString = '<video data-expensify-source="https://example.com/video.mp4" data-expensify-height="100" data-expensify-width="100">test</video>';
expect(parser.replace(testString, {
extras: {
videoAttributeCache: {
mediaAttributeCache: {
'https://example.com/video.mp4': 'data-expensify-height="100" data-expensify-width="100"'
}
}
Expand Down
18 changes: 15 additions & 3 deletions __tests__/ExpensiMark-Markdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,18 @@ describe('Image tag conversion to markdown', () => {
const resultString = '![```code```](https://example.com/image.png)';
expect(parser.htmlToMarkdown(testString)).toBe(resultString);
});

test('Cache extra attributes for img', () => {
const cacheMediaAttributes = jest.fn();
const testString = '<img src="https://example.com/image.png" alt="altText" data-expensify-width="100" data-expensify-height="500" data-name="newName" data-expensify-source="expensify-source" />';
const resultString = '![altText](https://example.com/image.png)';
const extras = {
cacheMediaAttributes,
};
expect(parser.htmlToMarkdown(testString, extras)).toBe(resultString);
expect(cacheMediaAttributes).toHaveBeenCalledWith("https://example.com/image.png", 'data-expensify-width="100" data-expensify-height="500" data-name="newName" data-expensify-source="expensify-source"')
});

});

describe('Video tag conversion to markdown', () => {
Expand All @@ -883,14 +895,14 @@ describe('Video tag conversion to markdown', () => {
})

test('While convert video, cache some extra attributes from the video tag', () => {
const cacheVideoAttributes = jest.fn();
const cacheMediaAttributes = jest.fn();
const testString = '<video data-expensify-source="https://example.com/video.mp4" data-expensify-width="100" data-expensify-height="500" data-expensify-thumbnail-url="https://image.com/img.jpg">video</video>';
const resultString = '![video](https://example.com/video.mp4)';
const extras = {
cacheVideoAttributes,
cacheMediaAttributes,
};
expect(parser.htmlToMarkdown(testString, extras)).toBe(resultString);
expect(cacheVideoAttributes).toHaveBeenCalledWith("https://example.com/video.mp4", ' data-expensify-width="100" data-expensify-height="500" data-expensify-thumbnail-url="https://image.com/img.jpg"')
expect(cacheMediaAttributes).toHaveBeenCalledWith("https://example.com/video.mp4", ' data-expensify-width="100" data-expensify-height="500" data-expensify-thumbnail-url="https://image.com/img.jpg"')
})
})

Expand Down
48 changes: 36 additions & 12 deletions lib/ExpensiMark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import * as Utils from './utils';
type Extras = {
reportIDToName?: Record<string, string>;
accountIDToName?: Record<string, string>;
cacheVideoAttributes?: (vidSource: string, attrs: string) => void;
videoAttributeCache?: Record<string, string>;
cacheMediaAttributes?: (mediaSource: string, attrs: string) => void;
mediaAttributeCache?: Record<string, string>;
};
const EXTRAS_DEFAULT = {};

Expand Down Expand Up @@ -171,11 +171,11 @@ export default class ExpensiMark {
* @return Returns the HTML video tag
*/
replacement: (extras, _match, videoName, videoSource) => {
const extraAttrs = extras && extras.videoAttributeCache && extras.videoAttributeCache[videoSource];
const extraAttrs = extras && extras.mediaAttributeCache && extras.mediaAttributeCache[videoSource];
return `<video data-expensify-source="${Str.sanitizeURL(videoSource)}" ${extraAttrs || ''}>${videoName ? `${videoName}` : ''}</video>`;
},
rawInputReplacement: (extras, _match, videoName, videoSource) => {
const extraAttrs = extras && extras.videoAttributeCache && extras.videoAttributeCache[videoSource];
const extraAttrs = extras && extras.mediaAttributeCache && extras.mediaAttributeCache[videoSource];
return `<video data-expensify-source="${Str.sanitizeURL(videoSource)}" data-raw-href="${videoSource}" data-link-variant="${typeof videoName === 'string' ? 'labeled' : 'auto'}" ${extraAttrs || ''}>${videoName ? `${videoName}` : ''}</video>`;
},
},
Expand Down Expand Up @@ -658,13 +658,37 @@ export default class ExpensiMark {

{
name: 'image',
regex: /<img[^><]*src\s*=\s*(['"])(.*?)\1(?:[^><]*alt\s*=\s*(['"])(.*?)\3)?[^><]*>*(?![^<][\s\S]*?(<\/pre>|<\/code>))/gi,
replacement: (_extras, _match, _g1, g2, _g3, g4) => {
if (g4) {
return `![${g4}](${g2})`;
regex: /<img[^><]*src\s*=\s*(['"])(.*?)\1(.*?)>(?![^<][\s\S]*?(<\/pre>|<\/code>))/gi,
/**
* @param extras - The extras object
* @param match - The full match
* @param _g1 - The first capture group (the quote)
* @param imgSource - The second capture group - src attribute value
* @param imgAttrs - The third capture group - any attributes after src
* @returns The markdown image tag
*/
replacement: (extras, _match, _g1, imgSource, imgAttrs) => {
// Extract alt attribute from imgAttrs
let altText = '';
const altRegex = /alt\s*=\s*(['"])(.*?)\1/i;
const altMatch = imgAttrs.match(altRegex);
let attributes = '';
if (altMatch) {
altText = altMatch[2];
// Remove the alt attribute from imgAttrs
attributes = imgAttrs.replace(altRegex, '');
}

return `!(${g2})`;
// Remove trailing slash and extra whitespace
attributes = attributes.replace(/\s*\/\s*$/, '').trim();
// Cache attributes without alt and trailing slash
if (imgAttrs && extras && extras.cacheMediaAttributes && typeof extras.cacheMediaAttributes === 'function') {
extras.cacheMediaAttributes(imgSource, attributes);
}
// Return the markdown image tag
if (altText) {
return `![${altText}](${imgSource})`;
}
return `!(${imgSource})`;
},
},

Expand All @@ -681,8 +705,8 @@ export default class ExpensiMark {
* @returns The markdown video tag
*/
replacement: (extras, _match, _g1, videoSource, videoAttrs, videoName) => {
if (videoAttrs && extras && extras.cacheVideoAttributes && typeof extras.cacheVideoAttributes === 'function') {
extras.cacheVideoAttributes(videoSource, videoAttrs);
if (videoAttrs && extras && extras.cacheMediaAttributes && typeof extras.cacheMediaAttributes === 'function') {
extras.cacheMediaAttributes(videoSource, videoAttrs);
}
if (videoName) {
return `![${videoName}](${videoSource})`;
Expand Down

0 comments on commit 6ce6391

Please sign in to comment.