Skip to content

Commit 291f2b6

Browse files
committed
add width height maxWidth maxHeight attributes to image markdown parser
1 parent 516a6ff commit 291f2b6

File tree

2 files changed

+89
-7
lines changed

2 files changed

+89
-7
lines changed

client/src/components/MarkDown.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@
77
min-height: 520px;
88
99
svg {
10-
max-width: 100% !important;
11-
height: auto !important;
10+
max-width: 100%;
11+
height: auto;
1212
1313
g > * :not(text) {
1414
stroke: #ccc !important;
1515
}
1616
}
1717
1818
img {
19-
max-width: 100% !important;
20-
height: auto !important;
19+
max-width: 100%;
20+
height: auto;
2121
}
2222
2323
audio {
24-
max-width: 100% !important;
25-
margin: 10px 0 !important;
24+
max-width: 100%;
25+
margin: 10px 0;
2626
}
2727
}
2828
</style>

common/src/markdown-converter-common.ts

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,90 @@ export abstract class MarkdownConverter {
121121
}
122122
return `<audio controls><source src="${href}" type="${audioType}">Your browser does not support the audio element.</audio>`;
123123
}
124+
125+
// Parse attributes from title attribute (format: "title|width:300px|height:200px|maxWidth:400px|maxHeight:300px|class:my-class")
126+
let imgTitle = title || "";
127+
let imgWidth = "";
128+
let imgHeight = "";
129+
let imgMaxWidth = "";
130+
let imgMaxHeight = "";
131+
let imgClass = "";
132+
133+
if (title && title.includes("|")) {
134+
const parts = title.split("|");
135+
imgTitle = parts[0];
136+
137+
for (let i = 1; i < parts.length; i++) {
138+
const part = parts[i];
139+
if (part.startsWith("width:")) {
140+
imgWidth = part.substring(6);
141+
} else if (part.startsWith("height:")) {
142+
imgHeight = part.substring(7);
143+
} else if (part.startsWith("maxWidth:")) {
144+
imgMaxWidth = part.substring(9);
145+
} else if (part.startsWith("maxHeight:")) {
146+
imgMaxHeight = part.substring(10);
147+
} else if (part.startsWith("class:")) {
148+
imgClass = part.substring(6);
149+
}
150+
}
151+
}
152+
153+
// Parse attributes from custom syntax in text (format: "alt{width=300px,height=200px,maxWidth=400px,maxHeight=300px,class=my-class}")
154+
if (text && text.includes("{")) {
155+
const match = text.match(/(.*?)\{([^}]+)\}/);
156+
if (match) {
157+
const [, altText, attributesStr] = match;
158+
text = altText;
159+
160+
// Parse comma-separated attributes
161+
const attributes = attributesStr.split(",");
162+
for (const attr of attributes) {
163+
const [key, value] = attr.split("=");
164+
if (key === "width") {
165+
imgWidth = value;
166+
} else if (key === "height") {
167+
imgHeight = value;
168+
} else if (key === "maxWidth") {
169+
imgMaxWidth = value;
170+
} else if (key === "maxHeight") {
171+
imgMaxHeight = value;
172+
} else if (key === "class") {
173+
imgClass = value;
174+
}
175+
}
176+
}
177+
}
178+
179+
// Build attributes
180+
const attributes = [`src="${href}"`, `alt="${text || ""}"`];
181+
if (imgTitle) {
182+
attributes.push(`title="${imgTitle}"`);
183+
}
184+
if (imgClass) {
185+
attributes.push(`class="${imgClass}"`);
186+
}
187+
188+
// Build style attribute
189+
const styles = [];
190+
if (imgWidth) {
191+
styles.push(`width: ${imgWidth}`);
192+
}
193+
if (imgHeight) {
194+
styles.push(`height: ${imgHeight}`);
195+
}
196+
if (imgMaxWidth) {
197+
styles.push(`max-width: ${imgMaxWidth}`);
198+
}
199+
if (imgMaxHeight) {
200+
styles.push(`max-height: ${imgMaxHeight}`);
201+
}
202+
if (styles.length > 0) {
203+
attributes.push(`style="${styles.join("; ")}"`);
204+
}
205+
124206
// Default image rendering
125-
return `<img src="${href}" alt="${text || ""}" title="${title || ""}">`;
207+
return `<img ${attributes.join(" ")}>`;
126208
},
127209
},
128210
});

0 commit comments

Comments
 (0)