Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new Wikimedia mobile end-point support/render #1903

Merged
merged 59 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5d6b68c
Implement mobile renderer (partial impl)
VadimKovalenkoSNF Sep 11, 2023
09aa838
Setup renderers for main page and articles
VadimKovalenkoSNF Sep 13, 2023
293caae
Fix regressions in saveArticles
VadimKovalenkoSNF Sep 13, 2023
fb6f78c
Pass hasWikimediaMobileRestApi to saveArticles as argument to prevent…
VadimKovalenkoSNF Sep 13, 2023
0b9b688
Add treatSections method for mobile render (partial impl)
VadimKovalenkoSNF Sep 14, 2023
3c5087d
Pass explicit output of mobile-html to the zim creator
VadimKovalenkoSNF Sep 15, 2023
f2b5c08
Apply mobile css and js in mobile renderer
VadimKovalenkoSNF Sep 18, 2023
96fb0f5
Adapt reference links and minor treatments
VadimKovalenkoSNF Sep 19, 2023
c45d285
Refactor tests (partial impl)
VadimKovalenkoSNF Sep 22, 2023
daa7d13
Update naming for mw api across mwoffliner
VadimKovalenkoSNF Sep 22, 2023
37a37c5
Split article treatment flow for mobile render to represent images in…
VadimKovalenkoSNF Sep 25, 2023
218e532
Apply css and js module downoload for WikimediaMobile render
VadimKovalenkoSNF Sep 26, 2023
baa55ae
Refactor modules for mobile renderer
VadimKovalenkoSNF Sep 27, 2023
d89bb92
Add PCS override script to enable links for mobile render
VadimKovalenkoSNF Sep 28, 2023
5a90865
Enable regular behaviour of links for mobile render
VadimKovalenkoSNF Sep 28, 2023
2b04559
Merge mobile and desktop modules output, replace article templating t…
VadimKovalenkoSNF Oct 3, 2023
83520c6
Optimize static files saving
VadimKovalenkoSNF Oct 3, 2023
9714818
Update naming for mobile and desktop api across application
VadimKovalenkoSNF Oct 3, 2023
6dc7d7a
Change PCS naming in favor of Wm Mobile
VadimKovalenkoSNF Oct 4, 2023
a5cbf51
Add tests for the format params while using WikimediaMobile render
VadimKovalenkoSNF Oct 4, 2023
b44bf8b
Override image size for WikimediaMobile
VadimKovalenkoSNF Oct 4, 2023
c96a237
Update placeholder in the test for nopdf param
VadimKovalenkoSNF Oct 4, 2023
7ffc1e2
Force article body to be centered for mobile render
VadimKovalenkoSNF Oct 4, 2023
e5d82f8
Implement mobile renderer (partial impl)
VadimKovalenkoSNF Sep 11, 2023
6b9c734
Setup renderers for main page and articles
VadimKovalenkoSNF Sep 13, 2023
2ba20e0
Fix regressions in saveArticles
VadimKovalenkoSNF Sep 13, 2023
10e82bb
Pass hasWikimediaMobileRestApi to saveArticles as argument to prevent…
VadimKovalenkoSNF Sep 13, 2023
9829d7c
Add treatSections method for mobile render (partial impl)
VadimKovalenkoSNF Sep 14, 2023
96f38ab
Pass explicit output of mobile-html to the zim creator
VadimKovalenkoSNF Sep 15, 2023
d92008c
Apply mobile css and js in mobile renderer
VadimKovalenkoSNF Sep 18, 2023
19f4acc
Adapt reference links and minor treatments
VadimKovalenkoSNF Sep 19, 2023
3dec607
Refactor tests (partial impl)
VadimKovalenkoSNF Sep 22, 2023
7562e4e
Update naming for mw api across mwoffliner
VadimKovalenkoSNF Sep 22, 2023
33db5a4
Split article treatment flow for mobile render to represent images in…
VadimKovalenkoSNF Sep 25, 2023
50ebfa1
Apply css and js module downoload for WikimediaMobile render
VadimKovalenkoSNF Sep 26, 2023
8824f8a
Refactor modules for mobile renderer
VadimKovalenkoSNF Sep 27, 2023
0ab3c4a
Add PCS override script to enable links for mobile render
VadimKovalenkoSNF Sep 28, 2023
40931ff
Enable regular behaviour of links for mobile render
VadimKovalenkoSNF Sep 28, 2023
1b4f12d
Merge mobile and desktop modules output, replace article templating t…
VadimKovalenkoSNF Oct 3, 2023
b315fc3
Optimize static files saving
VadimKovalenkoSNF Oct 3, 2023
5320b56
Update naming for mobile and desktop api across application
VadimKovalenkoSNF Oct 3, 2023
07809d4
Change PCS naming in favor of Wm Mobile
VadimKovalenkoSNF Oct 4, 2023
8867024
Add tests for the format params while using WikimediaMobile render
VadimKovalenkoSNF Oct 4, 2023
defd234
Override image size for WikimediaMobile
VadimKovalenkoSNF Oct 4, 2023
ecf7944
Update placeholder in the test for nopdf param
VadimKovalenkoSNF Oct 4, 2023
113ff0f
Force article body to be centered for mobile render
VadimKovalenkoSNF Oct 4, 2023
26ffb22
Merge branch '1664-mobile-html-renderer' of https://github.com/openzi…
VadimKovalenkoSNF Oct 5, 2023
546cb7e
Refactor modules resolving logic for mobile renderer
VadimKovalenkoSNF Oct 5, 2023
d3027e1
Create separate page templates for mobile and desktop
VadimKovalenkoSNF Oct 5, 2023
b1e7737
Add error handling for empty data in WikimediaMobile render
VadimKovalenkoSNF Oct 6, 2023
3b53982
Decrease image size in mobile render, secure tests
VadimKovalenkoSNF Oct 6, 2023
79d5acf
Don't save jsConfigVars for mobile render
VadimKovalenkoSNF Oct 6, 2023
5ea91e8
Throw an error if data no present for WikimediaDesktop render
VadimKovalenkoSNF Oct 6, 2023
99a4eda
Update image optimization for mobile render
VadimKovalenkoSNF Oct 9, 2023
17a50c0
Update naming and minor refactoring of resizeMobileImages() method
VadimKovalenkoSNF Oct 9, 2023
dbc3116
Update attributes for lazy loaded images of mobile render
VadimKovalenkoSNF Oct 9, 2023
61d7768
Move static files list preparation into renders (partial impl)
VadimKovalenkoSNF Oct 15, 2023
bdd0847
Update en.e2e.test.ts file to check zim integrity
VadimKovalenkoSNF Oct 16, 2023
d412ee4
Move common static files handling to abstract render
VadimKovalenkoSNF Oct 16, 2023
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
31 changes: 0 additions & 31 deletions res/templates/page.html

