@@ -288,6 +288,124 @@ describe("writr", () => {
288288 } ) ;
289289} ) ;
290290
291+ describe ( "Writr rawHtml" , ( ) => {
292+ it ( "should strip raw HTML by default" , async ( ) => {
293+ const writr = new Writr ( '# Hello\n\n<div class="custom">content</div>' ) ;
294+ const result = await writr . render ( ) ;
295+ expect ( result ) . not . toContain ( "<div" ) ;
296+ } ) ;
297+
298+ it ( "should preserve div tags with attributes when rawHtml is true" , async ( ) => {
299+ const writr = new Writr ( '# Hello\n\n<div class="custom">content</div>' ) ;
300+ const result = await writr . render ( { rawHtml : true } ) ;
301+ expect ( result ) . toContain ( '<div class="custom">content</div>' ) ;
302+ } ) ;
303+
304+ it ( "should preserve iframe tags with attributes when rawHtml is true" , async ( ) => {
305+ const writr = new Writr (
306+ '# Hello\n\n<iframe src="https://example.com" width="560" height="315"></iframe>' ,
307+ ) ;
308+ const result = await writr . render ( { rawHtml : true } ) ;
309+ expect ( result ) . toContain ( "<iframe" ) ;
310+ expect ( result ) . toContain ( 'src="https://example.com"' ) ;
311+ expect ( result ) . toContain ( 'width="560"' ) ;
312+ } ) ;
313+
314+ it ( "should preserve raw HTML with renderSync when rawHtml is true" , ( ) => {
315+ const writr = new Writr ( '# Hello\n\n<div class="custom">content</div>' ) ;
316+ const result = writr . renderSync ( { rawHtml : true } ) ;
317+ expect ( result ) . toContain ( '<div class="custom">content</div>' ) ;
318+ } ) ;
319+
320+ it ( "should strip raw HTML when rawHtml is explicitly false" , async ( ) => {
321+ const writr = new Writr ( '# Hello\n\n<div class="custom">content</div>' ) ;
322+ const result = await writr . render ( { rawHtml : false } ) ;
323+ expect ( result ) . not . toContain ( "<div" ) ;
324+ } ) ;
325+
326+ it ( "should be settable via constructor options" , ( ) => {
327+ const writr = new Writr ( {
328+ renderOptions : {
329+ rawHtml : true ,
330+ } ,
331+ } ) ;
332+ expect ( writr . options . renderOptions ?. rawHtml ) . toEqual ( true ) ;
333+ } ) ;
334+ } ) ;
335+
336+ describe ( "Writr mdx HTML passthrough" , ( ) => {
337+ it ( "should preserve iframe tags with attributes when mdx is true" , async ( ) => {
338+ const writr = new Writr (
339+ '# Hello\n\n<iframe src="https://example.com" width="560" height="315"></iframe>' ,
340+ ) ;
341+ const result = await writr . render ( { mdx : true } ) ;
342+ expect ( result ) . toContain ( "<iframe" ) ;
343+ expect ( result ) . toContain ( 'src="https://example.com"' ) ;
344+ expect ( result ) . toContain ( 'width="560"' ) ;
345+ expect ( result ) . toContain ( 'height="315"' ) ;
346+ } ) ;
347+
348+ it ( "should preserve div tags with attributes when mdx is true" , async ( ) => {
349+ const writr = new Writr ( '# Hello\n\n<div class="custom">content</div>' ) ;
350+ const result = await writr . render ( { mdx : true } ) ;
351+ expect ( result ) . toContain ( '<div class="custom">' ) ;
352+ expect ( result ) . toContain ( "content" ) ;
353+ } ) ;
354+
355+ it ( "should preserve boolean attributes when mdx is true" , async ( ) => {
356+ const writr = new Writr ( '<video src="vid.mp4" controls></video>' ) ;
357+ const result = await writr . render ( { mdx : true } ) ;
358+ expect ( result ) . toContain ( "<video" ) ;
359+ expect ( result ) . toContain ( 'src="vid.mp4"' ) ;
360+ expect ( result ) . toContain ( "controls" ) ;
361+ } ) ;
362+
363+ it ( "should preserve inline HTML elements when mdx is true" , async ( ) => {
364+ const writr = new Writr ( 'Hello <span style="color:red">world</span> there' ) ;
365+ const result = await writr . render ( { mdx : true } ) ;
366+ expect ( result ) . toContain ( '<span style="color:red">world</span>' ) ;
367+ } ) ;
368+
369+ it ( "should preserve iframe tags with renderSync when mdx is true" , ( ) => {
370+ const writr = new Writr (
371+ '<iframe src="https://example.com" width="560"></iframe>' ,
372+ ) ;
373+ const result = writr . renderSync ( { mdx : true } ) ;
374+ expect ( result ) . toContain ( "<iframe" ) ;
375+ expect ( result ) . toContain ( 'src="https://example.com"' ) ;
376+ } ) ;
377+
378+ it ( "should render a fragment as a div when mdx is true" , async ( ) => {
379+ const writr = new Writr ( "<>fragment content</>" ) ;
380+ const result = await writr . render ( { mdx : true } ) ;
381+ expect ( result ) . toContain ( "<div>" ) ;
382+ expect ( result ) . toContain ( "fragment content" ) ;
383+ } ) ;
384+
385+ it ( "should handle elements with no attributes when mdx is true" , async ( ) => {
386+ const writr = new Writr ( "<section>hello</section>" ) ;
387+ const result = await writr . render ( { mdx : true } ) ;
388+ expect ( result ) . toContain ( "<section>" ) ;
389+ expect ( result ) . toContain ( "hello" ) ;
390+ } ) ;
391+
392+ it ( "should skip spread expression attributes and keep named attributes when mdx is true" , async ( ) => {
393+ const writr = new Writr ( '<Comp {...props} foo="bar" />\n' ) ;
394+ const result = await writr . render ( { mdx : true } ) ;
395+ expect ( result ) . toContain ( 'foo="bar"' ) ;
396+ expect ( result ) . not . toContain ( "props" ) ;
397+ } ) ;
398+
399+ it ( "should skip expression attribute values when mdx is true" , async ( ) => {
400+ const writr = new Writr ( "<div data-x={42}>hello</div>" ) ;
401+ const result = await writr . render ( { mdx : true } ) ;
402+ expect ( result ) . toContain ( "<div>" ) ;
403+ expect ( result ) . toContain ( "hello" ) ;
404+ expect ( result ) . not . toContain ( "object" ) ;
405+ expect ( result ) . not . toContain ( "42" ) ;
406+ } ) ;
407+ } ) ;
408+
291409describe ( "WritrFrontMatter" , ( ) => {
292410 test ( "should initialize with content and work from same object" , ( ) => {
293411 const writr = new Writr ( productPageWithMarkdown ) ;
0 commit comments