Skip to content

Commit

Permalink
Refactor Renderer builder, replace types and interfaces to the Abstra…
Browse files Browse the repository at this point in the history
…ct renderer
  • Loading branch information
VadimKovalenkoSNF committed Aug 21, 2023
1 parent 14fd7a4 commit df401b5
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 63 deletions.
14 changes: 2 additions & 12 deletions src/Downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,6 @@ interface BackoffOptions {
backoffHandler: (number: number, delay: number, error?: any) => void
}

export interface RenderOpts {
data?: any
articleId?: string
articleDetailXId?: RKVS<ArticleDetail>
articleDetail?: ArticleDetail | string
isMainPage?: boolean
}

export const defaultStreamRequestOptions: AxiosRequestConfig = {
headers: {
accept: 'application/octet-stream',
Expand Down Expand Up @@ -329,15 +321,13 @@ class Downloader {
throw data.error
}

const renderOpts: RenderOpts = {
return articleRenderer.render({
data,
articleId,
articleDetailXId,
articleDetail,
isMainPage,
}

return articleRenderer.render(renderOpts)
})
}

public async getJSON<T>(_url: string): Promise<T> {
Expand Down
28 changes: 27 additions & 1 deletion src/util/renderers/abstract.renderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
import { RenderOpts } from './../../Downloader.js'
type RenderMode = 'auto' | 'desktop' | 'mobile' | 'specific'
type RenderAPI = 'VisualEditor' | 'WikimediaDesktop' | 'WikimediaMobile'

interface RendererBuilderOptionsBase {
renderMode: RenderMode
}

interface RendererBuilderOptionsCommon {
renderMode: RenderMode
renderAPI?: never
}

interface RendererBuilderOptionsSpecific extends RendererBuilderOptionsBase {
renderMode: 'specific'
renderAPI: RenderAPI
}

export type RendererBuilderOptions = RendererBuilderOptionsCommon | RendererBuilderOptionsSpecific

export interface RenderOpts {
data?: any
articleId?: string
articleDetailXId?: RKVS<ArticleDetail>
articleDetail?: ArticleDetail | string
isMainPage?: boolean
}

export abstract class Renderer {
abstract render(renderOpts: RenderOpts): Promise<any>
}
24 changes: 9 additions & 15 deletions src/util/renderers/renderer.builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,24 @@ import MediaWiki from './../../MediaWiki.js'
import { Renderer } from './abstract.renderer.js'
import { VisualEditorRenderer } from './visual-editor.renderer.js'
import { WikimediaDesktopRenderer } from './wikimedia-desktop.renderer.js'
import { RendererBuilderOptions } from './../saveArticles.js'
import { RendererBuilderOptions } from './abstract.renderer.js'
import * as logger from './../../Logger.js'

export class RendererBuilder {
private renderApi: 'VisualEditor' | 'WikimediaDesktop' | 'WikimediaMobile'
private renderMode: 'auto' | 'desktop' | 'mobile' | 'specific'

public async createRenderer(options: RendererBuilderOptions): Promise<Renderer> {
const { RendererMode, RendererAPI } = options

this.renderMode = RendererMode
this.renderApi = RendererAPI
const { renderMode, renderAPI } = options

const [hasVisualEditorApi, hasWikimediaDesktopRestApi] = await Promise.all([MediaWiki.hasVisualEditorApi(), MediaWiki.hasWikimediaDesktopRestApi()])

switch (this.renderMode) {
switch (renderMode) {
case 'desktop':
if (hasWikimediaDesktopRestApi) {
// Choose WikimediaDesktopRenderer if it's present, regardless of hasVisualEditorApi value
return new WikimediaDesktopRenderer()
} else if (hasVisualEditorApi) {
return new VisualEditorRenderer()
} else {
logger.error('No available renderer for desktop mode.')
logger.error('No available desktop renderer.')
process.exit(1)
}
case 'mobile':
Expand All @@ -38,12 +32,12 @@ export class RendererBuilder {
} else if (hasVisualEditorApi) {
return new VisualEditorRenderer()
} else {
logger.error('No available renderer for auto mode.')
logger.error('No render available at all.')
process.exit(1)
}
case 'specific':
// renderApi argument is required for 'specific' mode
switch (this.renderApi) {
// renderAPI argument is required for 'specific' mode
switch (renderAPI) {
case 'WikimediaDesktop':
if (hasWikimediaDesktopRestApi) {
return new WikimediaDesktopRenderer()
Expand All @@ -60,10 +54,10 @@ export class RendererBuilder {
// TODO: return WikimediaMobile renderer
return
default:
throw new Error(`Unknown RendererAPI for specific mode: ${this.renderApi}`)
throw new Error(`Unknown renderAPI for specific mode: ${renderAPI}`)
}
default:
throw new Error(`Unknown render mode: ${this.renderMode}`)
throw new Error(`Unknown render: ${renderMode}`)
}
}
}
2 changes: 1 addition & 1 deletion src/util/renderers/visual-editor.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DELETED_ARTICLE_ERROR } from '../const.js'
import * as logger from '../../Logger.js'
import { Renderer } from './abstract.renderer.js'
import { getStrippedTitleFromHtml } from '../misc.js'
import { RenderOpts } from './../../Downloader.js'
import { RenderOpts } from './abstract.renderer.js'

/*
Represent 'https://{wikimedia-wiki}/w/api.php?action=visualeditor&mobileformat=html&format=json&paction=parse&page={title}'
Expand Down
2 changes: 1 addition & 1 deletion src/util/renderers/wikimedia-desktop.renderer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import domino from 'domino'
import { Renderer } from './abstract.renderer.js'
import { getStrippedTitleFromHtml } from '../misc.js'
import { RenderOpts } from '../../Downloader.js'
import { RenderOpts } from './abstract.renderer.js'

// Represent 'https://{wikimedia-wiki}/api/rest_v1/page/html/'
export class WikimediaDesktopRenderer extends Renderer {
Expand Down
23 changes: 2 additions & 21 deletions src/util/saveArticles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,12 @@ import { CONCURRENCY_LIMIT, DELETED_ARTICLE_ERROR, MAX_FILE_DOWNLOAD_RETRIES } f
import ApiURLDirector from './builders/url/api.director.js'
import articleTreatment from './treatments/article.treatment.js'
import urlHelper from './url.helper.js'
import { Renderer } from './renderers/abstract.renderer.js'
import { RendererBuilderOptions, Renderer } from './renderers/abstract.renderer.js'
import { RendererBuilder } from './renderers/renderer.builder.js'

const genericJsModules = config.output.mw.js
const genericCssModules = config.output.mw.css

type RendererMode = 'auto' | 'desktop' | 'mobile' | 'specific'
type RendererAPI = 'VisualEditor' | 'WikimediaDesktop' | 'WikimediaMobile'

interface RendererBuilderOptionsBase {
RendererMode: RendererMode
}

interface RendererBuilderOptionsCommon {
RendererMode: RendererMode
RendererAPI?: never
}

interface RendererBuilderOptionsSpecific extends RendererBuilderOptionsBase {
RendererMode: 'specific'
RendererAPI: RendererAPI
}

export type RendererBuilderOptions = RendererBuilderOptionsCommon | RendererBuilderOptionsSpecific

export async function downloadFiles(fileStore: RKVS<FileDetail>, retryStore: RKVS<FileDetail>, zimCreator: ZimCreator, dump: Dump, downloader: Downloader, retryCounter = 0) {
await retryStore.flush()
const filesForAttempt = await fileStore.len()
Expand Down Expand Up @@ -276,7 +257,7 @@ export async function saveArticles(zimCreator: ZimCreator, downloader: Downloade

const rendererBuilder = new RendererBuilder()
const rendererBuilderOptions: RendererBuilderOptions = {
RendererMode: 'auto',
renderMode: 'auto',
}
const mainPageRenderer = await rendererBuilder.createRenderer(rendererBuilderOptions)
// TODO: article renderer will be switched to the mobiel mode later
Expand Down
24 changes: 12 additions & 12 deletions test/unit/renderers/renderer.builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { jest } from '@jest/globals'
import { setupScrapeClasses } from '../../util.js'
import { RendererBuilder } from '../../../src/util/renderers/renderer.builder.js'
import { VisualEditorRenderer } from '../../../src/util/renderers/visual-editor.renderer.js'
import { RendererBuilderOptions } from '../../../src/util/renderers/abstract.renderer.js'
import { WikimediaDesktopRenderer } from '../../../src/util/renderers/wikimedia-desktop.renderer.js'
import { RendererBuilderOptions } from '../../../src/util/saveArticles.js'

jest.setTimeout(10000)

Expand All @@ -18,7 +18,7 @@ describe('RendererBuilder', () => {

const renderer = await rendererBuilder.createRenderer({
MediaWiki,
RendererMode: 'desktop',
renderMode: 'desktop',
} as RendererBuilderOptions)
expect(renderer).toBeInstanceOf(WikimediaDesktopRenderer)
})
Expand All @@ -28,7 +28,7 @@ describe('RendererBuilder', () => {

const renderer = await rendererBuilder.createRenderer({
MediaWiki,
RendererMode: 'auto',
renderMode: 'auto',
} as RendererBuilderOptions)
expect(renderer).toBeInstanceOf(WikimediaDesktopRenderer)
})
Expand All @@ -39,9 +39,9 @@ describe('RendererBuilder', () => {
expect(async () => {
await rendererBuilder.createRenderer({
MediaWiki,
RendererMode: 'unknownMode' as any,
renderMode: 'unknownMode' as any,
} as RendererBuilderOptions)
}).rejects.toThrow('Unknown render mode: unknownMode')
}).rejects.toThrow('Unknown render: unknownMode')
})

it('should return VisualEditorRenderer for specific mode with RendererAPI as VisualEditor', async () => {
Expand All @@ -52,8 +52,8 @@ describe('RendererBuilder', () => {

const rendererBuilderOptions = {
MediaWiki,
RendererMode: 'specific',
RendererAPI: 'VisualEditor',
renderMode: 'specific',
renderAPI: 'VisualEditor',
}

const renderer = await rendererBuilder.createRenderer(rendererBuilderOptions as RendererBuilderOptions)
Expand All @@ -69,8 +69,8 @@ describe('RendererBuilder', () => {

const rendererBuilderOptions = {
MediaWiki,
RendererMode: 'specific',
RendererAPI: 'WikimediaDesktop',
renderMode: 'specific',
renderAPI: 'WikimediaDesktop',
}

const renderer = await rendererBuilder.createRenderer(rendererBuilderOptions as RendererBuilderOptions)
Expand All @@ -86,12 +86,12 @@ describe('RendererBuilder', () => {

const rendererBuilderOptions = {
MediaWiki,
RendererMode: 'specific',
RendererAPI: 'UnknownAPI', // Using an invalid RendererAPI for the test
renderMode: 'specific',
renderAPI: 'UnknownAPI', // Using an invalid RendererAPI for the test
}

expect(async () => await rendererBuilder.createRenderer(rendererBuilderOptions as RendererBuilderOptions)).rejects.toThrow(

Check notice on line 93 in test/unit/renderers/renderer.builder.test.ts

View check run for this annotation

codefactor.io / CodeFactor

test/unit/renderers/renderer.builder.test.ts#L93

Unnecessary 'await'. (no-return-await)
`Unknown RendererAPI for specific mode: ${rendererBuilderOptions.RendererAPI}`,
`Unknown renderAPI for specific mode: ${rendererBuilderOptions.renderAPI}`,
)
})
})

0 comments on commit df401b5

Please sign in to comment.