This file was deleted.

24 changes: 24 additions & 0 deletions res/templates/pageWikimediaDesktop.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html class='client-js'>
<head>
<meta charset="UTF-8"/>
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> __ARTICLE_CANONICAL_LINK__ __ARTICLE_CSS_LIST__
__CSS_LINKS__ __JS_SCRIPTS__
</head>
<body class="mediawiki mw-hide-empty-elt ns-0 ns-subject stable skin-minerva action-view animations">
<div id="mw-mf-viewport" class="feature-header-v2">
<div id="mw-mf-page-center">
<div id="content" class="mw-body">
<a id="top"></a>
<div id="bodyContent" class="content mw-parser-output">
<h1 id="titleHeading" style="background-color: white; margin: 0;"></h1>
<div id="mw-content-text"></div>
</div>
</div>
</div>
</div>
__ARTICLE_CONFIGVARS_LIST__
__ARTICLE_JS_LIST__
</body>
</html>
24 changes: 24 additions & 0 deletions res/templates/pageWikimediaMobile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html class='client-js'>
<head>
<meta charset="UTF-8"/>
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> __ARTICLE_CANONICAL_LINK__ __ARTICLE_CSS_LIST__
__CSS_LINKS__ __ARTICLE_JS_LIST__
</head>
<body class="mediawiki mw-hide-empty-elt ns-0 ns-subject stable skin-minerva action-view animations">
<div id="mw-mf-viewport" class="feature-header-v2">
<div id="mw-mf-page-center">
<div id="content" class="mw-body">
<a id="top"></a>
<div id="bodyContent" class="content mw-parser-output">
<h1 id="titleHeading" style="background-color: white; margin: 0;"></h1>
<div id="mw-content-text"></div>
</div>
</div>
</div>
</div>
__ARTICLE_CONFIGVARS_LIST__
__JS_SCRIPTS__
</body>
</html>
15 changes: 15 additions & 0 deletions res/wm_mobile_override_script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function importScript() { return 1 } // this is to avoid the error from site.js

