Skip to content
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
194 changes: 98 additions & 96 deletions dist/capture-engine.bundle.mjs

Large diffs are not rendered by default.

698 changes: 350 additions & 348 deletions dist/mcp-server.bundle.mjs

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions src/lib/capture-export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,79 @@ if ( existsSync( ${ JSON.stringify( join( outputDir, '.capture-export-html' ) )
expect( html ).toContain( '<canvas id="canvas" width="1440" height="900"></canvas>' );
} );

it( 'preserves mobile styles when matching responsive bodies style themselves differently', () => {
const outputDir = mkdtempSync( join( tmpdir(), 'dla-capture-export-' ) );
dirs.push( outputDir );
mkdirSync( join( outputDir, 'html' ), { recursive: true } );
mkdirSync( join( outputDir, 'html-mobile' ), { recursive: true } );
mkdirSync( join( outputDir, 'screenshots' ), { recursive: true } );
writeFileSync(
join( outputDir, 'html', 'homepage.html' ),
'<!doctype html><html><head><style>main{color:blue}</style><style media="print">main{margin:0}</style></head><body><main><h1>Home</h1></main></body></html>'
);
writeFileSync(
join( outputDir, 'html-mobile', 'homepage.html' ),
'<!doctype html><html><head><meta name="viewport" content="width=device-width, initial-scale=1"><style>main{color:red}</style></head><body><main><h1>Home</h1></main></body></html>'
);
writeFileSync(
join( outputDir, 'screenshots', 'manifest.json' ),
JSON.stringify( {
version: 1,
entries: { 'https://example.com/': { html: 'html/homepage.html' } },
} )
);

exportWebsiteCapture( {
outputDir,
sourceUrl: 'https://example.com/',
platform: 'fake',
summary: {},
failures: [],
} );
const html = readFileSync( join( outputDir, 'website', 'index.html' ), 'utf8' );
expect( html ).not.toContain( 'data-liberation-desktop-document' );
expect( html ).not.toContain( 'data-liberation-mobile-document' );
expect( html ).toContain( '<style media="(min-width:769px)">main{color:blue}</style>' );
expect( html ).toContain(
'<style media="(min-width:769px) and (print)">main{margin:0}</style>'
);
expect( html ).toContain( '<style media="(max-width:768px)">main{color:red}</style>' );
expect( html ).toContain( 'name="viewport"' );
} );

it( 'keeps shared styles unwrapped when matching responsive bodies style themselves identically', () => {
const outputDir = mkdtempSync( join( tmpdir(), 'dla-capture-export-' ) );
dirs.push( outputDir );
mkdirSync( join( outputDir, 'html' ), { recursive: true } );
mkdirSync( join( outputDir, 'html-mobile' ), { recursive: true } );
mkdirSync( join( outputDir, 'screenshots' ), { recursive: true } );
const document =
'<!doctype html><html><head><style>main{color:blue}</style></head><body><main><h1>Home</h1></main></body></html>';
writeFileSync( join( outputDir, 'html', 'homepage.html' ), document );
writeFileSync( join( outputDir, 'html-mobile', 'homepage.html' ), document );
writeFileSync(
join( outputDir, 'screenshots', 'manifest.json' ),
JSON.stringify( {
version: 1,
entries: { 'https://example.com/': { html: 'html/homepage.html' } },
} )
);

exportWebsiteCapture( {
outputDir,
sourceUrl: 'https://example.com/',
platform: 'fake',
summary: {},
failures: [],
} );
const html = readFileSync( join( outputDir, 'website', 'index.html' ), 'utf8' );
expect( html ).not.toContain( 'data-liberation-desktop-document' );
expect( html ).not.toContain( 'data-liberation-mobile-document' );
expect( html ).toContain( '<style>main{color:blue}</style>' );
expect( html ).not.toContain( '(min-width:769px)' );
expect( html ).not.toContain( '(max-width:768px)' );
} );

it( 'shares identical responsive styles when both authoring bodies are required', () => {
const outputDir = mkdtempSync( join( tmpdir(), 'dla-capture-export-' ) );
dirs.push( outputDir );
Expand Down
18 changes: 11 additions & 7 deletions src/lib/capture-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,14 @@ function responsiveHtml( desktopHtml: string, mobileHtml: string ): string {
? html.replace( /<meta\b[^>]*\bname\s*=\s*(["'])viewport\1[^>]*>/i, mobileViewport )
: html.replace( /<\/head\s*>/i, `${ mobileViewport }</head>` );
};
if ( responsiveBodySignature( desktopBody ) === responsiveBodySignature( mobileBody ) )
return withMobileViewport( desktopHtml );
if ( responsiveBodySignature( desktopBody ) === responsiveBodySignature( mobileBody ) ) {
if ( styleBlocks( desktopHtml ).join( '\n' ) === styleBlocks( mobileHtml ).join( '\n' ) )
return withMobileViewport( desktopHtml );
return withMobileViewport( scopedStyles( desktopHtml, '(min-width:769px)' ) ).replace(
/<\/head\s*>/i,
`${ responsiveMobileStyles( mobileHtml ) }</head>`
);
}

const wrapperAttributes = ( baseClass: string, bodyAttributes: string ): string => {
const body = cheerio.load( `<body${ bodyAttributes }></body>` )( 'body' );
Expand Down Expand Up @@ -388,7 +394,7 @@ function responsiveHtml( desktopHtml: string, mobileHtml: string ): string {
( _match, closingBody: string ) => `<body>${ responsiveBody }${ closingBody }`
);
}
const mobileStyles = responsiveMobileStyles( mobileHtml );
const mobileStyles = responsiveMobileStyles( mobileHtml, '.data-liberation-mobile-document' );
return withMobileViewport( scopedStyles( desktopHtml, '(min-width:769px)' ) )
.replace(
/<\/head\s*>/i,
Expand Down Expand Up @@ -430,14 +436,12 @@ function portableInlineStyleValues(
return { key: `${ media }\n${ css }`, media };
}

function responsiveMobileStyles( mobileHtml: string ): string {
function responsiveMobileStyles( mobileHtml: string, scope?: string ): string {
return styleBlocks( mobileHtml )
.filter( Boolean )
.map(
( style ) =>
`<style media="(max-width:768px)">${ scopeCss( style, {
scope: '.data-liberation-mobile-document',
} ) }</style>`
`<style media="(max-width:768px)">${ scope ? scopeCss( style, { scope } ) : style }</style>`
)
.join( '' );
}
Expand Down
Loading