Skip to content

Commit

Permalink
feat(plugin-pages): add validation for glob patterns
Browse files Browse the repository at this point in the history
Related to #132
  • Loading branch information
GerkinDev committed Jul 24, 2022
1 parent f8e4938 commit fb7c56a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
38 changes: 24 additions & 14 deletions packages/plugin-pages/src/options/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,30 @@ const pageKeys: Array<keyof IPageNode> = [ 'children', 'childrenDir', 'childrenO
const checkPageFactory = <T extends IPageNode>( allowedKeys: Array<keyof T> ) => ( plugin: PagesPlugin, page: unknown, path: string[] ): asserts page is T => {
assert( page && isObject( page ), 'Page should be an object' );
const _page = page as Record<string, unknown>;
if( 'title' in _page && !( 'name' in _page ) ){
_page.name = _page.title;
delete _page.title;
plugin.logger.warn( `Page ${[ ...path, _page.name ].map( p => `"${p}"` ).join( ' ⇒ ' )} is using deprecated "title" property. Use "name" instead.` );
}
assert( 'name' in _page && isString( _page.name ), 'Page should have a name' );
const extraProps = difference( Object.keys( _page ), allowedKeys as string[] );
assert.equal( extraProps.length, 0, `Page ${[ ...path, _page.name ].map( p => `"${p}"` ).join( ' ⇒ ' )} have extra properties ${JSON.stringify( extraProps )}` );
if( 'children' in _page && !isNil( _page.children ) ){
assert( isArray( _page.children ), 'Page children should be an array' );
const thisPath = [ ...path, _page.name as string ];
_page.children.forEach( ( c, i ) => miscUtils.catchWrap(
() => checkPage( plugin, c, thisPath ),
wrapPageError( thisPath, i ) ) );
const pagePath = () => [ ...path, _page.name ].map( p => `"${p ?? 'Unnamed'}"` ).join( ' ⇒ ' );
if( 'match' in page && 'template' in page ){
assert( isString( _page.match ) );
assert( isArray( _page.template ) );
const selfFn = checkPageFactory( allowedKeys );
_page.template.forEach( ( t, i ) => selfFn( plugin, t, [ ...path, `TEMPLATE ${i + 1}` ] ) );
} else if( !( 'match' in page ) && !( 'template' in page ) ){
if( 'title' in _page && !( 'name' in _page ) ){
_page.name = _page.title;
delete _page.title;
plugin.logger.warn( `Page ${pagePath()} is using deprecated "title" property. Use "name" instead.` );
}
assert( 'name' in _page && isString( _page.name ), `Page ${pagePath()} should have a name` );
const extraProps = difference( Object.keys( _page ), allowedKeys as string[] );
assert.equal( extraProps.length, 0, `Page ${pagePath()} have extra properties ${JSON.stringify( extraProps )}` );
if( 'children' in _page && !isNil( _page.children ) ){
assert( isArray( _page.children ), `Page ${pagePath()} "children" should be an array` );
const thisPath = [ ...path, _page.name as string ];
_page.children.forEach( ( c, i ) => miscUtils.catchWrap(
() => checkPage( plugin, c, thisPath ),
wrapPageError( thisPath, i ) ) );
}
} else {
throw new Error( `Page ${pagePath()} has a "match" or "template" property, but it should have both or none` );
}
};
const checkPage = checkPageFactory<IPageNode>( pageKeys );
Expand Down
17 changes: 17 additions & 0 deletions packages/plugin-pages/src/options/options.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,21 @@ describe( 'Pages', () => {
expect( application.logger.warn ).toHaveBeenCalledTimes( 1 );
expect( application.logger.warn ).toHaveBeenCalledWith( expect.toInclude( 'Page "A" is using deprecated "title" property. Use "name" instead.' ) );
} );
it( 'should throw if page has a `match` property, but no `template`', () => {
expect( () => options.setValue( { pages: [
{ match: 'A' },
] } ) ).toThrow( 'Page "Unnamed" has a "match" or "template" property, but it should have both or none' );
} );
it( 'should throw if page has a `template` property, but no `match`', () => {
expect( () => options.setValue( { pages: [
{ template: [] },
] } ) ).toThrow( 'Page "Unnamed" has a "match" or "template" property, but it should have both or none' );
} );
it( 'should throw if page has a `template` property with invalid child', () => {
expect( () => options.setValue( { pages: [
{ match: 'foo', template: [
{ asd: false },
] },
] } ) ).toThrow( 'Page "TEMPLATE 1" ⇒ "Unnamed" should have a name' );
} );
} );

0 comments on commit fb7c56a

Please sign in to comment.