window.onload = function () {
// Check if there is a Wikimedia mobile output page
if (document.querySelector('#pcs')) {
const supElements = document.querySelectorAll('sup');
const linkElements = document.querySelectorAll('a');
const disabledElems = Array.from(supElements).concat(Array.from(linkElements))
disabledElems.forEach((elem) => {
elem.addEventListener('click', (event) => {
event.stopPropagation();
}, true);
});
}
}
20 changes: 20 additions & 0 deletions res/wm_mobile_override_style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
body {
margin: 0 auto !important;
}
p#pcs-edit-section-add-title-description {
display: none !important;
}
span.noviewer {
display: none !important;
}
.reference-link::after {
content: none !important;
}
.mw-body h3, .mw-body h2 {
width: auto;
}

.thumbinner img.pcs-widen-image-override {
width: auto !important;
max-width: 100% !important;
}
43 changes: 37 additions & 6 deletions src/Downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class Downloader {
public arrayBufferRequestOptions: AxiosRequestConfig
public jsonRequestOptions: AxiosRequestConfig
public streamRequestOptions: AxiosRequestConfig
public wikimediaMobileJsDependenciesList: string[] = []
public wikimediaMobileStyleDependenciesList: string[] = []

private readonly uaString: string
private activeRequests = 0
Expand Down Expand Up @@ -171,21 +173,23 @@ class Downloader {
if (!forceRender) {
//* Objects order in array matters!
this.baseUrl = basicURLDirector.buildDownloaderBaseUrl([
{ condition: await MediaWiki.hasWikimediaDesktopRestApi(), value: MediaWiki.desktopRestApiUrl.href },
{ condition: await MediaWiki.hasWikimediaMobileApi(), value: MediaWiki.WikimediaMobileApiUrl.href },
{ condition: await MediaWiki.hasWikimediaDesktopApi(), value: MediaWiki.WikimediaDesktopApiUrl.href },
{ condition: await MediaWiki.hasVisualEditorApi(), value: MediaWiki.visualEditorApiUrl.href },
])

//* Objects order in array matters!
this.baseUrlForMainPage = basicURLDirector.buildDownloaderBaseUrl([
{ condition: await MediaWiki.hasWikimediaDesktopRestApi(), value: MediaWiki.desktopRestApiUrl.href },
{ condition: await MediaWiki.hasWikimediaDesktopApi(), value: MediaWiki.WikimediaDesktopApiUrl.href },
{ condition: await MediaWiki.hasVisualEditorApi(), value: MediaWiki.visualEditorApiUrl.href },
{ condition: await MediaWiki.hasWikimediaMobileApi(), value: MediaWiki.WikimediaMobileApiUrl.href },
])
} else {
switch (forceRender) {
case 'WikimediaDesktop':
if (MediaWiki.hasWikimediaDesktopRestApi()) {
this.baseUrl = MediaWiki.desktopRestApiUrl.href
this.baseUrlForMainPage = MediaWiki.desktopRestApiUrl.href
if (MediaWiki.hasWikimediaDesktopApi()) {
this.baseUrl = MediaWiki.WikimediaDesktopApiUrl.href
this.baseUrlForMainPage = MediaWiki.WikimediaDesktopApiUrl.href
break
}
break
Expand All @@ -196,6 +200,13 @@ class Downloader {
break
}
break
case 'WikimediaMobile':
if (MediaWiki.hasWikimediaMobileApi()) {
this.baseUrl = MediaWiki.WikimediaMobileApiUrl.href
this.baseUrlForMainPage = MediaWiki.WikimediaMobileApiUrl.href
break
}
break
default:
throw new Error('Unable to find specific API end-point to retrieve article HTML')
}
Expand Down Expand Up @@ -685,7 +696,27 @@ class Downloader {

jsConfigVars = jsConfigVars.replace('nosuchaction', 'view') // to replace the wgAction config that is set to 'nosuchaction' from api but should be 'view'

return { jsConfigVars, jsDependenciesList, styleDependenciesList }
kelson42 marked this conversation as resolved.
Show resolved Hide resolved
// Download mobile page dependencies only once
if ((await MediaWiki.hasWikimediaMobileApi()) && this.wikimediaMobileJsDependenciesList.length === 0 && this.wikimediaMobileStyleDependenciesList.length === 0) {
try {
// TODO: An arbitrary title can be placed since all Wikimedia wikis have the same mobile offline resources
const mobileModulesData = await this.getJSON<any>(`${MediaWiki.mobileModulePath}Test`)
mobileModulesData.forEach((module: string) => {
if (module.includes('javascript')) {
this.wikimediaMobileJsDependenciesList.push(module)
} else if (module.includes('css')) {
this.wikimediaMobileStyleDependenciesList.push(module)
}
})
} catch (err) {
throw new Error(`Error getting mobile modules ${err.message}`)
}
}
return {
jsConfigVars,
jsDependenciesList: jsDependenciesList.concat(this.wikimediaMobileJsDependenciesList),
styleDependenciesList: styleDependenciesList.concat(this.wikimediaMobileStyleDependenciesList),
}
}

// Solution to handle aws js sdk v3 from https://github.com/aws/aws-sdk-js-v3/issues/1877
Expand Down
66 changes: 42 additions & 24 deletions src/MediaWiki.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import semver from 'semver'
import basicURLDirector from './util/builders/url/basic.director.js'
import BaseURLDirector from './util/builders/url/base.director.js'
import ApiURLDirector from './util/builders/url/api.director.js'
import DesktopURLDirector from './util/builders/url/desktop.director.js'
import WikimediaDesktopURLDirector from './util/builders/url/desktop.director.js'
import WikimediaMobileURLDirector from './util/builders/url/mobile.director.js'
import VisualEditorURLDirector from './util/builders/url/visual-editor.director.js'
import { checkApiAvailability } from './util/mw-api.js'
import { BLACKLISTED_NS } from './util/const.js'
Expand Down Expand Up @@ -43,23 +44,27 @@ class MediaWiki {
public queryOpts: QueryOpts

#wikiPath: string
#restApiPath: string
#apiPath: string
#username: string
#password: string
#apiPath: string
#apiActionPath: string
#domain: string
private apiUrlDirector: ApiURLDirector
private wikimediaDesktopUrlDirector: DesktopURLDirector
private visualEditorURLDirector: VisualEditorURLDirector
private wikimediaDesktopUrlDirector: WikimediaDesktopURLDirector
private wikimediaMobileUrlDirector: WikimediaMobileURLDirector
private VisualEditorURLDirector: VisualEditorURLDirector

public visualEditorApiUrl: URL
public apiUrl: URL
public modulePath: string // only for reading
public _modulePathOpt: string // only for whiting to generate modulePath
public mobileModulePath: string
public webUrl: URL
public desktopRestApiUrl: URL
public WikimediaDesktopApiUrl: URL
public WikimediaMobileApiUrl: URL

#hasWikimediaDesktopRestApi: boolean | null
#hasWikimediaDesktopApi: boolean | null
#hasWikimediaMobileApi: boolean | null
#hasVisualEditorApi: boolean | null
#hasCoordinates: boolean | null

Expand All @@ -71,12 +76,12 @@ class MediaWiki {
this.#password = value
}

set apiPath(value: string) {
this.#apiPath = value
set apiActionPath(value: string) {
this.#apiActionPath = value
}

set restApiPath(value: string) {
this.#restApiPath = value
set apiPath(value: string) {
this.#apiPath = value
}

set domain(value: string) {
Expand Down Expand Up @@ -105,7 +110,7 @@ class MediaWiki {
this.namespaces = {}
this.namespacesToMirror = []

this.#apiPath = 'w/api.php'
this.#apiActionPath = 'w/api.php'
this.#wikiPath = 'wiki/'
this.apiCheckArticleId = 'MediaWiki:Sidebar'

Expand All @@ -119,7 +124,8 @@ class MediaWiki {
formatversion: '2',
}

this.#hasWikimediaDesktopRestApi = null
this.#hasWikimediaDesktopApi = null
this.#hasWikimediaMobileApi = null
this.#hasVisualEditorApi = null
this.#hasCoordinates = null
}
Expand All @@ -128,17 +134,25 @@ class MediaWiki {
this.initializeMediaWikiDefaults()
}

public async hasWikimediaDesktopRestApi(): Promise<boolean> {
if (this.#hasWikimediaDesktopRestApi === null) {
this.#hasWikimediaDesktopRestApi = await checkApiAvailability(this.wikimediaDesktopUrlDirector.buildArticleURL(this.apiCheckArticleId))
return this.#hasWikimediaDesktopRestApi
public async hasWikimediaDesktopApi(): Promise<boolean> {
if (this.#hasWikimediaDesktopApi === null) {
this.#hasWikimediaDesktopApi = await checkApiAvailability(this.wikimediaDesktopUrlDirector.buildArticleURL(this.apiCheckArticleId))
return this.#hasWikimediaDesktopApi
}
return this.#hasWikimediaDesktopApi
}

public async hasWikimediaMobileApi(): Promise<boolean> {
if (this.#hasWikimediaMobileApi === null) {
this.#hasWikimediaMobileApi = await checkApiAvailability(this.wikimediaMobileUrlDirector.buildArticleURL(this.apiCheckArticleId))
return this.#hasWikimediaMobileApi
}
return this.#hasWikimediaDesktopRestApi
return this.#hasWikimediaMobileApi
}

public async hasVisualEditorApi(): Promise<boolean> {
if (this.#hasVisualEditorApi === null) {
this.#hasVisualEditorApi = await checkApiAvailability(this.visualEditorURLDirector.buildArticleURL(this.apiCheckArticleId))
this.#hasVisualEditorApi = await checkApiAvailability(this.VisualEditorURLDirector.buildArticleURL(this.apiCheckArticleId))
return this.#hasVisualEditorApi
}
return this.#hasVisualEditorApi
Expand Down Expand Up @@ -166,13 +180,16 @@ class MediaWiki {
private initMWApis() {
const baseUrlDirector = new BaseURLDirector(this.baseUrl.href)
this.webUrl = baseUrlDirector.buildURL(this.#wikiPath)
this.apiUrl = baseUrlDirector.buildURL(this.#apiPath)
this.apiUrl = baseUrlDirector.buildURL(this.#apiActionPath)
this.apiUrlDirector = new ApiURLDirector(this.apiUrl.href)
this.visualEditorApiUrl = this.apiUrlDirector.buildVisualEditorURL()
this.desktopRestApiUrl = baseUrlDirector.buildDesktopRestApiURL(this.#restApiPath)
this.WikimediaDesktopApiUrl = baseUrlDirector.buildWikimediaDesktopApiUrl(this.#apiPath)
this.WikimediaMobileApiUrl = baseUrlDirector.buildWikimediaMobileApiUrl(this.#apiPath)
this.modulePath = baseUrlDirector.buildModuleURL(this._modulePathOpt)
this.wikimediaDesktopUrlDirector = new DesktopURLDirector(this.desktopRestApiUrl.href)
this.visualEditorURLDirector = new VisualEditorURLDirector(this.visualEditorApiUrl.href)
this.mobileModulePath = baseUrlDirector.buildMobileModuleURL()
this.wikimediaDesktopUrlDirector = new WikimediaDesktopURLDirector(this.WikimediaDesktopApiUrl.href)
this.wikimediaMobileUrlDirector = new WikimediaMobileURLDirector(this.WikimediaMobileApiUrl.href)
this.VisualEditorURLDirector = new VisualEditorURLDirector(this.visualEditorApiUrl.href)
}

public async login(downloader: Downloader) {
Expand Down Expand Up @@ -398,10 +415,11 @@ class MediaWiki {
webUrl: this.webUrl.href,
apiUrl: this.apiUrl.href,
modulePath: this.modulePath,
mobileModulePath: this.mobileModulePath,
webUrlPath: this.webUrl.pathname,
wikiPath: this.#wikiPath,
baseUrl: this.baseUrl.href,
apiPath: this.#apiPath,
apiActionPath: this.#apiActionPath,
domain: this.#domain,

textDir: textDir as TextDirection,
Expand Down
23 changes: 7 additions & 16 deletions src/Templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import swig from 'swig-templates'
import pathParser from 'path'
import { config } from './config.js'
import { readFileSync } from 'fs'
import { genHeaderCSSLink, genHeaderScript } from './util/index.js'
import * as path from 'path'
import { fileURLToPath } from 'url'

Expand All @@ -22,21 +21,12 @@ const categoriesTemplate = swig.compile(readTemplate(config.output.templates.cat
const subCategoriesTemplate = swig.compile(readTemplate(config.output.templates.subCategories))
const subPagesTemplate = swig.compile(readTemplate(config.output.templates.subPages))

const htmlTemplateCode = (articleId: string) => {
const cssLinks = config.output.cssResources.reduce((buf, css) => {
return buf + genHeaderCSSLink(config, css, articleId)
}, '')

const jsScripts = config.output.jsResources.reduce((buf, js) => {
return (
buf +
(js === 'script'
? genHeaderScript(config, js, articleId, '', `data-article-id="${articleId.replace(/"/g, '\\\\"')}" id="script-js"`)
: genHeaderScript(config, js, articleId))
)
}, '')
const htmlWikimediaMobileTemplateCode = () => {
return readTemplate(config.output.templates.pageWikimediaMobile)
}

return readTemplate(config.output.templates.page).replace('__CSS_LINKS__', cssLinks).replace('__JS_SCRIPTS__', jsScripts)
const htmlWikimediaDesktopTemplateCode = () => {
return readTemplate(config.output.templates.pageWikimediaDesktop)
}

const articleListHomeTemplate = readTemplate(config.output.templates.articleListHomeTemplate)
Expand All @@ -46,7 +36,8 @@ export {
leadSectionTemplate,
sectionTemplate,
subSectionTemplate,
htmlTemplateCode,
htmlWikimediaMobileTemplateCode,
htmlWikimediaDesktopTemplateCode,
articleListHomeTemplate,
categoriesTemplate,
subCategoriesTemplate,
Expand Down
Loading
Loading