librewiki / liberty-skin Goto Github PK
View Code? Open in Web Editor NEWLiberty skin
License: GNU General Public License v3.0
Liberty skin
License: GNU General Public License v3.0
미디어위키:Liberty-Navbar는 다음과 같이 적용했습니다.
* icon=comments | display=게시판
** icon=pencil-alt | display=위키방 | link=https://bbs.gaonwiki.com | title=https://bbs.gaonwiki.com
** icon=copyright | display=저작권 처리 게시판 | link=https://bbs.gaonwiki.com/copyrights | title=https://bbs.gaonwiki.com/copyrights
** icon=comments | display=자유게시판 | link=https://bbs.gaonwiki.com/free | title=https://bbs.gaonwiki.com/free
* icon=exclamation | display=버그/기능 개선
** icon=bullhorn | display=이슈 등록 | link=https://bbs.gaonwiki.com/issue | title=https://bbs.gaonwiki.com/issue
** icon=hands-helping | display=기능 구현 도움 | link=https://www.gaonwiki.com/w/가온_위키:기능_구현_불가-누가_해결책을_알려주세요! | title=https://www.gaonwiki.com/w/가온_위키:기능_구현_불가-누가_해결책을_알려주세요!
** icon=bug | display=알려진 문제들 | link=https://www.gaonwiki.com/w/가온_위키/알려진_문제들 | title=https://www.gaonwiki.com/w/가온_위키/알려진_문제들
* icon=gear | display=도구
** icon=wrench | display=특수 문서 목록 | link=특수:특수문서 | title=특수:특수문서
** icon=upload | display=파일 올리기
*** icon=cloud-upload-alt | display=(기존) 업로드 | link=특수:올리기 | title=특수:올리기
*** icon=file-upload | display=(신규) 업로드 마법사 | link=특수:UploadWizard | title=특수:UploadWizard
** icon=flag | display=이슈 트래커 | link=https://bbs.gaonwiki.com/issue/ | title=https://bbs.gaonwiki.com/issue/
** icon=flask | display=가온 위키 베타 | link=https://beta.gaonwiki.com | title=https://beta.gaonwiki.com
* icon=book | display=도움말
** icon=spell-check | display=위키 문법 | link=도움말:위키_문법 | title=도움말:위키_문법
** icon=book | display=설명서 | link=도움말:설명서 | title=도움말:설명서
이후 리버티 스킨 1786539 커밋을 적용하면 첨부한 이미지와 같이 각 드롭다운 메뉴의 마지막 항목이 다음 드롭다운 타이틀로 적용되는 문제가 있습니다.
현재 미디어위키 버전은 1.39.8 사용중이고, a15075a 커밋에서는 문제가 없습니다. 즉, a15075a 이후 커밋 중에 문제가 발생하는 것 같습니다(정확히 어떤 커밋에서 발생하는지는 모르겠습니다).
[환경]
문제가 발생하지 않은 a15075a 커밋을 바탕으로 다음과 같이 수정하면 정상 동작합니다.
protected function parseNavbar() {
global $wgArticlePath;
$headings = [];
$skin = $this->getSkin();
$userName = $skin->getUser()->getName();
$userLang = $skin->getLanguage()->mCode;
$globalData = ContentHandler::getContentText( WikiPage::factory(
Title::newFromText( 'Liberty-Navbar', NS_MEDIAWIKI )
)->getContent( RevisionRecord::RAW ) );
$globalLangData = ContentHandler::getContentText( WikiPage::factory(
Title::newFromText( 'Liberty-Navbar/' . $userLang, NS_MEDIAWIKI )
)->getContent( RevisionRecord::RAW ) );
$userData = ContentHandler::getContentText( WikiPage::factory(
Title::newFromText( $userName . '/Liberty-Navbar', NS_USER )
)->getContent( RevisionRecord::RAW ) );
if ( !empty( $userData ) ) {
$data = $userData;
} elseif ( !empty( $globalLangData ) ) {
$data = $globalLangData;
} else {
$data = $globalData;
}
if ( empty( $data ) ) {
return $headings;
}
$lines = explode( "\n", $data );
$types = [ 'icon', 'display', 'title', 'link', 'access', 'class' ];
foreach ( $lines as $line ) {
$line = rtrim( $line, "\r" );
if ( $line[0] !== '*' ) {
continue;
}
if ( $line[1] !== '*' ) {
// First level menu
$data = [];
$split = explode( '|', $line );
$split[0] = substr( $split[0], 1 );
foreach ( $split as $key => $value ) {
$valueArr = explode( '=', trim( $value ) );
if ( isset( $valueArr[1] ) ) {
$data[$valueArr[0]] = $valueArr[1];
} else {
$data[$types[$key]] = trim( $value );
}
}
$icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;
$group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;
$right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;
if ( isset( $data['display'] ) ) {
$textObj = $skin->msg( $data['display'] );
if ( $textObj->isDisabled() ) {
$text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
} else {
$text = $textObj->text();
}
} else {
$text = '';
}
if ( empty( $icon ) && empty( $text ) ) {
continue;
}
if ( isset( $data['title'] ) ) {
$titleObj = $skin->msg( $data['title'] );
if ( $titleObj->isDisabled() ) {
$title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
} else {
$title = $titleObj->text();
}
} else {
$title = $text;
}
if ( isset( $data['link'] ) ) {
if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
$href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
} else {
$href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
$href = str_replace( '$1', $href, $wgArticlePath );
}
} else {
$href = null;
}
$access = isset( $data['access'] ) ? preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '' : null;
$classes = isset( $data['class'] ) ? array_map( 'trim', explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) ) ) : [];protected function parseNavbar() {
global $wgArticlePath;
$headings = [];
$currentHeading = null;
$skin = $this->getSkin();
$userName = $skin->getUser()->getName();
$userLang = $skin->getLanguage()->mCode;
$globalData = ContentHandler::getContentText( WikiPage::factory(
Title::newFromText( 'Liberty-Navbar', NS_MEDIAWIKI )
)->getContent( RevisionRecord::RAW ) );
$globalLangData = ContentHandler::getContentText( WikiPage::factory(
Title::newFromText( 'Liberty-Navbar/' . $userLang, NS_MEDIAWIKI )
)->getContent( RevisionRecord::RAW ) );
$userData = ContentHandler::getContentText( WikiPage::factory(
Title::newFromText( $userName . '/Liberty-Navbar', NS_USER )
)->getContent( RevisionRecord::RAW ) );
if ( !empty( $userData ) ) {
$data = $userData;
} elseif ( !empty( $globalLangData ) ) {
$data = $globalLangData;
} else {
$data = $globalData;
}
// Well, [[MediaWiki:Liberty-Navbar]] *should* have some content, but
// if it doesn't, bail out here so that we don't trigger E_NOTICEs
// about undefined indexes later on
if ( empty( $data ) ) {
return $headings;
}
$lines = explode( "\n", $data );
$types = [ 'icon', 'display', 'title', 'link', 'access', 'class' ];
foreach ( $lines as $line ) {
$line = rtrim( $line, "\r" );
if ( $line[0] !== '*' ) {
// Line does not start with '*'
continue;
}
if ( $line[1] !== '*' ) {
// First level menu
$data = [];
$split = explode( '|', $line );
$split[0] = substr( $split[0], 1 );
foreach ( $split as $key => $value ) {
$valueArr = explode( '=', trim( $value ) );
if ( isset( $valueArr[1] ) ) {
$data[$valueArr[0]] = $valueArr[1];
} else {
$data[$types[$key]] = trim( $value );
}
}
// Icon
$icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;
// Group
$group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;
// Right
$right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;
// support the usual [[MediaWiki:Sidebar]] syntax of
// ** link target|<some MW: message name> and if the
// thing on the right side of the pipe isn't the name of a MW:
// message, then and _only_ then render it as-is
if ( isset( $data['display'] ) ) {
$textObj = $skin->msg( $data['display'] );
if ( $textObj->isDisabled() ) {
$text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
} else {
$text = $textObj->text();
}
} else {
$text = '';
}
// If icon and text both empty
if ( empty( $icon ) && empty( $text ) ) {
continue;
}
// Title
if ( isset( $data['title'] ) ) {
$titleObj = $skin->msg( $data['title'] );
if ( $titleObj->isDisabled() ) {
$title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
} else {
$title = $titleObj->text();
}
} else {
$title = $text;
}
// Link href
if ( isset( $data['link'] ) ) {
// @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
$href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
} else {
$href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
$href = str_replace( '$1', $href, $wgArticlePath );
}
} else {
$href = null;
}
if ( isset( $data['access'] ) ) {
// Access
$access = preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '';
} else {
$access = null;
}
if ( isset( $data['class'] ) ) {
// Classes
$classes = explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) );
foreach ( $classes as $key => $value ) {
$classes[$key] = trim( $value );
}
} else {
$classes = [];
}
$item = [
'access' => $access,
'classes' => $classes,
'href' => $href,
'icon' => $icon,
'text' => $text,
'title' => $title,
'group' => $group,
'right' => $right
];
$level2Children = &$item['children'];
$headings[] = $item;
continue;
}
if ( $line[2] !== '*' ) {
// Second level menu
$data = [];
$split = explode( '|', $line );
$split[0] = substr( $split[0], 2 );
foreach ( $split as $key => $value ) {
$valueArr = explode( '=', trim( $value ) );
if ( isset( $valueArr[1] ) ) {
$data[$valueArr[0]] = $valueArr[1];
} else {
$data[$types[$key]] = trim( $value );
}
}
// Icon
$icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;
// Group
$group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;
// Right
$right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;
// support the usual [[MediaWiki:Sidebar]] syntax of
// ** link target|<some MW: message name> and if the
// thing on the right side of the pipe isn't the name of a MW:
// message, then and _only_ then render it as-is
if ( isset( $data['display'] ) ) {
$textObj = $skin->msg( $data['display'] );
if ( $textObj->isDisabled() ) {
$text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
} else {
$text = $textObj->text();
}
} else {
$text = '';
}
// If icon and text both empty
if ( empty( $icon ) && empty( $text ) ) {
continue;
}
// Title
if ( isset( $data['title'] ) ) {
$titleObj = $skin->msg( $data['title'] );
if ( $titleObj->isDisabled() ) {
$title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
} else {
$title = $titleObj->text();
}
} else {
$title = $text;
}
if ( isset( $data['link'] ) ) {
// Link href
// @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
$href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
} else {
$href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
$href = str_replace( '$1', $href, $wgArticlePath );
}
}
if ( isset( $data['access'] ) ) {
// Access
$access = preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '';
} else {
$access = null;
}
if ( isset( $data['class'] ) ) {
// Classes
$classes = explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) );
foreach ( $classes as $key => $value ) {
$classes[$key] = trim( $value );
}
} else {
$classes = [];
}
$item = [
'access' => $access,
'classes' => $classes,
'href' => $href,
'icon' => $icon,
'text' => $text,
'title' => $title,
'group' => $group,
'right' => $right
];
$level3Children = &$item['children'];
$level2Children[] = $item;
continue;
}
if ( $line[3] !== '*' ) {
// Third level menu
$data = [];
$split = explode( '|', $line );
$split[0] = substr( $split[0], 3 );
foreach ( $split as $key => $value ) {
$valueArr = explode( '=', trim( $value ) );
if ( isset( $valueArr[1] ) ) {
$data[$valueArr[0]] = $valueArr[1];
} else {
$data[$types[$key]] = trim( $value );
}
}
// Icon
$icon = isset( $data['icon'] ) ? htmlentities( $data['icon'], ENT_QUOTES, 'UTF-8' ) : null;
// Group
$group = isset( $data['group'] ) ? htmlentities( $data['group'], ENT_QUOTES, 'UTF-8' ) : null;
// Right
$right = isset( $data['right'] ) ? htmlentities( $data['right'], ENT_QUOTES, 'UTF-8' ) : null;
// support the usual [[MediaWiki:Sidebar]] syntax of
// ** link target|<some MW: message name> and if the
// thing on the right side of the pipe isn't the name of a MW:
// message, then and _only_ then render it as-is
if ( isset( $data['display'] ) ) {
$textObj = $skin->msg( $data['display'] );
if ( $textObj->isDisabled() ) {
$text = htmlentities( $data['display'], ENT_QUOTES, 'UTF-8' );
} else {
$text = $textObj->text();
}
} else {
$text = '';
}
// If icon and text both empty
if ( empty( $icon ) && empty( $text ) ) {
continue;
}
// Title
if ( isset( $data['title'] ) ) {
$titleObj = $skin->msg( $data['title'] );
if ( $titleObj->isDisabled() ) {
$title = htmlentities( $data['title'], ENT_QUOTES, 'UTF-8' );
} else {
$title = $titleObj->text();
}
} else {
$title = $text;
}
// Link href
// @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
$href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
} else {
$href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
$href = str_replace( '$1', $href, $wgArticlePath );
}
// Access
if ( isset( $data['access'] ) ) {
$access = preg_match( '/^([0-9a-z]{1})$/i', $data['access'] ) ? $data['access'] : '';
} else {
$access = null;
}
if ( isset( $data['class'] ) ) {
// Classes
$classes = explode( ',', htmlentities( $data['class'], ENT_QUOTES, 'UTF-8' ) );
foreach ( $classes as $key => $value ) {
$classes[$key] = trim( $value );
}
} else {
$classes = [];
}
$item = [
'access' => $access,
'classes' => $classes,
'href' => $href,
'icon' => $icon,
'text' => $text,
'title' => $title,
'group' => $group,
'right' => $right
];
$level3Children[] = $item;
continue;
} else {
// Not supported
continue;
}
}
return $headings;
}
다만 a15075a 커밋 이후의 몇개의 수정사항이 반영되어 있지 않을 수 있어서 이 부분은 확인해 주시면 감사하겠습니다.
When pushing translations to this repository, we are currently facing this issue:
The command "cd 'mwgithub/librewiki/liberty-skin'; git add .; if ! git diff
--cached --quiet; then git commit -m 'Localisation updates from https://tr
anslatewiki.net.'; git rebase 'origin/master' && git push origin 'master';
fi" failed.
Exit Code: 1(General error)
Working directory: /scratch/exports
Output:
================
[master 1b05bbf] Localisation updates from https://translatewiki.net.
1 file changed, 11 insertions(+)
Current branch master is up to date.
Error Output:
================
remote: error: GH006: Protected branch update failed for refs/heads/master.
remote: error: 2 of 2 required status checks are expected.
To github.com:librewiki/liberty-skin.git
! [remote rejected] master -> master (protected branch hook declined)
error: failed to push some refs to 'github.com:librewiki/liberty-skin.git'
Please investigate a way to resume translations updates by @translatewiki.
The i18n messages liberty-btn-close
and liberty-btn-save-changes
got removed from the English i18n JSON file in aa86154 by @revi, but to this day they're seemingly "used" in the div.modal-footer
element of the login dialog (which is only shown to anons), but that element is always (?) visually hidden via CSS...
As a side note, it might be worthwhile to look into the OOJsUIAjaxLogin extension and see if using that extension would make more sense than to have the skin provide such a feature. (Granted, the extension is formally unmaintained but it worked just fine the last time I tried and it's not like it's the most complex piece of software out there, so it probably won't need much maintenance going forward.)
Seen in MediaWiki 1.41. Fatal on page load.
I've stopped featuring the skin on https://skins.wmcloud.org/ while this is broken.
Currently a bunch of external assets (FontAwesome from FontAwesome.com, other fonts mainly/only (?) for supporting Korean, share-api-polyfill from unpkg.com) are loaded unconditionally in SkinLiberty#setupCss
. While this may work just as intended from a functional point of view and be totally acceptable for a lower-traffic MediaWiki instance, this would make Liberty a no-go for more privacy-conscious setups; for example, the Wikimedia Foundation's sites.*
Ideally there'd be a configuration global that could and should be explicitly enabled by the end-user (sysadmin) in the wiki's LocalSettings.php
to enable loading assets from external servers.
Google AdSense JS is a notable exception to that since it cannot be self-hosted; but the scenario I want to see is that with ads turned off, Liberty makes no connections to external servers.
After installation on mw1.27.4 and php 7 (xampp) i get :
Notice: Undefined index: notifications-alert in L:\xammp7025\htdocs\mw1274\skins\liberty\LibertyTemplate.php on line 638 .... Notice: Undefined index: notifications-message in L:\xammp7025\htdocs\mw1274\skins\liberty\LibertyTemplate.php on line 639
(I was at https://issue.librewiki.net/search/query/ryjJBqxqTfRS/#R - but could not publish an issue...)
The alias ResourceLoaderSkinModule was dropped in favor of MediaWiki\ResourceLoader\SkinModule in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/994854 which leads to fatals in this skin in MediaWiki 1.41.
See: https://phabricator.wikimedia.org/T356563 for more information.
Seen in MediaWiki 1.41. Fatal on page load.
I've stopped featuring the skin on https://skins.wmcloud.org/ while this is broken.
Hello, thank you very much for creating the Liberty skin.
Currently, there is an issue where the site is not hyperlinked properly due to an HTML
parsing error when '=' and '&' are included in the HTML.
For instance, using "https://papago.naver.net/website?locale=ko&source=ko&target=en&url=https://xxx"
creates parsing errors at the "=", and due to incorrect usages of the "htmlentities(): function,
the result is "https://papago.naver.net/website?".
Since I am not familiar with PHP, I applied a simple patch as follows, but I am concerned about any potential security vulnerabilities.
// LibertyTemplate.php
foreach ( $split as $key => $value ) {
$valueArr = explode( '=', trim( $value ) );
if ( isset( $valueArr[1] ) ) {
$newValue = implode( '=', array_slice($valueArr, 1)); // <- Temporary fix for concat hyperlink with "=".
$data[$valueArr[0]] = $newValue;
} else {
$data[$types[$key]] = trim( $value );
}
}
// LibertyTemplate.php
if ( isset( $data['link'] ) ) {
// @todo CHECKME: Should this use wfUrlProtocols() or somesuch instead?
if ( preg_match( '/^((?:(?:http(?:s)?)?:)?\/\/(?:.{4,}))$/i', $data['link'] ) ) {
$href = htmlentities( $data['link'], ENT_QUOTES, 'UTF-8' );
$href = $data['link']; // <- Temporary fix for ignoring htmlentitites produce hyperlink with &.
} else {
$href = str_replace( '%3A', ':', urlencode( $data['link'] ) );
$href = str_replace( '$1', $href, $wgArticlePath );
}
} else {
$href = null;
}
If you could confirm, I will apply the related changes and submit a pull request.
Thank you.
Get this:
PHP message: PHP Deprecated: Use of ContentHandler::getContentText was deprecated in MediaWiki 1.37. [Called from LibertyTemplate::parseNavbar in skins/liberty-skin/LibertyTemplate.php:879]
I downloaded and applied the Levi's skin, but I don't see the Libre Wiki logo, and it doesn't show up even if I replace it with another picture. How do I fix it? Also, I'm curious about how I can change the color of the top bar of Wiki.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.