From 767980a0578ab31e392d4ef0925543c6cc63a69d Mon Sep 17 00:00:00 2001 From: speedie Date: Mon, 12 Jun 2023 01:53:21 +0200 Subject: [PATCH] Remove the speedwm wiki and instead redirect to the git repository --- LICENSE | 21 - README.md | 60 - config.php | 216 ---- icons/close.svg | 12 - icons/delete-dark.svg | 8 - icons/delete.svg | 8 - icons/edit-dark.svg | 8 - icons/edit.svg | 8 - icons/format-text-bold.svg | 8 - icons/format-text-code.svg | 8 - icons/format-text-italic.svg | 13 - icons/home.svg | 8 - icons/internet.png | Bin 886 -> 0 bytes icons/link-dark.svg | 10 - icons/link.svg | 10 - icons/list.svg | 8 - icons/new.svg | 13 - icons/rename-dark.svg | 17 - icons/rename.svg | 17 - icons/upload.svg | 8 - images/.gitignore | 4 - index.css | 410 ------- index.html | 14 + index.php | 938 ---------------- locales/de.php | 65 -- locales/en.php | 32 - locales/ja.php | 32 - locales/sample.php | 32 - md/Markdown.inc.php | 10 - md/Markdown.php | 1909 -------------------------------- md/MarkdownExtra.inc.php | 11 - md/MarkdownExtra.php | 1895 ------------------------------- md/MarkdownInterface.inc.php | 9 - md/MarkdownInterface.php | 38 - pages/Centered status bar.md | 22 - pages/Client rules.md | 130 --- pages/Configuring the bar.md | 178 --- pages/Getting Started.md | 183 --- pages/Home.md | 27 - pages/Keybinds.md | 167 --- pages/Managing changes.md | 14 - pages/Restoring the dwm bar.md | 167 --- pages/Rounded corners.md | 90 -- pages/Using the wiki.md | 24 - pages/Wayland support.md | 2 - pages/Where do I go?.md | 24 - pages/_sidebar.md | 12 - run.sh | 28 - test.sh | 3 - tests/travis-ci-apache.conf | 21 - 50 files changed, 14 insertions(+), 6938 deletions(-) delete mode 100755 LICENSE delete mode 100755 README.md delete mode 100755 config.php delete mode 100755 icons/close.svg delete mode 100755 icons/delete-dark.svg delete mode 100755 icons/delete.svg delete mode 100755 icons/edit-dark.svg delete mode 100755 icons/edit.svg delete mode 100755 icons/format-text-bold.svg delete mode 100755 icons/format-text-code.svg delete mode 100755 icons/format-text-italic.svg delete mode 100755 icons/home.svg delete mode 100755 icons/internet.png delete mode 100755 icons/link-dark.svg delete mode 100755 icons/link.svg delete mode 100755 icons/list.svg delete mode 100755 icons/new.svg delete mode 100755 icons/rename-dark.svg delete mode 100755 icons/rename.svg delete mode 100755 icons/upload.svg delete mode 100755 images/.gitignore delete mode 100755 index.css create mode 100644 index.html delete mode 100755 index.php delete mode 100755 locales/de.php delete mode 100755 locales/en.php delete mode 100755 locales/ja.php delete mode 100755 locales/sample.php delete mode 100755 md/Markdown.inc.php delete mode 100755 md/Markdown.php delete mode 100755 md/MarkdownExtra.inc.php delete mode 100755 md/MarkdownExtra.php delete mode 100755 md/MarkdownInterface.inc.php delete mode 100755 md/MarkdownInterface.php delete mode 100644 pages/Centered status bar.md delete mode 100644 pages/Client rules.md delete mode 100644 pages/Configuring the bar.md delete mode 100755 pages/Getting Started.md delete mode 100755 pages/Home.md delete mode 100644 pages/Keybinds.md delete mode 100755 pages/Managing changes.md delete mode 100644 pages/Restoring the dwm bar.md delete mode 100755 pages/Rounded corners.md delete mode 100644 pages/Using the wiki.md delete mode 100755 pages/Wayland support.md delete mode 100644 pages/Where do I go?.md delete mode 100755 pages/_sidebar.md delete mode 100755 run.sh delete mode 100755 test.sh delete mode 100755 tests/travis-ci-apache.conf diff --git a/LICENSE b/LICENSE deleted file mode 100755 index f7bd968..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2013 Steven Frank - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100755 index 37d3756..0000000 --- a/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# W2 wiki - -W2 wiki is a web-based, wiki-like notepad that you can host yourself. - - -## Notable features: - -- Elegant text markup: - - Uses [Markdown Syntax](https://github.com/codeling/w2wiki/blob/master/pages/MarkdownSyntax.md). - - It supports double-brackets [[like this]] to link to another page in the wiki by title - - It supports double-braces {{like this}} to link to an uploaded image -- Minimalistic but functional interface: - - Fits to screen nicely when viewed on iPhone, with custom icon for adding to home screen - - HTML5 compliant output -- Title & content search -- Filesystem storage (no database required) in plain Markdown text files. -- Rudimentary git integration to commit & push each page edit -- Localization support (currently en/ja translations available) -- Image uploading support -- Optionally password-protected -- Unlike cloud / hosted solutions, you retain control of your data -- Written in PHP for portability and hackability -- Extremely compact (only a few .php files and a .css file) - - -## Installation & Configuration - -See [Installation instructions](https://github.com/codeling/w2wiki/blob/master/INSTALL.md). - - -## Security Notice - -In its current form, W2 wiki is not security-hardened; it's recommended to only run on an additionally secured server (e.g. in a small, private network for one user only; and secured behind a VPN and/or HTTPS with basic authentication). - - -## License - -W2 is licensed under the [MIT license](https://github.com/codeling/w2wiki/blob/master/LICENSE). - - -## Acknowledgements - -Originally written by [Steven Frank](https://github.com/panicsteve/w2wiki) and others, with modifications by -- [44uk](https://github.com/44uk/w2wiki) -- [knee-cola](https://github.com/knee-cola/w2wiki) -- [namvan](https://github.com/namvan/w2wiki) -- [nickodell](https://github.com/nickodell/w2wiki) -- [pilem](https://github.com/pilem/w2) - -W2 wiki uses [PHP Markdown](https://github.com/michelf/php-markdown) by Michel Fortin for rendering Markdown to HTML. - -The [Markdown syntax](https://github.com/codeling/w2wiki/blob/master/pages/MarkdownSyntax.md) description is taken from [daringfireball.net](https://daringfireball.net/projects/markdown/syntax). - -Maintainer of this fork is [codeling](https://github.com/codeling/w2wiki). - - -## Reporting Bugs - -Please report bugs in [the github issue tracker](https://github.com/codeling/w2wiki/issues) of this fork. - diff --git a/config.php b/config.php deleted file mode 100755 index 6e2bf81..0000000 --- a/config.php +++ /dev/null @@ -1,216 +0,0 @@ - - * Code may be re-used as long as the above copyright notice is retained. - * See README.md for full details. - * - * Written with Coda: - * - */ - -// -------------------- -// Site layout settings -// -------------------- - -// PAGES_PATH -// -// The path to the raw text documents maintained by W2 -// You should not use a trailing slash. - -define('PAGES_PATH', dirname(__FILE__). '/pages'); - -// UPLOAD_FOLDER -// -// The subfolder in PAGES_PATH that uploads get stored to -define('UPLOAD_FOLDER', 'images'); - -// PAGES_EXT -// -// The extension of the Markdown files in the PAGES_PATH -// folder which are displayed by W2 -define('PAGES_EXT', 'md'); - - -// BASE_URI -// -// The base URI for this W2 installation. You only need to change this if we guess wrong. -// You should not use a trailing slash. - -define('BASE_URI', str_replace('/index.php', '', $_SERVER['SCRIPT_NAME'])); - -// SELF -// -// The path component of the URL to the main script, such as: /w2/index.php - -define('SELF', $_SERVER['SCRIPT_NAME']); - -// VIEW -// -// Needed only if your web server spawns PHP as a CGI instead of an internal module. -// For example: define('VIEW', '?action=view&page='); - -define('VIEW', ''); - -// DEFAULT_PAGE -// -// The name of the page to show as the "Home" page. -// Value is a string, the title of a page (case-sensitive!) - -define('DEFAULT_PAGE', 'Home'); - -// CSS_FILE -// -// The CSS file to load to style the wiki, relative to BASE_URI - -define('CSS_FILE', 'index.css'); - -// SIDEBAR_FILE -// -// The name of the page to be shown as sidebar (leave empty to disable sidebar feature) - -define ('SIDEBAR_PAGE', '_sidebar'); - -// PAGE_TITLE -// -// A title prepended to the title head tag of all pages of the wiki - -define ('PAGE_TITLE', 'Wiki: '); - -// -------------------- -// File upload settings -// -------------------- - -// DISABLE_UPLOADS -// -// Globally enable/disable file uploads - -define('DISABLE_UPLOADS', false); - -// VALID_UPLOAD_TYPES -// -// Acceptable file types for file uploads. This is a good idea for security. -// Value is a comma-separated string of MIME types. - -define('VALID_UPLOAD_TYPES', 'image/jpeg,image/pjpeg,image/png,image/gif,application/pdf'); - -// VALID_UPLOAD_EXTS -// -// Acceptable filename extensions for file uploads -// Value is a comma-separated string of filename extensions (case-sensitive!) - -define('VALID_UPLOAD_EXTS', 'jpg,jpeg,png,gif,pdf'); - -// ------------------ -// Interface settings -// ------------------ - -// TITLE_DATE -// -// The format to use when displaying page modification times. -// See the manual for the PHP 'date()' function for the specification: -// http://php.net/manual/en/function.date.php -// Note that these settings are overridden by the -// date_format/date_format_no_time in the used locale! - -define('TITLE_DATE', 'j-M-Y g:i A'); -define('TITLE_DATE_NO_TIME', 'j-M-Y'); - -// EDIT_ROWS -// -// Default size of the text editing area in text rows. - -define('EDIT_ROWS', 18); - -// AUTOLINK_PAGE_TITLES -// -// Automatically converts any page titles appearing in text into links -// to the named page. This might degrade performance if you have many -// thousands of pages. - -define('AUTOLINK_PAGE_TITLES', false); - - -// ----------------------------- -// Security and session settings -// ----------------------------- - -// REQUIRE_PASSWORD -// -// Is a password required to access this wiki? - -define('REQUIRE_PASSWORD', false); - -// W2_PASSWORD -// -// The password for the wiki, if REQUIRE_PASSWORD is true -// Replace 'secret' with your password to set your password. - -define('W2_PASSWORD', 'secret'); - -// W2_PASSWORD_HASH -// -// Alternate (more secure) password storage. -// To use a hashed password, Comment out the W2_PASSWORD definition above and uncomment -// this one, using the result of sha1('your_password') as the value. -// -// In Mac OS X, you can do this from the Terminal: -// echo -n 'your_password' | openssl sha1 -// -// define('W2_PASSWORD_HASH', 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4'); - -define('W2_PASSWORD_HASH', ''); - -// allowedIPs -// -// A whitelist of IP addresses that are allowed access to the wiki. -// If empty, all IPs are allowed. - -$allowedIPs = array(); - -// W2_SESSION_LIFETIME -// -// How long before a login session expires? Default is 30 days - -define('W2_SESSION_LIFETIME', 60 * 60 * 24 * 30); - -// W2_SESSION_NAME -// -// Name for session (used in the cookie) - -define('W2_SESSION_NAME', 'W2'); - - -// ----------------------------- -// Git Integration -// ----------------------------- - -// GIT_COMMIT_ENABLED -// -// Enable/Disable committing changes in page folder to local git repository - -define('GIT_COMMIT_ENABLED', false); - -// GIT_PUSH_ENABLED -// -// Enable/Disable pushing changes in page folder to a remote git repository - -define('GIT_PUSH_ENABLED', false); - - -// ----------------------------- -// Locale and encoding settings -// ----------------------------- - -// W2_CHARSET -// -// Value for meta charset. - -define('W2_CHARSET', 'UTF-8'); - -// W2_LOCALE -// -// Name for locale. - -define('W2_LOCALE', 'en'); diff --git a/icons/close.svg b/icons/close.svg deleted file mode 100755 index 4d8b37e..0000000 --- a/icons/close.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/icons/delete-dark.svg b/icons/delete-dark.svg deleted file mode 100755 index 9c33315..0000000 --- a/icons/delete-dark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/delete.svg b/icons/delete.svg deleted file mode 100755 index 9c33315..0000000 --- a/icons/delete.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/edit-dark.svg b/icons/edit-dark.svg deleted file mode 100755 index 255b07d..0000000 --- a/icons/edit-dark.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/edit.svg b/icons/edit.svg deleted file mode 100755 index 611d77a..0000000 --- a/icons/edit.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/format-text-bold.svg b/icons/format-text-bold.svg deleted file mode 100755 index 1b2b8e4..0000000 --- a/icons/format-text-bold.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/format-text-code.svg b/icons/format-text-code.svg deleted file mode 100755 index ae5e15e..0000000 --- a/icons/format-text-code.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/format-text-italic.svg b/icons/format-text-italic.svg deleted file mode 100755 index d051ff2..0000000 --- a/icons/format-text-italic.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/icons/home.svg b/icons/home.svg deleted file mode 100755 index 27d5580..0000000 --- a/icons/home.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/internet.png b/icons/internet.png deleted file mode 100755 index 56991f28f295ec828288839fbab55fa994828c8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 886 zcmV-+1Bv{JP)_6rCNvy8lgy~Ep3^0>g$_n=l%G8 zzb;-&gm{ya+?$--oO5rE@JPM$+qILGuIQt_qTSo&>FgiNS$%e@blW07xQ_eH>|0OH z{Fg5~%^MdklxhRHsr~)okO)MvaPCSsm7-?yW&w@DiZUYVw8Zwkxwi+~4;Gxfc(G^X z2|L%nE9wRawj9p>xQqLK27?2luu7$LQRF-A)WN~k*UpWO`Yu4VY_3##wz^{jvx_;- zPwpm46etBESP`&*q=J>T&u=wz-vYKJk zQD79-C?t_|)&kZ6o%Yq$4@nW7sngPxCyTw{hm^B0|2cROUq?0O&%iA+jmh8AnfT| zV9&q`^?G5+>3;cx8jkmzmuYjLb{&JpSc4T!SD{H?wT?w-1_gBDf(1V)F~8W)dOdeW zsg1@2VPtfqh>U*VZwL8OgTv2WW9;Z<(4=;ZgT!dZ_b1f+XNP`K!P=QHaJhAJAF)aP z7xQ$h_zOd=u^6PcKxnc@1S7iipj47C|(XJct17r5iIr}l*p zrE#Z@d~yDGS9Rsne9<4yc$?XkTf@oXjRSWu(N9Kqetqw&+Cy>v7oC=71Z3T`dH?_b M07*qoM6N<$f@im=oB#j- diff --git a/icons/link-dark.svg b/icons/link-dark.svg deleted file mode 100755 index 36db492..0000000 --- a/icons/link-dark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/icons/link.svg b/icons/link.svg deleted file mode 100755 index 9381210..0000000 --- a/icons/link.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/icons/list.svg b/icons/list.svg deleted file mode 100755 index 02605c1..0000000 --- a/icons/list.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/icons/new.svg b/icons/new.svg deleted file mode 100755 index 2f81e2f..0000000 --- a/icons/new.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/icons/rename-dark.svg b/icons/rename-dark.svg deleted file mode 100755 index 9d31cc1..0000000 --- a/icons/rename-dark.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/icons/rename.svg b/icons/rename.svg deleted file mode 100755 index e8570f9..0000000 --- a/icons/rename.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/icons/upload.svg b/icons/upload.svg deleted file mode 100755 index c6ec427..0000000 --- a/icons/upload.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/images/.gitignore b/images/.gitignore deleted file mode 100755 index 6f40c4d..0000000 --- a/images/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything -* -# except this file -!.gitignore diff --git a/index.css b/index.css deleted file mode 100755 index c371bb3..0000000 --- a/index.css +++ /dev/null @@ -1,410 +0,0 @@ -/* - * W2 - * - * Copyright (C) 2007-2011 Steven Frank - * - * Code may be re-used as long as the above copyright notice is retained. - * See README.txt for full details. - * - * Written with Coda: - * - * colors icons: - * 240,240,240 - * dark: 15, 15, 15 - */ - -* { - font-family: Monospace; - font-size: 11px; - margin: 0; - padding: 0; -} - -body { - background-color: #363636; -} - -blockquote { - background-color: #0f070f; - margin: 4px 4px 12px 20px; - padding: 4px 10px 4px 10px; -} - -form { - display: inline; -} - -li { - line-height: 1.5em; -} - -h1 { - font-size: 2em; - font-weight: bold; - margin-bottom: 4px; - /*margin-top: .6em;*/ -} - -h2 { - font-size: 1.2em; - font-weight: bold; - margin-bottom: 4px; - margin-top: .5em; -} - -h3 { - font-size: 1.2em; - font-weight: bold; -} -h3, h4, h5, h6 { - margin-top: .4em; - margin-bottom: 4px; -} - -hr { - border-top: 1px solid #363636; - border-bottom: 0; - border-left: 0; - border-right: 0; - margin-top: 12px; - margin-bottom: 12px; -} - -ul, -ol { - margin-top: .5em; - margin-left: 1em; - padding-left: 1em; - list-style-position: outside; -} - -ul li, ol li { - padding-left: .5em; -} - -li > ul, li > ol -{ - margin-top: 0; -} - -p { - margin-top: 1.5em; - margin-bottom: 1.5em; -} - -pre { - font-family: Monospace; - margin-left: 0; - margin-bottom: .5em; - margin-top: .5em; - - /* stroke each browser so that they wrap lines in the pre tag */ - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - - background: #212121; - border: 1px dotted gray; - padding: .2em .2em .2em .4em; -} - -code { - font-family: Monospace; - background: #212121; - color: #bbbbbb; - padding: .1em .1em .1em .2em; -} - -table { - border-collapse: collapse; - padding: .2em; - max-width: 99%; - background-color: #212121; - color: #dddddd; -} - th { - text-align: left; - } - td, th { - padding: .1em 1em .1em .1em; - word-break: break-all; - background: #212121; - } - thead { - border-bottom: 1px solid black; - font-weight: bold; - } - thead td a { - text-decoration:none; - } - thead td span.sortBy:after { - content: "\25BC"; - } - tr:nth-child(even) { - background: #e4e4e4; - } - tr:nth-child(odd) { - background: #eeeeee; - } -.pageActions { - padding-left: 8px; - padding-right: 8px; -} - -textarea { - font-family: Monospace; - width: 75%; - background-color: #212121; - color: #f0eee4; -} - @media (max-width: 600px), (orientation: portrait) { - textarea { - width: 99%; - } - } - -input[type="text"], -textarea { - padding: 2px; -} - -input { - font-family: Monospace; -} - -input#gitmsg -{ - width: 60%; -} - -.main { - padding: .3em .3em .3em 1em; - background-color: #212121; - color: #f0eee4; -} - -.main a { - color: #89bfff; - text-decoration: none; - transition: 0.1s; -} - -.main a:hover { - color: #ccccff; - text-decoration: underline; -} - -/* the globe */ -.main a[href^="http"]::after { - /*content: url('/icons/internet.png');*/ -} - -.main a.literalMatch { - font-weight: bold; - color: #6666ff; -} - -.main a.noexist { - color: #f34000 !important; -} - -.login { - margin: 40px auto; - max-width: 650px; - line-height: 1.4; -} - -.note { - background-color: #212121; - padding: 4px; - margin: .5em 0 .5em 0; - color: #6666ff; - border: solid 1px #6666ff; - width: 75%; -} - @media (max-width: 600px), (orientation: portrait) { - .note { - width: 99%; - } - } - -.titlebar { - background-color: #262626; - color: #89bfff; - padding: 2px; -} - -.titlebar span.title { - font-size: 10px; - font-weight: bold; - margin: 5px; -} - -.titledate { - font-size: 0.90em; - color: #777777; - margin-left: 1em; - margin-right: 1em; -} - -.toolbar { - background-color: #363636; - position: sticky; - top: 0; - font-size: 2px; -} - -.toolbar > a, .titlebar > a { - font-size: 0.90em; - margin-right: 1em; - color: #eeeeee; - text-decoration: none; - font-weight: normal; -} - -.toolbar > a:hover, .titlebar > a:hover { - text-decoration: underline; -} - -.sidebar { - float: right; -} -.sidebar, .linkshere { - margin-right: 5px; - margin-top: 5px; - padding: 4px; - border: solid 1px #666644; -} -.sidebar ul { - margin-top: 0; - margin-left: 4px; -} -.linkshere { - width: 50%; - margin-left: 5px; -} - @media (max-width: 600px), (orientation: portrait) { - .sidebar, .linkshere { - margin-left: 5px; - float: none; - width: auto; - } - } - -input.search { -/* font-size: 0.95em;*/ - color: #212121; - width: 5em; - padding: .1em; -} - -input.search:focus { - width: 15em; -} - -input.pagename { - width: 20em; -} - -/* buttons (non-colors) */ -input[type="button"], -input[type="submit"] { - border:none; - border-radius: 3px; - padding: .5em 1em; - cursor: pointer; - margin-right: .5em; -} -#maxsizelabel { - margin-right: 1em; -} - -/* buttons (such as for the edit page) */ -input[type="submit"] { - background-color: #f0eee4; - color: black; -} -input[type="button"] { - background-color: #363636; - color: white; -} - -input[type="submit"]:hover { - background-color: #f0eee4; - color: black; -} -input[type="button"]:hover { - background-color: #363636; - color: white; -} - -img { - max-width: 50%; - height: auto; -} - -#drawer { - display: inline-block; - position: absolute; - width: 300px; - background-color: rgb(240, 240, 240); - opacity: 0.5; - border: 1px solid black; - border-radius: 5px; - padding: 0; - cursor: move; -} -#drawer h5 { - border-bottom: 1px solid black; - padding: 4px; -} -#drawer div { - padding: 4px; -} -#drawer:hover { - opacity: 1.0; -} -.inactive { - display: none !important; -} -img.icon { - width: 1.5em; - vertical-align: middle; -} -a > img.icon:hover, a > span.icongroup:hover { - outline: 1px outset white; -} -a > img.icon:active, a > span.icongroup:active { - outline: 1px inset white; -} -.rightaligned -{ - float: right; -} - -input.search { - border-color: #363636; - border-width: 0px; - background-color: #363636; - color: #f0eee4; - width: 165px -} - -.sidebar { - color: #aaaaaa; - border-color: #aaaaaa; - background-color: #262626; -} - -.sidebar a { - color: #19bfff; - text-decoration: none; - transition: 0.1s; -} - -.sidebar a:hover { - color: #bbbbff; - text-decoration: underline; -} diff --git a/index.html b/index.html new file mode 100644 index 0000000..48f1b2c --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + +speedwm + + + + + + + + + + diff --git a/index.php b/index.php deleted file mode 100755 index d489d9e..0000000 --- a/index.php +++ /dev/null @@ -1,938 +0,0 @@ - - * - * Code may be re-used as long as the above copyright notice is retained. - * See README.txt for full details. - * - * Written with Coda: - * - */ - -// Install PSR-4-compatible class autoloader -spl_autoload_register(function($class){ - require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php'; -}); - -// Get Markdown class -use md\MarkdownExtra; - - -// User configurable options: -require_once "config.php"; - -// Load configured localization: -require_once 'locales/' . W2_LOCALE . '.php'; - -/** - * Get translated word - * - * String $label Key for locale word - * String $alt_word Alternative word - * return String - */ -function __( $label, $alt_word = null ) -{ - global $w2_word_set; - if( empty($w2_word_set[$label]) ) - { - return is_null($alt_word) ? $label : $alt_word; - } - return htmlspecialchars($w2_word_set[$label], ENT_QUOTES); -} - -if ( REQUIRE_PASSWORD ) -{ - ini_set('session.gc_maxlifetime', W2_SESSION_LIFETIME); - session_set_cookie_params(W2_SESSION_LIFETIME); -} -session_name(W2_SESSION_NAME); -session_start(); - - -if ( count($allowedIPs) > 0 ) -{ - $ip = $_SERVER['REMOTE_ADDR']; - $accepted = false; - - foreach ( $allowedIPs as $allowed ) - { - if ( strncmp($allowed, $ip, strlen($allowed)) == 0 ) - { - $accepted = true; - break; - } - } - - if ( !$accepted ) - { - print "Access from IP address $ip is not allowed"; - exit; - } -} - -function printHeader($title, $action, $bodyclass="") -{ - print "\n"; - print "\n"; - print " \n"; - print " \n"; - print " \n"; - print " \n"; - print " \n"; - print " ".PAGE_TITLE."$title\n"; - print " \n"; - print " \n"; -} - -function printFooter() -{ - print " \n"; - print ""; -} - -function printDrawer() -{ - print "
\n". - " \"".__('Close')."\"\n". - "
\n". - "# ".__('Header')." 1
". - "## ".__('Header')." 2
". - "### ".__('Header')." 3
". - "#### ".__('Header')." 4
". - "##### ".__('Header')." 5
". - "###### ".__('Header')." 6
". - "
". - "*".__('Emphasize')."* - ".__('Emphasize')."
". - "_".__('Emphasize')."* - ".__('Emphasize')."
". - "**".__('Bold')."** - ".__('Bold')."
". - "__".__('Bold')."__ - ".__('Bold')."
". - "
". - "[[Link to page]]
". - "<http://example.com/>
". - "[link text](http://url)

". - "{{image.jpg}}
". - "![Alt text](/images/image.jpg)
". - "![Alt text](/images/image.jpg \"Optional title\")
". - "
". - "- Unordered list
". - "+ Unordered list
". - "* Unordered list
". - "1. Ordered list
". - "
". - "> Blockquote
".//
Blockquotes
\n". - "```Code```
". //
Code
\n\n". - "`inline-code`

". - "*** Horizontal rule
". - "--- Horizontal rule
\n". - "
\n". - "
\n". - " \n". - " \n"; -} - -if ( REQUIRE_PASSWORD && !isset($_SESSION['password']) ) -{ - if ( !defined('W2_PASSWORD_HASH') || W2_PASSWORD_HASH == '' ) - define('W2_PASSWORD_HASH', sha1(W2_PASSWORD)); - - if ( (isset($_POST['p'])) && (sha1($_POST['p']) == W2_PASSWORD_HASH) ) - $_SESSION['password'] = W2_PASSWORD_HASH; - else - { - printHeader( __('Log In'), '', "login"); - print "

" . __('Log In') . "

\n"; - print "
\n"; - print " ".__('Password') . ": \n"; - print " \n"; - print "
\n"; - printFooter(); - exit; - } -} - -// Support functions - -function descLengthSort($val_1, $val_2) -{ - $firstVal = strlen($val_1); - $secondVal = strlen($val_2); - return ( $firstVal > $secondVal ) ? - -1 : ( ( $firstVal < $secondVal ) ? 1 : 0); -} - -function getAllPageNames($path = "") -{ - $filenames = array(); - $dir = opendir(PAGES_PATH . "/$path" ); - while ( $filename = readdir($dir) ) - { - if ( $filename[0] == "." ) - { - continue; - } - if ( is_dir( PAGES_PATH . "/$path/$filename" ) ) - { - array_push($filenames, ...getAllPageNames( "$path/$filename" ) ); - continue; - } - if ( preg_match("/".PAGES_EXT."$/", $filename) != 1) - { - continue; - } - $filename = substr($filename, 0, -(strlen(PAGES_EXT)+1) ); - $filenames[] = substr("$path/$filename", 1); - } - closedir($dir); - return $filenames; -} - -function fileNameForPage($page) -{ - return PAGES_PATH . "/$page." . PAGES_EXT; -} - -function imageLinkText($imgName) -{ - return "![".__("Image Description")."](/".UPLOAD_FOLDER."/$imgName)"; -} - -function sanitizeFilename($inFileName) -{ - return str_replace(array('~', '..', '\\', ':', '|', '&'), '-', $inFileName); -} - -function pageURL($page) -{ - return SELF . VIEW . "/".str_replace("%2F", "/", str_replace("%23", "#", urlencode(sanitizeFilename($page)))); -} - -function pageLink($page, $title, $attributes="") -{ - return "$title"; - /* wip - $link_page = $match[1]; - $link_filename = PAGES_PATH . "/$link_page.txt"; - $link_page_exists = file_exists($link_filename); - if ($link_page_exists) - return "$title"; - else - //return "" . htmlentities($link_page) . ""; - return "$title"; - */ -} - -function redirectWithMessage($page, $msg) -{ - $_SESSION["msg"] = $msg; - header("HTTP/1.1 303 See Other"); - header("Location: " . pageURL($page) ); - exit; -} - -function checkedExecute(&$msg, $cmd) -{ - $returnValue = 0; - $output = ''; - exec($cmd, $output, $returnValue); - if ($returnValue != 0) - { - $msg .= "
Error executing command ".$cmd." (return value: ".$returnValue."): ".implode(" ", $output); - } - return ($returnValue == 0); -} - -function gitChangeHandler($commitmsg, &$msg) -{ - if (!GIT_COMMIT_ENABLED) - { - return; - } - if (checkedExecute($msg, "cd ".PAGES_PATH." && git add -A && git commit -m ".escapeshellarg($commitmsg))) - { - if (!GIT_PUSH_ENABLED) - { - return; - } - checkedExecute($msg, "cd ".PAGES_PATH." && git push"); - } -} - -function toHTMLID($noid) -{ // in HTML5, only spaces aren't allowed - return str_replace(" ", "-", $noid); -} - -function toHTML($inText) -{ - $parser = new MarkdownExtra; - $parser->no_markup = true; - $outHTML = $parser->transform($inText); - if ( AUTOLINK_PAGE_TITLES ) - { - $pagenames = getAllPageNames(); - uasort($pagenames, "descLengthSort"); - foreach ( $pagenames as $pageName ) - { - // match pageName, but only if it isn't inside another word or inside braces (as in "[$pageName]"). - $outHTML = preg_replace("/(? 1) ? $linkTitleSplit[1] : $linkedPage; - $pagePart = explode('#', $linkedPage)[0]; // split away an eventual anchor part - $linkedFilename = fileNameForPage(sanitizeFilename($pagePart)); - $exists = file_exists($linkedFilename); - $outHTML = str_replace("[[$fullLinkText]]", - pageLink($linkedPage, $linkText, ($exists? "" : " class=\"noexist\"")), $outHTML); - } - $outHTML = preg_replace("/\{\{(.*?)\}\}/", "\"\\1\"", $outHTML); - - // add an anchor in all title tags (h1/2/3/4): - preg_match_all( - "/(.*?)<\/h\\1>/", - $outHTML, - $matches, - PREG_PATTERN_ORDER - ); - for ($i = 0; $i < count($matches[0]); $i++) - { - $prefix = ""; - $caption = $matches[2][$i]; - $suffix = substr_replace($prefix, "/", 1, 0); - $outHTML = str_replace("$prefix$caption$suffix", - "$prefix$caption$suffix", $outHTML); - } - return $outHTML; -} - -function destroy_session() -{ - if ( isset($_COOKIE[session_name()]) ) - { - setcookie(session_name(), '', time() - 42000, '/'); - } - session_destroy(); - unset($_SESSION["password"]); - unset($_SESSION); -} - -function getPageActions($page, $action, $imgSuffix) -{ - $pageActions = array('edit', 'delete', 'rename'); - $pageActionNames = array(__('Edit'), __('Delete'), __('Rename')); - $result = ''; - for ($i = 0; $i < count($pageActions); $i++ ) - { - if ($action != $pageActions[$i]) - { - $result .= " \"".$pageActionNames[$i]."\"\n"; - } - } - $result .= " \"".__('Show\n"; - return $result; -} - -// Main code - -$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'view'; -$newPage = ""; -$text = ""; -$html = ""; -if ($action === 'view' || $action === 'edit' || $action === 'save' || $action === 'rename' || $action === 'delete') -{ - // Look for page name following the script name in the URL, like this: - // http://stevenf.com/w2demo/index.php/Markdown%20Syntax - // - // Otherwise, get page name from 'page' request variable. - - $page = preg_match('@^/@', @$_SERVER["PATH_INFO"]) ? - urldecode(substr($_SERVER["PATH_INFO"], 1)) : urldecode(@$_REQUEST['page']); - $page = sanitizeFilename($page); - if ( $page == "" ) - { - $page = DEFAULT_PAGE; - } - $filename = fileNameForPage($page); -} -if ($action === 'view' || $action === 'edit') -{ - if ( file_exists($filename) ) - { - $text = file_get_contents($filename); - } - else - { - $newPage = $page; - $action = 'new'; - } -} -$oldgitmsg = ""; -$triedSave = false; -if ( $action == 'save' ) -{ - $msg = ''; - $newText = $_REQUEST['newText']; - $isNew = $_REQUEST['isNew']; - if ($isNew) - { - $page = str_replace(array('|','#'), '', $page); - $filename = fileNameForPage($page); - } - if ($isNew && file_exists($filename)) - { - $msg .= "Error creating page '$page' - it already exists! Please choose a different name, or edit the existing page (this discards current text!)!\n"; - $action = 'new'; - $text = $newText; - $newPage = $page; - if (GIT_COMMIT_ENABLED) - { - $oldgitmsg = $_REQUEST['gitmsg']; - } - $triedSave = true; - } - else - { - $errLevel = error_reporting(0); - if ( !file_exists( dirname($filename) ) ) { - mkdir(dirname($filename), 0755, true); - } - $success = file_put_contents($filename, $newText); - error_reporting($errLevel); - if ( $success === FALSE) - { - $msg .= "Error saving changes! Make sure your web server has write access to " . PAGES_PATH . "\n"; - $action = ($isNew ? 'new' : 'edit'); - $text = $newText; - $newPage = $page; - if (GIT_COMMIT_ENABLED) - { - $oldgitmsg = $_REQUEST['gitmsg']; - } - $triedSave = true; - } - else - { - $msg .= ($isNew ? __('Created'): __('Saved')); - $usermsg = $_REQUEST['gitmsg']; - $commitmsg = $page . ($usermsg !== '' ? (": ".$usermsg) : ($isNew ? " created" : " changed")); - gitChangeHandler($commitmsg, $msg); - } - } - redirectWithMessage($page, $msg); -} - -if ( $action === 'edit' || $action === 'new' ) -{ - $formAction = SELF . (($action === 'edit') ? "/$page" : ""); - $html .= "
\n"; - - if ( $action === 'edit' ) - { - $html .= "\n"; - } - else - { - if ($newPage != "" && !$triedSave) - { - $html .= "
". __('Creating new page since no page with given title exists!') ; - // check if similar page exists... - $pageNames = getAllPageNames(); - foreach($pageNames as $pageName) - { - if (levenshtein(strtoupper($newPage), strtoupper($pageName)) < sqrt(min(strlen($newPage), strlen($pageName))) ) - { - $html .= "
Note: Found similar page ".pageLink($pageName, $pageName).". Maybe you meant to edit this instead?"; - } - } - $html .= "
\n"; - } - $html .= "

" . __('Title') . ":

\n"; - - } - - $html .= "

\n"; - if (GIT_COMMIT_ENABLED) - { - $html .= "

Message:

\n"; - } - - $html .= "

\n"; - $html .= "\n"; - $html .= ''."\n"; - $html .= ''."\n"; - $html .= "

\n"; -} -else if ( $action === 'logout' ) -{ - destroy_session(); - header("Location: " . SELF); - exit; -} -else if ( $action === 'upload' ) -{ - if ( DISABLE_UPLOADS ) - { - $html .= '

' . __('Image uploading has been disabled on this installation.') . '

'; - } - else - { - $html .= "

\n". - "". - "\n". - ''. - ''. - ''. - ''. - ''."\n". - ''."\n"; - "

\n"; - } - // list files in UPLOAD_FOLDER - $path = PAGES_PATH . "/". UPLOAD_FOLDER . "/*"; - $imgNames = glob($path); - natcasesort($imgNames); - $html .= "

".__('Total').": ".count($imgNames)." ".__('images')."

"; - $html .= ""; - $html .= "". -/* - "". - "". - */ "". - ""; - $date_format = __('date_format', TITLE_DATE); - foreach ($imgNames as $imgName) - { - $html .= "". - "". - "". - "". - "". - "\n"; - } - $html .= "
".(($sortBy!='name')?("Name"):"Name")."".(($sortBy!='recent')?("Modified"):"Modified")."".__("Name")."".__("Usage")."".__("Modified")."".__("Action")."
".basename($imgName)."
".imageLinkText(basename($imgName))."
".date($date_format, filemtime($imgName))."".__('Delete')."
\n"; -} -else if ( $action === 'uploaded' ) -{ - if ( DISABLE_UPLOADS ) - { - die('Invalid access. Uploads are disabled in the configuration.'); - } - $dstName = sanitizeFilename($_FILES['userfile']['name']); - $dstName = str_replace(" ", "_", $dstName); // image display currently doesn't like spaces! - $fileType = $_FILES['userfile']['type']; - preg_match('/\.([^.]+)$/', $dstName, $matches); - $fileExt = isset($matches[1]) ? $matches[1] : null; - $imgExts = array('jpg','jpeg','png','gif'); - $msg = ''; - if (in_array($fileType, explode(',', VALID_UPLOAD_TYPES)) && - in_array($fileExt, explode(',', VALID_UPLOAD_EXTS))) - { - $path = PAGES_PATH . "/". UPLOAD_FOLDER . "/$dstName"; - $resize = isset($_POST['resize']) && $_POST['resize'] === 'true'; - $doResize = $resize && in_array($fileExt, $imgExts); - if ($doResize) - { - $exif = exif_read_data($_FILES['userfile']['tmp_name']); - $size = getimagesize($_FILES['userfile']['tmp_name']); - $maxsize = intval($_POST['maxsize']); - $doResize = ($size[0] > $maxsize || $size[1] > $maxsize); - if ($doResize) - { - $msg .= "trying to resize"; - $finalPath = $path; - $path = substr($path, 0, strlen($path)-strlen($fileExt)-1) . "-tmp-resize." . $fileExt; - } - } - $errLevel = error_reporting(0); - if ( move_uploaded_file($_FILES['userfile']['tmp_name'], $path) === true ) - { - $msg = "File '$dstName' uploaded! "; - if ($doResize) - { - $newSize = array(0, 0); - $idx0 = ($size[0] > $size[1]) ? 0 : 1; - $idx1 = ($idx0 == 0) ? 1 : 0; - $newSize[$idx0] = $maxsize; - $newSize[$idx1] = (int)round($size[$idx1] * $maxsize / $size[$idx0]); - $src = imagecreatefromstring(file_get_contents($path)); - $dst = imagecreatetruecolor($newSize[0], $newSize[1]); - if (!imagecopyresampled($dst, $src, 0, 0, 0, 0, $newSize[0], $newSize[1], $size[0], $size[1])) - { - $msg .= "Resizing file failed!"; - } - imagedestroy( $src ); - if(!empty($exif['Orientation'])) - { - switch($exif['Orientation']) - { - case 8: - $msg .= "Image rotated by +90°. "; - $rot = imagerotate($dst,90,0); - break; - case 3: - $msg .= "Image rotated by 180°. "; - $rot = imagerotate($dst,180,0); - break; - case 6: - $msg .= "Image rotated by -90°. "; - $rot = imagerotate($dst,-90,0); - break; - default: - $msg .= "Unknown EXIF orientation specification: ".$exif['Orientation']."!"; - break; - } - if ($rot === false) - { - $msg .= "Rotation failed!"; - } - else - { - imagedestroy( $dst ); - $dst = $rot; - } - } - if ($fileExt === 'png') - { - imagepng($dst, $finalPath); - } - else if ($fileExt === 'jpg' || $fileExt === 'jpeg') - { - imagejpeg($dst, $finalPath); - } - else if ($fileExt === 'gif') - { - imagegif($dst, $finalPath); - } - unlink($path); - imagedestroy( $dst ); - } - gitChangeHandler($msg, $msg); - $msg .= " ($size[0]x$size[1]".(($doResize)?", resized to $newSize[0]x$newSize[1]":"").") successfully! Use
".imageLinkText($dstName)."
to refer to it!"; - } - else - { - $error_code = $_FILES['userfile']['error']; - if ( $error_code === 0 ) { - // Likely a permissions issue - $msg .= __('Upload error') .": Can't write to ".$path."

\n". - "Check that your permissions are set correctly."; - } else { - // Give generic error message - $msg .= __('Upload error').", error #".$error_code."

\n". - "Please see here for more information.

\n". - "If you see this message, please file a bug to improve w2wiki"; - } - } - error_reporting($errLevel); - } - else - { - $msg .= __('Upload error: invalid file type'); - } - redirectWithMessage(DEFAULT_PAGE, $msg); -} -else if ( $action === 'rename' || $action === 'delete' || $action === 'imgDelete') -{ - if ($action === 'imgDelete') - { - $page = sanitizeFilename(urldecode($_REQUEST['imgName'])); - } - $actionName = ($action === 'delete' || $action === 'imgDelete')?__('Delete'):__('Rename'); - $html .= "
"; - $html .= "

".$actionName." $page ". - (($action==='rename')? (__('to')." ") : "?") . "

"; - $html .= "

"; - $html .= "\n"; - $html .= ""; - $html .= ""; - $html .= "

"; -} -else if ( $action === 'renamed' || $action === 'deleted') -{ - // TODO: prevent relative filenames from being injected - $oldPageName = sanitizeFilename($_POST['oldPageName']); - $newPageName = ($action === 'deleted') ? "": sanitizeFilename($_POST['newPageName']); - $msg = ''; - if ($action === 'deleted') - { - $success = unlink(fileNameForPage($oldPageName)); - } - else - { - $success = rename(fileNameForPage($oldPageName), fileNameForPage($newPageName)); - } - if ($success) - { - $message = ($action === 'deleted') ? "Removed $oldPageName." : - "Renamed $oldPageName to $newPageName."; - $msg .= $message; - // Change links in all pages to point to new page - $pagenames = getAllPageNames(); - $changedPages = array(); - foreach ($pagenames as $replacePage) - { - $content = file_get_contents(fileNameForPage($replacePage)); - $count = 0; - $regexSaveOldPageName = str_replace("/", "\\/", $oldPageName); - $newContent = preg_replace("/\[\[$regexSaveOldPageName([|#].*\]\]|\]\])/", - (($action === 'deleted') ? "" : "[[$newPageName\\1"), - $content, -1, $count); - if ($count > 0) // if something changed - { - $changedPages[] = $replacePage." ($count ".__('matches').")"; - file_put_contents(fileNameForPage($replacePage), $newContent); - } - } - if (count($changedPages) > 0) - { - $msg .= "
\n".__('Updated links in the following pages:')."\n
  • "; - $msg .= implode("
  • ", $changedPages); - $msg .= "
"; - } - gitChangeHandler($message, $msg); - $page = $newPageName; - } - else - { - $msg .= ($action === 'deleted') ? __('Error deleting file'): __('Error renaming file'); - $page = $oldPageName; - } - if ($action === 'deleted' && $success) - { - $page = DEFAULT_PAGE; - } - redirectWithMessage($page, $msg); -} -else if ( $action === 'imgDeleted') -{ - // TODO: prevent relative filenames from being injected - $oldPageName = sanitizeFilename($_REQUEST['oldPageName']); - $imgPath = PAGES_PATH . "/". UPLOAD_FOLDER . "/". $oldPageName; - $success = unlink($imgPath); - if ($success) - { - $msg = __('Image deleted'); - gitChangeHandler($msg, $msg); - $msg .= " (".$imgPath.")"; - } - else - { - $msg = __('Error deleting image'); - $msg .= " (".$imgPath.")"; - } - redirectWithMessage(DEFAULT_PAGE, $msg); -} -else if ( $action === 'all' ) -{ - $pageNames = getAllPageNames(); - $filelist = array(); - $sortBy = isset($_REQUEST['sortBy']) ? $_REQUEST['sortBy'] : 'name'; - if (!in_array($sortBy, array('name', 'recent'))) - { - $sortBy = 'name'; - } - if ($sortBy === 'name') - { - natcasesort($pageNames); - foreach($pageNames as $page) - { - $filelist[$page] = filemtime(fileNameForPage($page)); - } - } - else - { - foreach($pageNames as $page) - { - $filelist[$page] = filemtime(fileNameForPage($page)); - } - arsort($filelist, SORT_NUMERIC); - } - $html .= "

".__('Total').": ".count($pageNames)." ".__("pages")."

"; - $html .= ""; - $html .= "". - "". - "". - "". - ""; - $date_format = __('date_format', TITLE_DATE); - - foreach ($filelist as $pageName => $pageDate) - { - $html .= "". - "". - "". - //"". /* dark mode */ - "". /* light mode */ - "\n"; - } - $html .= "
".(($sortBy!='name')?("Name"):"".__('Name')."")."".(($sortBy!='recent')?("".__('Modified').""):"".__('Modified')."")."".__('Action')."
".pageLink($pageName, $pageName)."".date( $date_format, $pageDate)."".getPageActions($pageName, $action,"-dark")."".getPageActions($pageName, $action, "")."
\n"; - } - else if ( $action === 'search' ) - { - $matches = 0; - $q = $_REQUEST['q']; - $html .= "

Search: $q

\n"; - - if ( trim($q) != "" ) - { - $html .= "
    \n"; - $pagenames = getAllPageNames(); - $found = FALSE; - $matchingPages = array(); - foreach ($pagenames as $searchPage) - { - if ($searchPage === $q) - { - $found = TRUE; - } - if (preg_match("/{$q}/i", $searchPage)) - { - array_unshift($matchingPages, $searchPage); - ++$matches; - } - else - { - $text = file_get_contents(fileNameForPage($searchPage)); - if ( preg_match("/{$q}/i", $text) ) - { - $matchingPages[] = $searchPage; - ++$matches; - } - } - } - foreach ($matchingPages as $page) - { - $link = pageLink($page, $page, ($page === $q)? " class=\"literalMatch\"": ""); - $html .= "
  • $link
  • \n"; - } - if (!$found) - { - $html .= "
  • ".pageLink($q, __('Create page')." '$q'", " class=\"noexist\"")."
  • "; - } - $html .= "
\n"; - } - $html .= "

$matches ".__('matches')."

\n"; - } - else - { - $html .= empty($text) ? '' : toHTML($text); - } - - $datetime = ''; - - if ( ($action === 'all')) - { - $title = __("All"); - } - else if ( $action === 'upload' ) - { - $title = __("Upload"); - } - else if ( $action === 'new' ) - { - $title = __("New"); - } - else if ( $action === 'search' ) - { - $title = __("Search"); - } - else if ($filename != '') - { - $title = (($action === 'edit')? (__('Edit').": "):"") . $page; - $date_format = __('date_format', TITLE_DATE); - if ( $date_format ) - { - $datetime = "" . date($date_format, @filemtime($filename)) . ""; - } - } - else - { - $title = __($action); - } - - // Disable caching on the client (the iPhone is pretty agressive about this - // and it can cause problems with the editing function) - - header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past - printHeader($title, $action); - print "
$title$datetime"; - if ($action === 'view' || $action === 'rename' || $action === 'delete' || $action === 'edit') - { - print(getPageActions($page, $action, "")); - } - print "
\n"; - print "
\n"; - print " \"".\n"; -print " \"".\n"; -print " \"".__('New')."\"\n"; -if ( !DISABLE_UPLOADS ) -{ - print " \"".__('Upload')."\"\n"; -} -if ( REQUIRE_PASSWORD ) -{ - print " ". __('Log out') . ""; -} -print "
\n"; -print " \n
\n"; -if ($action === 'edit') -{ - printDrawer(); -} -print "
\n"; -if (SIDEBAR_PAGE != '') -{ - print "
\n\n"; - $sidebarFile = fileNameForPage(SIDEBAR_PAGE); - if (file_exists($sidebarFile)) - { - $text = file_get_contents($sidebarFile); - } - else - { - $text = __('Sidebar file could not be found')." ($sidebarFile)"; - } - print toHTML($text); - print "
\n"; -} -if ($action === 'view' && $_GET['linkshere']) -{ - print "
".__('What links here:')."
    "; - $pagenames = getAllPageNames(); - foreach($pagenames as $searchPage) - { - $text = file_get_contents(fileNameForPage($searchPage)); - $regexSavePage = str_replace("/", "\\/", $page); - if ( preg_match("/\[\[$regexSavePage/i", $text) ) - { - $link = pageLink($searchPage, $searchPage, ""); - print("
  • $link
  • \n"); - } - } - print "
"; -} -print "
\n\n"; -if(isset($_SESSION['msg']) && $_SESSION['msg'] != '') -{ - print "
".$_SESSION['msg']."
"; - unset($_SESSION['msg']); -} -print "$html\n"; -print "
\n"; -printFooter(); diff --git a/locales/de.php b/locales/de.php deleted file mode 100755 index 1ef8db1..0000000 --- a/locales/de.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Start', - 'New' => 'Neu', - 'Edit' => 'Bearbeiten', - 'Delete' => 'Löschen', - 'Rename' => 'Umbenennen', - 'Created' => 'Angelegt', - 'Upload' => 'Hochladen', - 'All' => 'Alle', - 'Recent' => 'Zuletzt', - 'Exit' => 'Ausloggen', - 'Search' => 'Suchen', - 'Formatting help' => 'Formatierungshilfe', - 'Bold' => 'Fett', - 'Emphasize' => 'Kursiv', - 'Header' => 'Überschrift', - 'Save' => 'Speichern', - 'Cancel' => 'Abbrechen', - 'Saved' => 'Gespeichert', - 'Log In' => 'Einloggen', - 'Log Out' => 'Ausloggen', - 'Password' => 'Passwort', - 'Title' => 'Titel', - 'Image Description' => 'Bildbeschreibung', - 'Name' => 'Name', - 'Usage' => 'Verwendung', - 'Modified' => 'Verändert', - 'Action' => 'Aktion', - 'Total' => 'Gesamt', - 'images' => 'Bilder', - 'matches' => 'Übereinstimmung(en)', - 'pages' => 'Seite(n)', - 'Create page' => 'Seite anlegen', - 'to' => 'in', - 'Shrink if larger than ' => 'Verkleinern wenn größer als ', - 'Pixels' => 'Pixel', - 'What links here:' => 'Seiten die hierher linken:', - 'Close' => 'Schließen', - // Messages - 'Upload error' => 'Fehler beim Hochladen', - 'Upload error: invalid file type' => 'Fehler beim Hochladen: Dieser Dateityp ist nicht zugelassen, bitte wende Dich an deinen Administrator!', - 'Image uploading has been disabled on this installation.' => 'Hochladen ist nicht erlaubt, bitte wende Dich an deinen Administrator!', - 'Creating new page since no page with given title exists!' => 'Es wird eine neue Seite angelegt, weil noch keine Seite mit dem angegebenen Titel existiert!', - 'Updated links in the following pages:' => 'Es wurden Links in den folgenden Seiten aktualisiert:', - 'Error deleting file' => 'Fehler beim Löschen der Datei', - 'Error renaming file' => 'Fehler beim Umbenennen der Datei', - 'Sidebar file could not be found' => 'Seitenleisten-Datei nicht gefunden', - 'Name of new page (restrictions in tip)' => 'Seitenname (Einschränkungen im Tip)', - "Character restrictions: '#' and '|' have a special meaning in page links, they will therefore be removed; also, characters '~', '/', '\\', ':', '|', '&' might cause trouble in filenames and are therefore replaced by '-'." => "Buchstaben-Beschränkungen: '#' und '|' haben eine spezielle Bedeutung in Links, sie werden deshalb entfernt. Weiters können die Zeichen '~', '/', '\\', ':', '|', '&' Probleme in Dateinamen verursachen, und werden deshalb durch einen Bindestrich '-' ersetzt.", - 'Image deleted' => 'Bild gelöscht', - 'Error deleting image' => 'Fehler beim Löschen des Bildes', - // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. - 'date_format' => 'd.m.Y H:i', - 'date_format_no_time' => 'd.m.Y', -); diff --git a/locales/en.php b/locales/en.php deleted file mode 100755 index c609d05..0000000 --- a/locales/en.php +++ /dev/null @@ -1,32 +0,0 @@ - 'Home', - 'New' => 'New', - 'Edit' => 'Edit', - 'Upload' => 'Upload', - 'All' => 'All', - 'Recent' => 'Recent', - 'Exit' => 'Exit', - 'Search' => 'Search', - 'Save' => 'Save', - 'Cancel' => 'Cancel', - 'Saved' => 'Saved', - 'Log In' => 'Log In', - 'Title' => 'Title', - // Messages - 'Upload error' => 'Upload error', - 'Upload error: invalid file type' => 'Upload error: invalid file type', - 'Image uploading has been disabled on this installation.' => 'Image uploading has been disabled on this installation.', - // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. - 'date_format' => 'Y-m-d H:i:s', - 'date_format_no_time' => 'Y-m-d', -); diff --git a/locales/ja.php b/locales/ja.php deleted file mode 100755 index 26ca03a..0000000 --- a/locales/ja.php +++ /dev/null @@ -1,32 +0,0 @@ - 'ホーム', - 'New' => '新規', - 'Edit' => '編集', - 'Upload' => 'アップロード', - 'All' => '全て', - 'Recent' => '最近', - 'Exit' => 'ログアウト', - 'Search' => '検索', - 'Save' => '保存', - 'Cancel' => 'キャンセル', - 'Saved' => '保存しました', - 'Log In' => 'ログイン', - 'Title' => 'ページタイトル', - // Messages - 'Upload error' => 'アップロードエラー', - 'Upload error: invalid file type' => 'アップロードエラー:不正なファイル形式です', - 'Image uploading has been disabled on this installation.' => '画像アップロードは許可されていません。', - // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. - 'date_format' => 'Y-m-d H:i:s', - 'date_format_no_time' => 'Y-m-d', -); diff --git a/locales/sample.php b/locales/sample.php deleted file mode 100755 index c609d05..0000000 --- a/locales/sample.php +++ /dev/null @@ -1,32 +0,0 @@ - 'Home', - 'New' => 'New', - 'Edit' => 'Edit', - 'Upload' => 'Upload', - 'All' => 'All', - 'Recent' => 'Recent', - 'Exit' => 'Exit', - 'Search' => 'Search', - 'Save' => 'Save', - 'Cancel' => 'Cancel', - 'Saved' => 'Saved', - 'Log In' => 'Log In', - 'Title' => 'Title', - // Messages - 'Upload error' => 'Upload error', - 'Upload error: invalid file type' => 'Upload error: invalid file type', - 'Image uploading has been disabled on this installation.' => 'Image uploading has been disabled on this installation.', - // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. - 'date_format' => 'Y-m-d H:i:s', - 'date_format_no_time' => 'Y-m-d', -); diff --git a/md/Markdown.inc.php b/md/Markdown.inc.php deleted file mode 100755 index e2bd380..0000000 --- a/md/Markdown.inc.php +++ /dev/null @@ -1,10 +0,0 @@ - - * @copyright 2004-2019 Michel Fortin - * @copyright (Original Markdown) 2004-2006 John Gruber - */ - -namespace md; - -/** - * Markdown Parser Class - */ -class Markdown implements MarkdownInterface { - /** - * Define the package version - * @var string - */ - const MARKDOWNLIB_VERSION = "1.9.0"; - - /** - * Simple function interface - Initialize the parser and return the result - * of its transform method. This will work fine for derived classes too. - * - * @api - * - * @param string $text - * @return string - */ - public static function defaultTransform($text) { - // Take parser class on which this function was called. - $parser_class = \get_called_class(); - - // Try to take parser from the static parser list - static $parser_list; - $parser =& $parser_list[$parser_class]; - - // Create the parser it not already set - if (!$parser) { - $parser = new $parser_class; - } - - // Transform text using parser. - return $parser->transform($text); - } - - /** - * Configuration variables - */ - - /** - * Change to ">" for HTML output. - * @var string - */ - public $empty_element_suffix = " />"; - - /** - * The width of indentation of the output markup - * @var int - */ - public $tab_width = 4; - - /** - * Change to `true` to disallow markup or entities. - * @var boolean - */ - public $no_markup = false; - public $no_entities = false; - - - /** - * Change to `true` to enable line breaks on \n without two trailling spaces - * @var boolean - */ - public $hard_wrap = false; - - /** - * Predefined URLs and titles for reference links and images. - * @var array - */ - public $predef_urls = array(); - public $predef_titles = array(); - - /** - * Optional filter function for URLs - * @var callable|null - */ - public $url_filter_func = null; - - /** - * Optional header id="" generation callback function. - * @var callable|null - */ - public $header_id_func = null; - - /** - * Optional function for converting code block content to HTML - * @var callable|null - */ - public $code_block_content_func = null; - - /** - * Optional function for converting code span content to HTML. - * @var callable|null - */ - public $code_span_content_func = null; - - /** - * Class attribute to toggle "enhanced ordered list" behaviour - * setting this to true will allow ordered lists to start from the index - * number that is defined first. - * - * For example: - * 2. List item two - * 3. List item three - * - * Becomes: - *
    - *
  1. List item two
  2. - *
  3. List item three
  4. - *
- * - * @var bool - */ - public $enhanced_ordered_list = false; - - /** - * Parser implementation - */ - - /** - * Regex to match balanced [brackets]. - * Needed to insert a maximum bracked depth while converting to PHP. - * @var int - */ - protected $nested_brackets_depth = 6; - protected $nested_brackets_re; - - protected $nested_url_parenthesis_depth = 4; - protected $nested_url_parenthesis_re; - - /** - * Table of hash values for escaped characters: - * @var string - */ - protected $escape_chars = '\`*_{}[]()>#+-.!'; - protected $escape_chars_re; - - /** - * Constructor function. Initialize appropriate member variables. - * @return void - */ - public function __construct() { - $this->_initDetab(); - $this->prepareItalicsAndBold(); - - $this->nested_brackets_re = - str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). - str_repeat('\])*', $this->nested_brackets_depth); - - $this->nested_url_parenthesis_re = - str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). - str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); - - $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; - - // Sort document, block, and span gamut in ascendent priority order. - asort($this->document_gamut); - asort($this->block_gamut); - asort($this->span_gamut); - } - - - /** - * Internal hashes used during transformation. - * @var array - */ - protected $urls = array(); - protected $titles = array(); - protected $html_hashes = array(); - - /** - * Status flag to avoid invalid nesting. - * @var boolean - */ - protected $in_anchor = false; - - /** - * Status flag to avoid invalid nesting. - * @var boolean - */ - protected $in_emphasis_processing = false; - - /** - * Called before the transformation process starts to setup parser states. - * @return void - */ - protected function setup() { - // Clear global hashes. - $this->urls = $this->predef_urls; - $this->titles = $this->predef_titles; - $this->html_hashes = array(); - $this->in_anchor = false; - $this->in_emphasis_processing = false; - } - - /** - * Called after the transformation process to clear any variable which may - * be taking up memory unnecessarly. - * @return void - */ - protected function teardown() { - $this->urls = array(); - $this->titles = array(); - $this->html_hashes = array(); - } - - /** - * Main function. Performs some preprocessing on the input text and pass - * it through the document gamut. - * - * @api - * - * @param string $text - * @return string - */ - public function transform($text) { - $this->setup(); - - # Remove UTF-8 BOM and marker character in input, if present. - $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); - - # Standardize line endings: - # DOS to Unix and Mac to Unix - $text = preg_replace('{\r\n?}', "\n", $text); - - # Make sure $text ends with a couple of newlines: - $text .= "\n\n"; - - # Convert all tabs to spaces. - $text = $this->detab($text); - - # Turn block-level HTML blocks into hash entries - $text = $this->hashHTMLBlocks($text); - - # Strip any lines consisting only of spaces and tabs. - # This makes subsequent regexen easier to write, because we can - # match consecutive blank lines with /\n+/ instead of something - # contorted like /[ ]*\n+/ . - $text = preg_replace('/^[ ]+$/m', '', $text); - - # Run document gamut methods. - foreach ($this->document_gamut as $method => $priority) { - $text = $this->$method($text); - } - - $this->teardown(); - - return $text . "\n"; - } - - /** - * Define the document gamut - * @var array - */ - protected $document_gamut = array( - // Strip link definitions, store in hashes. - "stripLinkDefinitions" => 20, - "runBasicBlockGamut" => 30, - ); - - /** - * Strips link definitions from text, stores the URLs and titles in - * hash references - * @param string $text - * @return string - */ - protected function stripLinkDefinitions($text) { - - $less_than_tab = $this->tab_width - 1; - - // Link defs are in the form: ^[id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 - [ ]* - \n? # maybe *one* newline - [ ]* - (?: - <(.+?)> # url = $2 - | - (\S+?) # url = $3 - ) - [ ]* - \n? # maybe one newline - [ ]* - (?: - (?<=\s) # lookbehind for whitespace - ["(] - (.*?) # title = $4 - [")] - [ ]* - )? # title is optional - (?:\n+|\Z) - }xm', - array($this, '_stripLinkDefinitions_callback'), - $text - ); - return $text; - } - - /** - * The callback to strip link definitions - * @param array $matches - * @return string - */ - protected function _stripLinkDefinitions_callback($matches) { - $link_id = strtolower($matches[1]); - $url = $matches[2] == '' ? $matches[3] : $matches[2]; - $this->urls[$link_id] = $url; - $this->titles[$link_id] =& $matches[4]; - return ''; // String that will replace the block - } - - /** - * Hashify HTML blocks - * @param string $text - * @return string - */ - protected function hashHTMLBlocks($text) { - if ($this->no_markup) { - return $text; - } - - $less_than_tab = $this->tab_width - 1; - - /** - * Hashify HTML blocks: - * - * We only want to do this for block-level HTML tags, such as headers, - * lists, and tables. That's because we still want to wrap

s around - * "paragraphs" that are wrapped in non-block-level tags, such as - * anchors, phrase emphasis, and spans. The list of tags we're looking - * for is hard-coded: - * - * * List "a" is made of tags which can be both inline or block-level. - * These will be treated block-level when the start tag is alone on - * its line, otherwise they're not matched here and will be taken as - * inline later. - * * List "b" is made of tags which are always block-level; - */ - $block_tags_a_re = 'ins|del'; - $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. - 'script|noscript|style|form|fieldset|iframe|math|svg|'. - 'article|section|nav|aside|hgroup|header|footer|'. - 'figure|details|summary'; - - // Regular expression for the content of a block tag. - $nested_tags_level = 4; - $attr = ' - (?> # optional tag attributes - \s # starts with whitespace - (?> - [^>"/]+ # text outside quotes - | - /+(?!>) # slash not followed by ">" - | - "[^"]*" # text inside double quotes (tolerate ">") - | - \'[^\']*\' # text inside single quotes (tolerate ">") - )* - )? - '; - $content = - str_repeat(' - (?> - [^<]+ # content without tag - | - <\2 # nested opening tag - '.$attr.' # attributes - (?> - /> - | - >', $nested_tags_level). // end of opening tag - '.*?'. // last level nested tag content - str_repeat(' - # closing nested tag - ) - | - <(?!/\2\s*> # other tags with a different name - ) - )*', - $nested_tags_level); - $content2 = str_replace('\2', '\3', $content); - - /** - * First, look for nested blocks, e.g.: - *

- *
- * tags for inner block must be indented. - *
- *
- * - * The outermost tags must start at the left margin for this to match, - * and the inner nested divs must be indented. - * We need to do this before the next, more liberal match, because the - * next match will start at the first `
` and stop at the - * first `
`. - */ - $text = preg_replace_callback('{(?> - (?> - (?<=\n) # Starting on its own line - | # or - \A\n? # the at beginning of the doc - ) - ( # save in $1 - - # Match from `\n` to `\n`, handling nested tags - # in between. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_b_re.')# start tag = $2 - '.$attr.'> # attributes followed by > and \n - '.$content.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special version for tags of group a. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_a_re.')# start tag = $3 - '.$attr.'>[ ]*\n # attributes followed by > - '.$content2.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special case just for
. It was easier to make a special - # case than to make the other regex more complicated. - - [ ]{0,'.$less_than_tab.'} - <(hr) # start tag = $2 - '.$attr.' # attributes - /?> # the matching end tag - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # Special case for standalone HTML comments: - - [ ]{0,'.$less_than_tab.'} - (?s: - - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # PHP and ASP-style processor instructions ( - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - ) - )}Sxmi', - array($this, '_hashHTMLBlocks_callback'), - $text - ); - - return $text; - } - - /** - * The callback for hashing HTML blocks - * @param string $matches - * @return string - */ - protected function _hashHTMLBlocks_callback($matches) { - $text = $matches[1]; - $key = $this->hashBlock($text); - return "\n\n$key\n\n"; - } - - /** - * Called whenever a tag must be hashed when a function insert an atomic - * element in the text stream. Passing $text to through this function gives - * a unique text-token which will be reverted back when calling unhash. - * - * The $boundary argument specify what character should be used to surround - * the token. By convension, "B" is used for block elements that needs not - * to be wrapped into paragraph tags at the end, ":" is used for elements - * that are word separators and "X" is used in the general case. - * - * @param string $text - * @param string $boundary - * @return string - */ - protected function hashPart($text, $boundary = 'X') { - // Swap back any tag hash found in $text so we do not have to `unhash` - // multiple times at the end. - $text = $this->unhash($text); - - // Then hash the block. - static $i = 0; - $key = "$boundary\x1A" . ++$i . $boundary; - $this->html_hashes[$key] = $text; - return $key; // String that will replace the tag. - } - - /** - * Shortcut function for hashPart with block-level boundaries. - * @param string $text - * @return string - */ - protected function hashBlock($text) { - return $this->hashPart($text, 'B'); - } - - /** - * Define the block gamut - these are all the transformations that form - * block-level tags like paragraphs, headers, and list items. - * @var array - */ - protected $block_gamut = array( - "doHeaders" => 10, - "doHorizontalRules" => 20, - "doLists" => 40, - "doCodeBlocks" => 50, - "doBlockQuotes" => 60, - ); - - /** - * Run block gamut tranformations. - * - * We need to escape raw HTML in Markdown source before doing anything - * else. This need to be done for each block, and not only at the - * begining in the Markdown function since hashed blocks can be part of - * list items and could have been indented. Indented blocks would have - * been seen as a code block in a previous pass of hashHTMLBlocks. - * - * @param string $text - * @return string - */ - protected function runBlockGamut($text) { - $text = $this->hashHTMLBlocks($text); - return $this->runBasicBlockGamut($text); - } - - /** - * Run block gamut tranformations, without hashing HTML blocks. This is - * useful when HTML blocks are known to be already hashed, like in the first - * whole-document pass. - * - * @param string $text - * @return string - */ - protected function runBasicBlockGamut($text) { - - foreach ($this->block_gamut as $method => $priority) { - $text = $this->$method($text); - } - - // Finally form paragraph and restore hashed blocks. - $text = $this->formParagraphs($text); - - return $text; - } - - /** - * Convert horizontal rules - * @param string $text - * @return string - */ - protected function doHorizontalRules($text) { - return preg_replace( - '{ - ^[ ]{0,3} # Leading space - ([-*_]) # $1: First marker - (?> # Repeated marker group - [ ]{0,2} # Zero, one, or two spaces. - \1 # Marker character - ){2,} # Group repeated at least twice - [ ]* # Tailing spaces - $ # End of line. - }mx', - "\n".$this->hashBlock("empty_element_suffix")."\n", - $text - ); - } - - /** - * These are all the transformations that occur *within* block-level - * tags like paragraphs, headers, and list items. - * @var array - */ - protected $span_gamut = array( - // Process character escapes, code spans, and inline HTML - // in one shot. - "parseSpan" => -30, - // Process anchor and image tags. Images must come first, - // because ![foo][f] looks like an anchor. - "doImages" => 10, - "doAnchors" => 20, - // Make links out of things like `` - // Must come after doAnchors, because you can use < and > - // delimiters in inline links like [this](). - "doAutoLinks" => 30, - "encodeAmpsAndAngles" => 40, - "doItalicsAndBold" => 50, - "doHardBreaks" => 60, - ); - - /** - * Run span gamut transformations - * @param string $text - * @return string - */ - protected function runSpanGamut($text) { - foreach ($this->span_gamut as $method => $priority) { - $text = $this->$method($text); - } - - return $text; - } - - /** - * Do hard breaks - * @param string $text - * @return string - */ - protected function doHardBreaks($text) { - if ($this->hard_wrap) { - return preg_replace_callback('/ *\n/', - array($this, '_doHardBreaks_callback'), $text); - } else { - return preg_replace_callback('/ {2,}\n/', - array($this, '_doHardBreaks_callback'), $text); - } - } - - /** - * Trigger part hashing for the hard break (callback method) - * @param array $matches - * @return string - */ - protected function _doHardBreaks_callback($matches) { - return $this->hashPart("empty_element_suffix\n"); - } - - /** - * Turn Markdown link shortcuts into XHTML tags. - * @param string $text - * @return string - */ - protected function doAnchors($text) { - if ($this->in_anchor) { - return $text; - } - $this->in_anchor = true; - - // First, handle reference-style links: [link text] [id] - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - ) - }xs', - array($this, '_doAnchors_reference_callback'), $text); - - // Next, inline-style links: [link text](url "optional title") - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - \( # literal paren - [ \n]* - (?: - <(.+?)> # href = $3 - | - ('.$this->nested_url_parenthesis_re.') # href = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # Title = $7 - \6 # matching quote - [ \n]* # ignore any spaces/tabs between closing quote and ) - )? # title is optional - \) - ) - }xs', - array($this, '_doAnchors_inline_callback'), $text); - - // Last, handle reference-style shortcuts: [link text] - // These must come last in case you've also got [link text][1] - // or [link text](/foo) - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ([^\[\]]+) # link text = $2; can\'t contain [ or ] - \] - ) - }xs', - array($this, '_doAnchors_reference_callback'), $text); - - $this->in_anchor = false; - return $text; - } - - /** - * Callback method to parse referenced anchors - * @param string $matches - * @return string - */ - protected function _doAnchors_reference_callback($matches) { - $whole_match = $matches[1]; - $link_text = $matches[2]; - $link_id =& $matches[3]; - - if ($link_id == "") { - // for shortcut links like [this][] or [this]. - $link_id = $link_text; - } - - // lower-case and turn embedded newlines into spaces - $link_id = strtolower($link_id); - $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); - - if (isset($this->urls[$link_id])) { - $url = $this->urls[$link_id]; - $url = $this->encodeURLAttribute($url); - - $result = "titles[$link_id] ) ) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - $result = $this->hashPart($result); - } else { - $result = $whole_match; - } - return $result; - } - - /** - * Callback method to parse inline anchors - * @param string $matches - * @return string - */ - protected function _doAnchors_inline_callback($matches) { - $link_text = $this->runSpanGamut($matches[2]); - $url = $matches[3] === '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - // If the URL was of the form it got caught by the HTML - // tag parser and hashed. Need to reverse the process before using - // the URL. - $unhashed = $this->unhash($url); - if ($unhashed !== $url) - $url = preg_replace('/^<(.*)>$/', '\1', $unhashed); - - $url = $this->encodeURLAttribute($url); - - $result = "encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - - return $this->hashPart($result); - } - - /** - * Turn Markdown image shortcuts into tags. - * @param string $text - * @return string - */ - protected function doImages($text) { - // First, handle reference-style labeled images: ![alt text][id] - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - - ) - }xs', - array($this, '_doImages_reference_callback'), $text); - - // Next, handle inline images: ![alt text](url "optional title") - // Don't forget: encode * and _ - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - \s? # One optional whitespace character - \( # literal paren - [ \n]* - (?: - <(\S*)> # src url = $3 - | - ('.$this->nested_url_parenthesis_re.') # src url = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # title = $7 - \6 # matching quote - [ \n]* - )? # title is optional - \) - ) - }xs', - array($this, '_doImages_inline_callback'), $text); - - return $text; - } - - /** - * Callback to parse references image tags - * @param array $matches - * @return string - */ - protected function _doImages_reference_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $link_id = strtolower($matches[3]); - - if ($link_id == "") { - $link_id = strtolower($alt_text); // for shortcut links like ![this][]. - } - - $alt_text = $this->encodeAttribute($alt_text); - if (isset($this->urls[$link_id])) { - $url = $this->encodeURLAttribute($this->urls[$link_id]); - $result = "\"$alt_text\"";titles[$link_id])) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - $result .= $this->empty_element_suffix; - $result = $this->hashPart($result); - } else { - // If there's no such link ID, leave intact: - $result = $whole_match; - } - - return $result; - } - - /** - * Callback to parse inline image tags - * @param array $matches - * @return string - */ - protected function _doImages_inline_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $alt_text = $this->encodeAttribute($alt_text); - $url = $this->encodeURLAttribute($url); - $result = "\"$alt_text\"";encodeAttribute($title); - $result .= " title=\"$title\""; // $title already quoted - } - $result .= $this->empty_element_suffix; - - return $this->hashPart($result); - } - - /** - * Parse Markdown heading elements to HTML - * @param string $text - * @return string - */ - protected function doHeaders($text) { - /** - * Setext-style headers: - * Header 1 - * ======== - * - * Header 2 - * -------- - */ - $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', - array($this, '_doHeaders_callback_setext'), $text); - - /** - * atx-style headers: - * # Header 1 - * ## Header 2 - * ## Header 2 with closing hashes ## - * ... - * ###### Header 6 - */ - $text = preg_replace_callback('{ - ^(\#{1,6}) # $1 = string of #\'s - [ ]* - (.+?) # $2 = Header text - [ ]* - \#* # optional closing #\'s (not counted) - \n+ - }xm', - array($this, '_doHeaders_callback_atx'), $text); - - return $text; - } - - /** - * Setext header parsing callback - * @param array $matches - * @return string - */ - protected function _doHeaders_callback_setext($matches) { - // Terrible hack to check we haven't found an empty list item. - if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) { - return $matches[0]; - } - - $level = $matches[2][0] == '=' ? 1 : 2; - - // ID attribute generation - $idAtt = $this->_generateIdFromHeaderValue($matches[1]); - - $block = "".$this->runSpanGamut($matches[1]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - /** - * ATX header parsing callback - * @param array $matches - * @return string - */ - protected function _doHeaders_callback_atx($matches) { - // ID attribute generation - $idAtt = $this->_generateIdFromHeaderValue($matches[2]); - - $level = strlen($matches[1]); - $block = "".$this->runSpanGamut($matches[2]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - /** - * If a header_id_func property is set, we can use it to automatically - * generate an id attribute. - * - * This method returns a string in the form id="foo", or an empty string - * otherwise. - * @param string $headerValue - * @return string - */ - protected function _generateIdFromHeaderValue($headerValue) { - if (!is_callable($this->header_id_func)) { - return ""; - } - - $idValue = call_user_func($this->header_id_func, $headerValue); - if (!$idValue) { - return ""; - } - - return ' id="' . $this->encodeAttribute($idValue) . '"'; - } - - /** - * Form HTML ordered (numbered) and unordered (bulleted) lists. - * @param string $text - * @return string - */ - protected function doLists($text) { - $less_than_tab = $this->tab_width - 1; - - // Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - - $markers_relist = array( - $marker_ul_re => $marker_ol_re, - $marker_ol_re => $marker_ul_re, - ); - - foreach ($markers_relist as $marker_re => $other_marker_re) { - // Re-usable pattern to match any entirel ul or ol list: - $whole_list_re = ' - ( # $1 = whole list - ( # $2 - ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces - ('.$marker_re.') # $4 = first list item marker - [ ]+ - ) - (?s:.+?) - ( # $5 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another list item marker - [ ]* - '.$marker_re.'[ ]+ - ) - | - (?= # Lookahead for another kind of list - \n - \3 # Must have the same indentation - '.$other_marker_re.'[ ]+ - ) - ) - ) - '; // mx - - // We use a different prefix before nested lists than top-level lists. - //See extended comment in _ProcessListItems(). - - if ($this->list_level) { - $text = preg_replace_callback('{ - ^ - '.$whole_list_re.' - }mx', - array($this, '_doLists_callback'), $text); - } else { - $text = preg_replace_callback('{ - (?:(?<=\n)\n|\A\n?) # Must eat the newline - '.$whole_list_re.' - }mx', - array($this, '_doLists_callback'), $text); - } - } - - return $text; - } - - /** - * List parsing callback - * @param array $matches - * @return string - */ - protected function _doLists_callback($matches) { - // Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - $marker_ol_start_re = '[0-9]+'; - - $list = $matches[1]; - $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; - - $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); - - $list .= "\n"; - $result = $this->processListItems($list, $marker_any_re); - - $ol_start = 1; - if ($this->enhanced_ordered_list) { - // Get the start number for ordered list. - if ($list_type == 'ol') { - $ol_start_array = array(); - $ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array); - if ($ol_start_check){ - $ol_start = $ol_start_array[0]; - } - } - } - - if ($ol_start > 1 && $list_type == 'ol'){ - $result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . ""); - } else { - $result = $this->hashBlock("<$list_type>\n" . $result . ""); - } - return "\n". $result ."\n\n"; - } - - /** - * Nesting tracker for list levels - * @var integer - */ - protected $list_level = 0; - - /** - * Process the contents of a single ordered or unordered list, splitting it - * into individual list items. - * @param string $list_str - * @param string $marker_any_re - * @return string - */ - protected function processListItems($list_str, $marker_any_re) { - /** - * The $this->list_level global keeps track of when we're inside a list. - * Each time we enter a list, we increment it; when we leave a list, - * we decrement. If it's zero, we're not in a list anymore. - * - * We do this because when we're not inside a list, we want to treat - * something like this: - * - * I recommend upgrading to version - * 8. Oops, now this line is treated - * as a sub-list. - * - * As a single paragraph, despite the fact that the second line starts - * with a digit-period-space sequence. - * - * Whereas when we're inside a list (or sub-list), that line will be - * treated as the start of a sub-list. What a kludge, huh? This is - * an aspect of Markdown's syntax that's hard to parse perfectly - * without resorting to mind-reading. Perhaps the solution is to - * change the syntax rules such that sub-lists must start with a - * starting cardinal number; e.g. "1." or "a.". - */ - $this->list_level++; - - // Trim trailing blank lines: - $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); - - $list_str = preg_replace_callback('{ - (\n)? # leading line = $1 - (^[ ]*) # leading whitespace = $2 - ('.$marker_any_re.' # list marker and space = $3 - (?:[ ]+|(?=\n)) # space only required if item is not empty - ) - ((?s:.*?)) # list item text = $4 - (?:(\n+(?=\n))|\n) # tailing blank line = $5 - (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) - }xm', - array($this, '_processListItems_callback'), $list_str); - - $this->list_level--; - return $list_str; - } - - /** - * List item parsing callback - * @param array $matches - * @return string - */ - protected function _processListItems_callback($matches) { - $item = $matches[4]; - $leading_line =& $matches[1]; - $leading_space =& $matches[2]; - $marker_space = $matches[3]; - $tailing_blank_line =& $matches[5]; - - if ($leading_line || $tailing_blank_line || - preg_match('/\n{2,}/', $item)) - { - // Replace marker with the appropriate whitespace indentation - $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; - $item = $this->runBlockGamut($this->outdent($item)."\n"); - } else { - // Recursion for sub-lists: - $item = $this->doLists($this->outdent($item)); - $item = $this->formParagraphs($item, false); - } - - return "
  • " . $item . "
  • \n"; - } - - /** - * Process Markdown `
    ` blocks.
    -	 * @param  string $text
    -	 * @return string
    -	 */
    -	protected function doCodeBlocks($text) {
    -		$text = preg_replace_callback('{
    -				(?:\n\n|\A\n?)
    -				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    -				  (?>
    -					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    -					.*\n+
    -				  )+
    -				)
    -				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    -			}xm',
    -			array($this, '_doCodeBlocks_callback'), $text);
    -
    -		return $text;
    -	}
    -
    -	/**
    -	 * Code block parsing callback
    -	 * @param  array $matches
    -	 * @return string
    -	 */
    -	protected function _doCodeBlocks_callback($matches) {
    -		$codeblock = $matches[1];
    -
    -		$codeblock = $this->outdent($codeblock);
    -		if (is_callable($this->code_block_content_func)) {
    -			$codeblock = call_user_func($this->code_block_content_func, $codeblock, "");
    -		} else {
    -			$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    -		}
    -
    -		# trim leading newlines and trailing newlines
    -		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    -
    -		$codeblock = "
    $codeblock\n
    "; - return "\n\n" . $this->hashBlock($codeblock) . "\n\n"; - } - - /** - * Create a code span markup for $code. Called from handleSpanToken. - * @param string $code - * @return string - */ - protected function makeCodeSpan($code) { - if (is_callable($this->code_span_content_func)) { - $code = call_user_func($this->code_span_content_func, $code); - } else { - $code = htmlspecialchars(trim($code), ENT_NOQUOTES); - } - return $this->hashPart("$code"); - } - - /** - * Define the emphasis operators with their regex matches - * @var array - */ - protected $em_relist = array( - '' => '(?:(? '(? '(? '(?:(? '(? '(? '(?:(? '(? '(?em_relist as $em => $em_re) { - foreach ($this->strong_relist as $strong => $strong_re) { - // Construct list of allowed token expressions. - $token_relist = array(); - if (isset($this->em_strong_relist["$em$strong"])) { - $token_relist[] = $this->em_strong_relist["$em$strong"]; - } - $token_relist[] = $em_re; - $token_relist[] = $strong_re; - - // Construct master expression from list. - $token_re = '{(' . implode('|', $token_relist) . ')}'; - $this->em_strong_prepared_relist["$em$strong"] = $token_re; - } - } - } - - /** - * Convert Markdown italics (emphasis) and bold (strong) to HTML - * @param string $text - * @return string - */ - protected function doItalicsAndBold($text) { - if ($this->in_emphasis_processing) { - return $text; // avoid reentrency - } - $this->in_emphasis_processing = true; - - $token_stack = array(''); - $text_stack = array(''); - $em = ''; - $strong = ''; - $tree_char_em = false; - - while (1) { - // Get prepared regular expression for seraching emphasis tokens - // in current context. - $token_re = $this->em_strong_prepared_relist["$em$strong"]; - - // Each loop iteration search for the next emphasis token. - // Each token is then passed to handleSpanToken. - $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); - $text_stack[0] .= $parts[0]; - $token =& $parts[1]; - $text =& $parts[2]; - - if (empty($token)) { - // Reached end of text span: empty stack without emitting. - // any more emphasis. - while ($token_stack[0]) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - break; - } - - $token_len = strlen($token); - if ($tree_char_em) { - // Reached closing marker while inside a three-char emphasis. - if ($token_len == 3) { - // Three-char closing marker, close em and strong. - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - $strong = ''; - } else { - // Other closing marker: close one em or strong and - // change current token state to match the other - $token_stack[0] = str_repeat($token[0], 3-$token_len); - $tag = $token_len == 2 ? "strong" : "em"; - $span = $text_stack[0]; - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] = $this->hashPart($span); - $$tag = ''; // $$tag stands for $em or $strong - } - $tree_char_em = false; - } else if ($token_len == 3) { - if ($em) { - // Reached closing marker for both em and strong. - // Closing strong marker: - for ($i = 0; $i < 2; ++$i) { - $shifted_token = array_shift($token_stack); - $tag = strlen($shifted_token) == 2 ? "strong" : "em"; - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] .= $this->hashPart($span); - $$tag = ''; // $$tag stands for $em or $strong - } - } else { - // Reached opening three-char emphasis marker. Push on token - // stack; will be handled by the special condition above. - $em = $token[0]; - $strong = "$em$em"; - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $tree_char_em = true; - } - } else if ($token_len == 2) { - if ($strong) { - // Unwind any dangling emphasis marker: - if (strlen($token_stack[0]) == 1) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - $em = ''; - } - // Closing strong marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $strong = ''; - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $strong = $token; - } - } else { - // Here $token_len == 1 - if ($em) { - if (strlen($token_stack[0]) == 1) { - // Closing emphasis marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - } else { - $text_stack[0] .= $token; - } - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $em = $token; - } - } - } - $this->in_emphasis_processing = false; - return $text_stack[0]; - } - - /** - * Parse Markdown blockquotes to HTML - * @param string $text - * @return string - */ - protected function doBlockQuotes($text) { - $text = preg_replace_callback('/ - ( # Wrap whole match in $1 - (?> - ^[ ]*>[ ]? # ">" at the start of a line - .+\n # rest of the first line - (.+\n)* # subsequent consecutive lines - \n* # blanks - )+ - ) - /xm', - array($this, '_doBlockQuotes_callback'), $text); - - return $text; - } - - /** - * Blockquote parsing callback - * @param array $matches - * @return string - */ - protected function _doBlockQuotes_callback($matches) { - $bq = $matches[1]; - // trim one level of quoting - trim whitespace-only lines - $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); - $bq = $this->runBlockGamut($bq); // recurse - - $bq = preg_replace('/^/m', " ", $bq); - // These leading spaces cause problem with
     content,
    -		// so we need to fix that:
    -		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', - array($this, '_doBlockQuotes_callback2'), $bq); - - return "\n" . $this->hashBlock("
    \n$bq\n
    ") . "\n\n"; - } - - /** - * Blockquote parsing callback - * @param array $matches - * @return string - */ - protected function _doBlockQuotes_callback2($matches) { - $pre = $matches[1]; - $pre = preg_replace('/^ /m', '', $pre); - return $pre; - } - - /** - * Parse paragraphs - * - * @param string $text String to process in paragraphs - * @param boolean $wrap_in_p Whether paragraphs should be wrapped in

    tags - * @return string - */ - protected function formParagraphs($text, $wrap_in_p = true) { - // Strip leading and trailing lines: - $text = preg_replace('/\A\n+|\n+\z/', '', $text); - - $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); - - // Wrap

    tags and unhashify HTML blocks - foreach ($grafs as $key => $value) { - if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { - // Is a paragraph. - $value = $this->runSpanGamut($value); - if ($wrap_in_p) { - $value = preg_replace('/^([ ]*)/', "

    ", $value); - $value .= "

    "; - } - $grafs[$key] = $this->unhash($value); - } else { - // Is a block. - // Modify elements of @grafs in-place... - $graf = $value; - $block = $this->html_hashes[$graf]; - $graf = $block; -// if (preg_match('{ -// \A -// ( # $1 =
    tag -//
    ]* -// \b -// markdown\s*=\s* ([\'"]) # $2 = attr quote char -// 1 -// \2 -// [^>]* -// > -// ) -// ( # $3 = contents -// .* -// ) -// (
    ) # $4 = closing tag -// \z -// }xs', $block, $matches)) -// { -// list(, $div_open, , $div_content, $div_close) = $matches; -// -// // We can't call Markdown(), because that resets the hash; -// // that initialization code should be pulled into its own sub, though. -// $div_content = $this->hashHTMLBlocks($div_content); -// -// // Run document gamut methods on the content. -// foreach ($this->document_gamut as $method => $priority) { -// $div_content = $this->$method($div_content); -// } -// -// $div_open = preg_replace( -// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); -// -// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; -// } - $grafs[$key] = $graf; - } - } - - return implode("\n\n", $grafs); - } - - /** - * Encode text for a double-quoted HTML attribute. This function - * is *not* suitable for attributes enclosed in single quotes. - * @param string $text - * @return string - */ - protected function encodeAttribute($text) { - $text = $this->encodeAmpsAndAngles($text); - $text = str_replace('"', '"', $text); - return $text; - } - - /** - * Encode text for a double-quoted HTML attribute containing a URL, - * applying the URL filter if set. Also generates the textual - * representation for the URL (removing mailto: or tel:) storing it in $text. - * This function is *not* suitable for attributes enclosed in single quotes. - * - * @param string $url - * @param string $text Passed by reference - * @return string URL - */ - protected function encodeURLAttribute($url, &$text = null) { - if (is_callable($this->url_filter_func)) { - $url = call_user_func($this->url_filter_func, $url); - } - - if (preg_match('{^mailto:}i', $url)) { - $url = $this->encodeEntityObfuscatedAttribute($url, $text, 7); - } else if (preg_match('{^tel:}i', $url)) { - $url = $this->encodeAttribute($url); - $text = substr($url, 4); - } else { - $url = $this->encodeAttribute($url); - $text = $url; - } - - return $url; - } - - /** - * Smart processing for ampersands and angle brackets that need to - * be encoded. Valid character entities are left alone unless the - * no-entities mode is set. - * @param string $text - * @return string - */ - protected function encodeAmpsAndAngles($text) { - if ($this->no_entities) { - $text = str_replace('&', '&', $text); - } else { - // Ampersand-encoding based entirely on Nat Irons's Amputator - // MT plugin: - $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', - '&', $text); - } - // Encode remaining <'s - $text = str_replace('<', '<', $text); - - return $text; - } - - /** - * Parse Markdown automatic links to anchor HTML tags - * @param string $text - * @return string - */ - protected function doAutoLinks($text) { - $text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i', - array($this, '_doAutoLinks_url_callback'), $text); - - // Email addresses: - $text = preg_replace_callback('{ - < - (?:mailto:)? - ( - (?: - [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ - | - ".*?" - ) - \@ - (?: - [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ - | - \[[\d.a-fA-F:]+\] # IPv4 & IPv6 - ) - ) - > - }xi', - array($this, '_doAutoLinks_email_callback'), $text); - - return $text; - } - - /** - * Parse URL callback - * @param array $matches - * @return string - */ - protected function _doAutoLinks_url_callback($matches) { - $url = $this->encodeURLAttribute($matches[1], $text); - $link = "$text"; - return $this->hashPart($link); - } - - /** - * Parse email address callback - * @param array $matches - * @return string - */ - protected function _doAutoLinks_email_callback($matches) { - $addr = $matches[1]; - $url = $this->encodeURLAttribute("mailto:$addr", $text); - $link = "$text"; - return $this->hashPart($link); - } - - /** - * Input: some text to obfuscate, e.g. "mailto:foo@example.com" - * - * Output: the same text but with most characters encoded as either a - * decimal or hex entity, in the hopes of foiling most address - * harvesting spam bots. E.g.: - * - * mailto:foo - * @example.co - * m - * - * Note: the additional output $tail is assigned the same value as the - * ouput, minus the number of characters specified by $head_length. - * - * Based by a filter by Matthew Wickline, posted to BBEdit-Talk. - * With some optimizations by Milian Wolff. Forced encoding of HTML - * attribute special characters by Allan Odgaard. - * - * @param string $text - * @param string $tail Passed by reference - * @param integer $head_length - * @return string - */ - protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) { - if ($text == "") { - return $tail = ""; - } - - $chars = preg_split('/(? $char) { - $ord = ord($char); - // Ignore non-ascii chars. - if ($ord < 128) { - $r = ($seed * (1 + $key)) % 100; // Pseudo-random function. - // roughly 10% raw, 45% hex, 45% dec - // '@' *must* be encoded. I insist. - // '"' and '>' have to be encoded inside the attribute - if ($r > 90 && strpos('@"&>', $char) === false) { - /* do nothing */ - } else if ($r < 45) { - $chars[$key] = '&#x'.dechex($ord).';'; - } else { - $chars[$key] = '&#'.$ord.';'; - } - } - } - - $text = implode('', $chars); - $tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text; - - return $text; - } - - /** - * Take the string $str and parse it into tokens, hashing embeded HTML, - * escaped characters and handling code spans. - * @param string $str - * @return string - */ - protected function parseSpan($str) { - $output = ''; - - $span_re = '{ - ( - \\\\'.$this->escape_chars_re.' - | - (?no_markup ? '' : ' - | - # comment - | - <\?.*?\?> | <%.*?%> # processing instruction - | - <[!$]?[-a-zA-Z0-9:_]+ # regular tags - (?> - \s - (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* - )? - > - | - <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag - | - # closing tag - ').' - ) - }xs'; - - while (1) { - // Each loop iteration seach for either the next tag, the next - // openning code span marker, or the next escaped character. - // Each token is then passed to handleSpanToken. - $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); - - // Create token from text preceding tag. - if ($parts[0] != "") { - $output .= $parts[0]; - } - - // Check if we reach the end. - if (isset($parts[1])) { - $output .= $this->handleSpanToken($parts[1], $parts[2]); - $str = $parts[2]; - } else { - break; - } - } - - return $output; - } - - /** - * Handle $token provided by parseSpan by determining its nature and - * returning the corresponding value that should replace it. - * @param string $token - * @param string $str Passed by reference - * @return string - */ - protected function handleSpanToken($token, &$str) { - switch ($token[0]) { - case "\\": - return $this->hashPart("&#". ord($token[1]). ";"); - case "`": - // Search for end marker in remaining text. - if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', - $str, $matches)) - { - $str = $matches[2]; - $codespan = $this->makeCodeSpan($matches[1]); - return $this->hashPart($codespan); - } - return $token; // Return as text since no ending marker found. - default: - return $this->hashPart($token); - } - } - - /** - * Remove one level of line-leading tabs or spaces - * @param string $text - * @return string - */ - protected function outdent($text) { - return preg_replace('/^(\t|[ ]{1,' . $this->tab_width . '})/m', '', $text); - } - - - /** - * String length function for detab. `_initDetab` will create a function to - * handle UTF-8 if the default function does not exist. - * @var string - */ - protected $utf8_strlen = 'mb_strlen'; - - /** - * Replace tabs with the appropriate amount of spaces. - * - * For each line we separate the line in blocks delemited by tab characters. - * Then we reconstruct every line by adding the appropriate number of space - * between each blocks. - * - * @param string $text - * @return string - */ - protected function detab($text) { - $text = preg_replace_callback('/^.*\t.*$/m', - array($this, '_detab_callback'), $text); - - return $text; - } - - /** - * Replace tabs callback - * @param string $matches - * @return string - */ - protected function _detab_callback($matches) { - $line = $matches[0]; - $strlen = $this->utf8_strlen; // strlen function for UTF-8. - - // Split in blocks. - $blocks = explode("\t", $line); - // Add each blocks to the line. - $line = $blocks[0]; - unset($blocks[0]); // Do not add first block twice. - foreach ($blocks as $block) { - // Calculate amount of space, insert spaces, insert block. - $amount = $this->tab_width - - $strlen($line, 'UTF-8') % $this->tab_width; - $line .= str_repeat(" ", $amount) . $block; - } - return $line; - } - - /** - * Check for the availability of the function in the `utf8_strlen` property - * (initially `mb_strlen`). If the function is not available, create a - * function that will loosely count the number of UTF-8 characters with a - * regular expression. - * @return void - */ - protected function _initDetab() { - - if (function_exists($this->utf8_strlen)) { - return; - } - - $this->utf8_strlen = function($text) { - return preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m); - }; - } - - /** - * Swap back in all the tags hashed by _HashHTMLBlocks. - * @param string $text - * @return string - */ - protected function unhash($text) { - return preg_replace_callback('/(.)\x1A[0-9]+\1/', - array($this, '_unhash_callback'), $text); - } - - /** - * Unhashing callback - * @param array $matches - * @return string - */ - protected function _unhash_callback($matches) { - return $this->html_hashes[$matches[0]]; - } -} diff --git a/md/MarkdownExtra.inc.php b/md/MarkdownExtra.inc.php deleted file mode 100755 index d09bd7a..0000000 --- a/md/MarkdownExtra.inc.php +++ /dev/null @@ -1,11 +0,0 @@ - - * @copyright 2004-2019 Michel Fortin - * @copyright (Original Markdown) 2004-2006 John Gruber - */ - -namespace md; - -/** - * Markdown Extra Parser Class - */ -class MarkdownExtra extends \md\Markdown { - /** - * Configuration variables - */ - - /** - * Prefix for footnote ids. - * @var string - */ - public $fn_id_prefix = ""; - - /** - * Optional title attribute for footnote links. - * @var string - */ - public $fn_link_title = ""; - - /** - * Optional class attribute for footnote links and backlinks. - * @var string - */ - public $fn_link_class = "footnote-ref"; - public $fn_backlink_class = "footnote-backref"; - - /** - * Content to be displayed within footnote backlinks. The default is '↩'; - * the U+FE0E on the end is a Unicode variant selector used to prevent iOS - * from displaying the arrow character as an emoji. - * Optionally use '^^' and '%%' to refer to the footnote number and - * reference number respectively. {@see parseFootnotePlaceholders()} - * @var string - */ - public $fn_backlink_html = '↩︎'; - - /** - * Optional title and aria-label attributes for footnote backlinks for - * added accessibility (to ensure backlink uniqueness). - * Use '^^' and '%%' to refer to the footnote number and reference number - * respectively. {@see parseFootnotePlaceholders()} - * @var string - */ - public $fn_backlink_title = ""; - public $fn_backlink_label = ""; - - /** - * Class name for table cell alignment (%% replaced left/center/right) - * For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center' - * If empty, the align attribute is used instead of a class name. - * @var string - */ - public $table_align_class_tmpl = ''; - - /** - * Optional class prefix for fenced code block. - * @var string - */ - public $code_class_prefix = ""; - - /** - * Class attribute for code blocks goes on the `code` tag; - * setting this to true will put attributes on the `pre` tag instead. - * @var boolean - */ - public $code_attr_on_pre = false; - - /** - * Predefined abbreviations. - * @var array - */ - public $predef_abbr = array(); - - /** - * Only convert atx-style headers if there's a space between the header and # - * @var boolean - */ - public $hashtag_protection = false; - - /** - * Determines whether footnotes should be appended to the end of the document. - * If true, footnote html can be retrieved from $this->footnotes_assembled. - * @var boolean - */ - public $omit_footnotes = false; - - - /** - * After parsing, the HTML for the list of footnotes appears here. - * This is available only if $omit_footnotes == true. - * - * Note: when placing the content of `footnotes_assembled` on the page, - * consider adding the attribute `role="doc-endnotes"` to the `div` or - * `section` that will enclose the list of footnotes so they are - * reachable to accessibility tools the same way they would be with the - * default HTML output. - * @var null|string - */ - public $footnotes_assembled = null; - - /** - * Parser implementation - */ - - /** - * Constructor function. Initialize the parser object. - * @return void - */ - public function __construct() { - // Add extra escapable characters before parent constructor - // initialize the table. - $this->escape_chars .= ':|'; - - // Insert extra document, block, and span transformations. - // Parent constructor will do the sorting. - $this->document_gamut += array( - "doFencedCodeBlocks" => 5, - "stripFootnotes" => 15, - "stripAbbreviations" => 25, - "appendFootnotes" => 50, - ); - $this->block_gamut += array( - "doFencedCodeBlocks" => 5, - "doTables" => 15, - "doDefLists" => 45, - ); - $this->span_gamut += array( - "doFootnotes" => 5, - "doAbbreviations" => 70, - ); - - $this->enhanced_ordered_list = true; - parent::__construct(); - } - - - /** - * Extra variables used during extra transformations. - * @var array - */ - protected $footnotes = array(); - protected $footnotes_ordered = array(); - protected $footnotes_ref_count = array(); - protected $footnotes_numbers = array(); - protected $abbr_desciptions = array(); - /** @var string */ - protected $abbr_word_re = ''; - - /** - * Give the current footnote number. - * @var integer - */ - protected $footnote_counter = 1; - - /** - * Ref attribute for links - * @var array - */ - protected $ref_attr = array(); - - /** - * Setting up Extra-specific variables. - */ - protected function setup() { - parent::setup(); - - $this->footnotes = array(); - $this->footnotes_ordered = array(); - $this->footnotes_ref_count = array(); - $this->footnotes_numbers = array(); - $this->abbr_desciptions = array(); - $this->abbr_word_re = ''; - $this->footnote_counter = 1; - $this->footnotes_assembled = null; - - foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { - if ($this->abbr_word_re) - $this->abbr_word_re .= '|'; - $this->abbr_word_re .= preg_quote($abbr_word); - $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); - } - } - - /** - * Clearing Extra-specific variables. - */ - protected function teardown() { - $this->footnotes = array(); - $this->footnotes_ordered = array(); - $this->footnotes_ref_count = array(); - $this->footnotes_numbers = array(); - $this->abbr_desciptions = array(); - $this->abbr_word_re = ''; - - if ( ! $this->omit_footnotes ) - $this->footnotes_assembled = null; - - parent::teardown(); - } - - - /** - * Extra attribute parser - */ - - /** - * Expression to use to catch attributes (includes the braces) - * @var string - */ - protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}'; - - /** - * Expression to use when parsing in a context when no capture is desired - * @var string - */ - protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}'; - - /** - * Parse attributes caught by the $this->id_class_attr_catch_re expression - * and return the HTML-formatted list of attributes. - * - * Currently supported attributes are .class and #id. - * - * In addition, this method also supports supplying a default Id value, - * which will be used to populate the id attribute in case it was not - * overridden. - * @param string $tag_name - * @param string $attr - * @param mixed $defaultIdValue - * @param array $classes - * @return string - */ - protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) { - if (empty($attr) && !$defaultIdValue && empty($classes)) { - return ""; - } - - // Split on components - preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches); - $elements = $matches[0]; - - // Handle classes and IDs (only first ID taken into account) - $attributes = array(); - $id = false; - foreach ($elements as $element) { - if ($element[0] === '.') { - $classes[] = substr($element, 1); - } else if ($element[0] === '#') { - if ($id === false) $id = substr($element, 1); - } else if (strpos($element, '=') > 0) { - $parts = explode('=', $element, 2); - $attributes[] = $parts[0] . '="' . $parts[1] . '"'; - } - } - - if ($id === false || $id === '') { - $id = $defaultIdValue; - } - - // Compose attributes as string - $attr_str = ""; - if (!empty($id)) { - $attr_str .= ' id="'.$this->encodeAttribute($id) .'"'; - } - if (!empty($classes)) { - $attr_str .= ' class="'. implode(" ", $classes) . '"'; - } - if (!$this->no_markup && !empty($attributes)) { - $attr_str .= ' '.implode(" ", $attributes); - } - return $attr_str; - } - - /** - * Strips link definitions from text, stores the URLs and titles in - * hash references. - * @param string $text - * @return string - */ - protected function stripLinkDefinitions($text) { - $less_than_tab = $this->tab_width - 1; - - // Link defs are in the form: ^[id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 - [ ]* - \n? # maybe *one* newline - [ ]* - (?: - <(.+?)> # url = $2 - | - (\S+?) # url = $3 - ) - [ ]* - \n? # maybe one newline - [ ]* - (?: - (?<=\s) # lookbehind for whitespace - ["(] - (.*?) # title = $4 - [")] - [ ]* - )? # title is optional - (?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr - (?:\n+|\Z) - }xm', - array($this, '_stripLinkDefinitions_callback'), - $text); - return $text; - } - - /** - * Strip link definition callback - * @param array $matches - * @return string - */ - protected function _stripLinkDefinitions_callback($matches) { - $link_id = strtolower($matches[1]); - $url = $matches[2] == '' ? $matches[3] : $matches[2]; - $this->urls[$link_id] = $url; - $this->titles[$link_id] =& $matches[4]; - $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]); - return ''; // String that will replace the block - } - - - /** - * HTML block parser - */ - - /** - * Tags that are always treated as block tags - * @var string - */ - protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure|details|summary'; - - /** - * Tags treated as block tags only if the opening tag is alone on its line - * @var string - */ - protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; - - /** - * Tags where markdown="1" default to span mode: - * @var string - */ - protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; - - /** - * Tags which must not have their contents modified, no matter where - * they appear - * @var string - */ - protected $clean_tags_re = 'script|style|math|svg'; - - /** - * Tags that do not need to be closed. - * @var string - */ - protected $auto_close_tags_re = 'hr|img|param|source|track'; - - /** - * Hashify HTML Blocks and "clean tags". - * - * We only want to do this for block-level HTML tags, such as headers, - * lists, and tables. That's because we still want to wrap

    s around - * "paragraphs" that are wrapped in non-block-level tags, such as anchors, - * phrase emphasis, and spans. The list of tags we're looking for is - * hard-coded. - * - * This works by calling _HashHTMLBlocks_InMarkdown, which then calls - * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" - * attribute is found within a tag, _HashHTMLBlocks_InHTML calls back - * _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. - * These two functions are calling each other. It's recursive! - * @param string $text - * @return string - */ - protected function hashHTMLBlocks($text) { - if ($this->no_markup) { - return $text; - } - - // Call the HTML-in-Markdown hasher. - list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); - - return $text; - } - - /** - * Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. - * - * * $indent is the number of space to be ignored when checking for code - * blocks. This is important because if we don't take the indent into - * account, something like this (which looks right) won't work as expected: - * - *

    - *
    - * Hello World. <-- Is this a Markdown code block or text? - *
    <-- Is this a Markdown code block or a real tag? - *
    - * - * If you don't like this, just don't indent the tag on which - * you apply the markdown="1" attribute. - * - * * If $enclosing_tag_re is not empty, stops at the first unmatched closing - * tag with that name. Nested tags supported. - * - * * If $span is true, text inside must treated as span. So any double - * newline will be replaced by a single newline so that it does not create - * paragraphs. - * - * Returns an array of that form: ( processed text , remaining text ) - * - * @param string $text - * @param integer $indent - * @param string $enclosing_tag_re - * @param boolean $span - * @return array - */ - protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0, - $enclosing_tag_re = '', $span = false) - { - - if ($text === '') return array('', ''); - - // Regex to check for the presense of newlines around a block tag. - $newline_before_re = '/(?:^\n?|\n\n)*$/'; - $newline_after_re = - '{ - ^ # Start of text following the tag. - (?>[ ]*)? # Optional comment. - [ ]*\n # Must be followed by newline. - }xs'; - - // Regex to match any tag. - $block_tag_re = - '{ - ( # $2: Capture whole tag. - # Tag name. - ' . $this->block_tags_re . ' | - ' . $this->context_block_tags_re . ' | - ' . $this->clean_tags_re . ' | - (?!\s)'.$enclosing_tag_re . ' - ) - (?: - (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. - (?> - ".*?" | # Double quotes (can contain `>`) - \'.*?\' | # Single quotes (can contain `>`) - .+? # Anything but quotes and `>`. - )*? - )? - > # End of tag. - | - # HTML Comment - | - <\?.*?\?> | <%.*?%> # Processing instruction - | - # CData Block - ' . ( !$span ? ' # If not in span. - | - # Indented code block - (?: ^[ ]*\n | ^ | \n[ ]*\n ) - [ ]{' . ($indent + 4) . '}[^\n]* \n - (?> - (?: [ ]{' . ($indent + 4) . '}[^\n]* | [ ]* ) \n - )* - | - # Fenced code block marker - (?<= ^ | \n ) - [ ]{0,' . ($indent + 3) . '}(?:~{3,}|`{3,}) - [ ]* - (?: \.?[-_:a-zA-Z0-9]+ )? # standalone class name - [ ]* - (?: ' . $this->id_class_attr_nocatch_re . ' )? # extra attributes - [ ]* - (?= \n ) - ' : '' ) . ' # End (if not is span). - | - # Code span marker - # Note, this regex needs to go after backtick fenced - # code blocks but it should also be kept outside of the - # "if not in span" condition adding backticks to the parser - `+ - ) - }xs'; - - - $depth = 0; // Current depth inside the tag tree. - $parsed = ""; // Parsed text that will be returned. - - // Loop through every tag until we find the closing tag of the parent - // or loop until reaching the end of text if no parent tag specified. - do { - // Split the text using the first $tag_match pattern found. - // Text before pattern will be first in the array, text after - // pattern will be at the end, and between will be any catches made - // by the pattern. - $parts = preg_split($block_tag_re, $text, 2, - PREG_SPLIT_DELIM_CAPTURE); - - // If in Markdown span mode, add a empty-string span-level hash - // after each newline to prevent triggering any block element. - if ($span) { - $void = $this->hashPart("", ':'); - $newline = "\n$void"; - $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; - } - - $parsed .= $parts[0]; // Text before current tag. - - // If end of $text has been reached. Stop loop. - if (count($parts) < 3) { - $text = ""; - break; - } - - $tag = $parts[1]; // Tag to handle. - $text = $parts[2]; // Remaining text after current tag. - - // Check for: Fenced code block marker. - // Note: need to recheck the whole tag to disambiguate backtick - // fences from code spans - if (preg_match('{^\n?([ ]{0,' . ($indent + 3) . '})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:' . $this->id_class_attr_nocatch_re . ')?[ ]*\n?$}', $tag, $capture)) { - // Fenced code block marker: find matching end marker. - $fence_indent = strlen($capture[1]); // use captured indent in re - $fence_re = $capture[2]; // use captured fence in re - if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text, - $matches)) - { - // End marker found: pass text unchanged until marker. - $parsed .= $tag . $matches[0]; - $text = substr($text, strlen($matches[0])); - } - else { - // No end marker: just skip it. - $parsed .= $tag; - } - } - // Check for: Indented code block. - else if ($tag[0] === "\n" || $tag[0] === " ") { - // Indented code block: pass it unchanged, will be handled - // later. - $parsed .= $tag; - } - // Check for: Code span marker - // Note: need to check this after backtick fenced code blocks - else if ($tag[0] === "`") { - // Find corresponding end marker. - $tag_re = preg_quote($tag); - if (preg_match('{^(?>.+?|\n(?!\n))*?(?block_tags_re . ')\b}', $tag) || - ( preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) && - preg_match($newline_before_re, $parsed) && - preg_match($newline_after_re, $text) ) - ) - { - // Need to parse tag and following text using the HTML parser. - list($block_text, $text) = - $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); - - // Make sure it stays outside of any paragraph by adding newlines. - $parsed .= "\n\n$block_text\n\n"; - } - // Check for: Clean tag (like script, math) - // HTML Comments, processing instructions. - else if (preg_match('{^<(?:' . $this->clean_tags_re . ')\b}', $tag) || - $tag[1] === '!' || $tag[1] === '?') - { - // Need to parse tag and following text using the HTML parser. - // (don't check for markdown attribute) - list($block_text, $text) = - $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); - - $parsed .= $block_text; - } - // Check for: Tag with same name as enclosing tag. - else if ($enclosing_tag_re !== '' && - // Same name as enclosing tag. - preg_match('{^= 0); - - return array($parsed, $text); - } - - /** - * Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. - * - * * Calls $hash_method to convert any blocks. - * * Stops when the first opening tag closes. - * * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. - * (it is not inside clean tags) - * - * Returns an array of that form: ( processed text , remaining text ) - * @param string $text - * @param string $hash_method - * @param bool $md_attr Handle `markdown="1"` attribute - * @return array - */ - protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { - if ($text === '') return array('', ''); - - // Regex to match `markdown` attribute inside of a tag. - $markdown_attr_re = ' - { - \s* # Eat whitespace before the `markdown` attribute - markdown - \s*=\s* - (?> - (["\']) # $1: quote delimiter - (.*?) # $2: attribute value - \1 # matching delimiter - | - ([^\s>]*) # $3: unquoted attribute value - ) - () # $4: make $3 always defined (avoid warnings) - }xs'; - - // Regex to match any tag. - $tag_re = '{ - ( # $2: Capture whole tag. - - ".*?" | # Double quotes (can contain `>`) - \'.*?\' | # Single quotes (can contain `>`) - .+? # Anything but quotes and `>`. - )*? - )? - > # End of tag. - | - # HTML Comment - | - <\?.*?\?> | <%.*?%> # Processing instruction - | - # CData Block - ) - }xs'; - - $original_text = $text; // Save original text in case of faliure. - - $depth = 0; // Current depth inside the tag tree. - $block_text = ""; // Temporary text holder for current text. - $parsed = ""; // Parsed text that will be returned. - $base_tag_name_re = ''; - - // Get the name of the starting tag. - // (This pattern makes $base_tag_name_re safe without quoting.) - if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) - $base_tag_name_re = $matches[1]; - - // Loop through every tag until we find the corresponding closing tag. - do { - // Split the text using the first $tag_match pattern found. - // Text before pattern will be first in the array, text after - // pattern will be at the end, and between will be any catches made - // by the pattern. - $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); - - if (count($parts) < 3) { - // End of $text reached with unbalenced tag(s). - // In that case, we return original text unchanged and pass the - // first character as filtered to prevent an infinite loop in the - // parent function. - return array($original_text[0], substr($original_text, 1)); - } - - $block_text .= $parts[0]; // Text before current tag. - $tag = $parts[1]; // Tag to handle. - $text = $parts[2]; // Remaining text after current tag. - - // Check for: Auto-close tag (like
    ) - // Comments and Processing Instructions. - if (preg_match('{^auto_close_tags_re . ')\b}', $tag) || - $tag[1] === '!' || $tag[1] === '?') - { - // Just add the tag to the block as if it was text. - $block_text .= $tag; - } - else { - // Increase/decrease nested tag count. Only do so if - // the tag's name match base tag's. - if (preg_match('{^contain_span_tags_re . ')\b}', $tag)); - - // Calculate indent before tag. - if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { - $strlen = $this->utf8_strlen; - $indent = $strlen($matches[1], 'UTF-8'); - } else { - $indent = 0; - } - - // End preceding block with this tag. - $block_text .= $tag; - $parsed .= $this->$hash_method($block_text); - - // Get enclosing tag name for the ParseMarkdown function. - // (This pattern makes $tag_name_re safe without quoting.) - preg_match('/^<([\w:$]*)\b/', $tag, $matches); - $tag_name_re = $matches[1]; - - // Parse the content using the HTML-in-Markdown parser. - list ($block_text, $text) - = $this->_hashHTMLBlocks_inMarkdown($text, $indent, - $tag_name_re, $span_mode); - - // Outdent markdown text. - if ($indent > 0) { - $block_text = preg_replace("/^[ ]{1,$indent}/m", "", - $block_text); - } - - // Append tag content to parsed text. - if (!$span_mode) { - $parsed .= "\n\n$block_text\n\n"; - } else { - $parsed .= (string) $block_text; - } - - // Start over with a new block. - $block_text = ""; - } - else $block_text .= $tag; - } - - } while ($depth > 0); - - // Hash last block text that wasn't processed inside the loop. - $parsed .= $this->$hash_method($block_text); - - return array($parsed, $text); - } - - /** - * Called whenever a tag must be hashed when a function inserts a "clean" tag - * in $text, it passes through this function and is automaticaly escaped, - * blocking invalid nested overlap. - * @param string $text - * @return string - */ - protected function hashClean($text) { - return $this->hashPart($text, 'C'); - } - - /** - * Turn Markdown link shortcuts into XHTML tags. - * @param string $text - * @return string - */ - protected function doAnchors($text) { - if ($this->in_anchor) { - return $text; - } - $this->in_anchor = true; - - // First, handle reference-style links: [link text] [id] - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - (' . $this->nested_brackets_re . ') # link text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - ) - }xs', - array($this, '_doAnchors_reference_callback'), $text); - - // Next, inline-style links: [link text](url "optional title") - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - (' . $this->nested_brackets_re . ') # link text = $2 - \] - \( # literal paren - [ \n]* - (?: - <(.+?)> # href = $3 - | - (' . $this->nested_url_parenthesis_re . ') # href = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # Title = $7 - \6 # matching quote - [ \n]* # ignore any spaces/tabs between closing quote and ) - )? # title is optional - \) - (?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes - ) - }xs', - array($this, '_doAnchors_inline_callback'), $text); - - // Last, handle reference-style shortcuts: [link text] - // These must come last in case you've also got [link text][1] - // or [link text](/foo) - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ([^\[\]]+) # link text = $2; can\'t contain [ or ] - \] - ) - }xs', - array($this, '_doAnchors_reference_callback'), $text); - - $this->in_anchor = false; - return $text; - } - - /** - * Callback for reference anchors - * @param array $matches - * @return string - */ - protected function _doAnchors_reference_callback($matches) { - $whole_match = $matches[1]; - $link_text = $matches[2]; - $link_id =& $matches[3]; - - if ($link_id == "") { - // for shortcut links like [this][] or [this]. - $link_id = $link_text; - } - - // lower-case and turn embedded newlines into spaces - $link_id = strtolower($link_id); - $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); - - if (isset($this->urls[$link_id])) { - $url = $this->urls[$link_id]; - $url = $this->encodeURLAttribute($url); - - $result = "titles[$link_id] ) ) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - if (isset($this->ref_attr[$link_id])) - $result .= $this->ref_attr[$link_id]; - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - $result = $this->hashPart($result); - } - else { - $result = $whole_match; - } - return $result; - } - - /** - * Callback for inline anchors - * @param array $matches - * @return string - */ - protected function _doAnchors_inline_callback($matches) { - $link_text = $this->runSpanGamut($matches[2]); - $url = $matches[3] === '' ? $matches[4] : $matches[3]; - $title_quote =& $matches[6]; - $title =& $matches[7]; - $attr = $this->doExtraAttributes("a", $dummy =& $matches[8]); - - // if the URL was of the form it got caught by the HTML - // tag parser and hashed. Need to reverse the process before using the URL. - $unhashed = $this->unhash($url); - if ($unhashed !== $url) - $url = preg_replace('/^<(.*)>$/', '\1', $unhashed); - - $url = $this->encodeURLAttribute($url); - - $result = "encodeAttribute($title); - $result .= " title=\"$title\""; - } - $result .= $attr; - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - - return $this->hashPart($result); - } - - /** - * Turn Markdown image shortcuts into tags. - * @param string $text - * @return string - */ - protected function doImages($text) { - // First, handle reference-style labeled images: ![alt text][id] - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - (' . $this->nested_brackets_re . ') # alt text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - - ) - }xs', - array($this, '_doImages_reference_callback'), $text); - - // Next, handle inline images: ![alt text](url "optional title") - // Don't forget: encode * and _ - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - (' . $this->nested_brackets_re . ') # alt text = $2 - \] - \s? # One optional whitespace character - \( # literal paren - [ \n]* - (?: - <(\S*)> # src url = $3 - | - (' . $this->nested_url_parenthesis_re . ') # src url = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # title = $7 - \6 # matching quote - [ \n]* - )? # title is optional - \) - (?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes - ) - }xs', - array($this, '_doImages_inline_callback'), $text); - - return $text; - } - - /** - * Callback for referenced images - * @param array $matches - * @return string - */ - protected function _doImages_reference_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $link_id = strtolower($matches[3]); - - if ($link_id === "") { - $link_id = strtolower($alt_text); // for shortcut links like ![this][]. - } - - $alt_text = $this->encodeAttribute($alt_text); - if (isset($this->urls[$link_id])) { - $url = $this->encodeURLAttribute($this->urls[$link_id]); - $result = "\"$alt_text\"";titles[$link_id])) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - if (isset($this->ref_attr[$link_id])) { - $result .= $this->ref_attr[$link_id]; - } - $result .= $this->empty_element_suffix; - $result = $this->hashPart($result); - } - else { - // If there's no such link ID, leave intact: - $result = $whole_match; - } - - return $result; - } - - /** - * Callback for inline images - * @param array $matches - * @return string - */ - protected function _doImages_inline_callback($matches) { - $alt_text = $matches[2]; - $url = $matches[3] === '' ? $matches[4] : $matches[3]; - $title_quote =& $matches[6]; - $title =& $matches[7]; - $attr = $this->doExtraAttributes("img", $dummy =& $matches[8]); - - $alt_text = $this->encodeAttribute($alt_text); - $url = $this->encodeURLAttribute($url); - $result = "\"$alt_text\"";encodeAttribute($title); - $result .= " title=\"$title\""; // $title already quoted - } - $result .= $attr; - $result .= $this->empty_element_suffix; - - return $this->hashPart($result); - } - - /** - * Process markdown headers. Redefined to add ID and class attribute support. - * @param string $text - * @return string - */ - protected function doHeaders($text) { - // Setext-style headers: - // Header 1 {#header1} - // ======== - // - // Header 2 {#header2 .class1 .class2} - // -------- - // - $text = preg_replace_callback( - '{ - (^.+?) # $1: Header text - (?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes - [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer - }mx', - array($this, '_doHeaders_callback_setext'), $text); - - // atx-style headers: - // # Header 1 {#header1} - // ## Header 2 {#header2} - // ## Header 2 with closing hashes ## {#header3.class1.class2} - // ... - // ###### Header 6 {.class2} - // - $text = preg_replace_callback('{ - ^(\#{1,6}) # $1 = string of #\'s - [ ]'.($this->hashtag_protection ? '+' : '*').' - (.+?) # $2 = Header text - [ ]* - \#* # optional closing #\'s (not counted) - (?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes - [ ]* - \n+ - }xm', - array($this, '_doHeaders_callback_atx'), $text); - - return $text; - } - - /** - * Callback for setext headers - * @param array $matches - * @return string - */ - protected function _doHeaders_callback_setext($matches) { - if ($matches[3] === '-' && preg_match('{^- }', $matches[1])) { - return $matches[0]; - } - - $level = $matches[3][0] === '=' ? 1 : 2; - - $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null; - - $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId); - $block = "" . $this->runSpanGamut($matches[1]) . ""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - /** - * Callback for atx headers - * @param array $matches - * @return string - */ - protected function _doHeaders_callback_atx($matches) { - $level = strlen($matches[1]); - - $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null; - $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId); - $block = "" . $this->runSpanGamut($matches[2]) . ""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - /** - * Form HTML tables. - * @param string $text - * @return string - */ - protected function doTables($text) { - $less_than_tab = $this->tab_width - 1; - // Find tables with leading pipe. - // - // | Header 1 | Header 2 - // | -------- | -------- - // | Cell 1 | Cell 2 - // | Cell 3 | Cell 4 - $text = preg_replace_callback(' - { - ^ # Start of a line - [ ]{0,' . $less_than_tab . '} # Allowed whitespace. - [|] # Optional leading pipe (present) - (.+) \n # $1: Header row (at least one pipe) - - [ ]{0,' . $less_than_tab . '} # Allowed whitespace. - [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline - - ( # $3: Cells - (?> - [ ]* # Allowed whitespace. - [|] .* \n # Row content. - )* - ) - (?=\n|\Z) # Stop at final double newline. - }xm', - array($this, '_doTable_leadingPipe_callback'), $text); - - // Find tables without leading pipe. - // - // Header 1 | Header 2 - // -------- | -------- - // Cell 1 | Cell 2 - // Cell 3 | Cell 4 - $text = preg_replace_callback(' - { - ^ # Start of a line - [ ]{0,' . $less_than_tab . '} # Allowed whitespace. - (\S.*[|].*) \n # $1: Header row (at least one pipe) - - [ ]{0,' . $less_than_tab . '} # Allowed whitespace. - ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline - - ( # $3: Cells - (?> - .* [|] .* \n # Row content - )* - ) - (?=\n|\Z) # Stop at final double newline. - }xm', - array($this, '_DoTable_callback'), $text); - - return $text; - } - - /** - * Callback for removing the leading pipe for each row - * @param array $matches - * @return string - */ - protected function _doTable_leadingPipe_callback($matches) { - $head = $matches[1]; - $underline = $matches[2]; - $content = $matches[3]; - - $content = preg_replace('/^ *[|]/m', '', $content); - - return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); - } - - /** - * Make the align attribute in a table - * @param string $alignname - * @return string - */ - protected function _doTable_makeAlignAttr($alignname) { - if (empty($this->table_align_class_tmpl)) { - return " align=\"$alignname\""; - } - - $classname = str_replace('%%', $alignname, $this->table_align_class_tmpl); - return " class=\"$classname\""; - } - - /** - * Calback for processing tables - * @param array $matches - * @return string - */ - protected function _doTable_callback($matches) { - $head = $matches[1]; - $underline = $matches[2]; - $content = $matches[3]; - - // Remove any tailing pipes for each line. - $head = preg_replace('/[|] *$/m', '', $head); - $underline = preg_replace('/[|] *$/m', '', $underline); - $content = preg_replace('/[|] *$/m', '', $content); - - // Reading alignement from header underline. - $separators = preg_split('/ *[|] */', $underline); - foreach ($separators as $n => $s) { - if (preg_match('/^ *-+: *$/', $s)) - $attr[$n] = $this->_doTable_makeAlignAttr('right'); - else if (preg_match('/^ *:-+: *$/', $s)) - $attr[$n] = $this->_doTable_makeAlignAttr('center'); - else if (preg_match('/^ *:-+ *$/', $s)) - $attr[$n] = $this->_doTable_makeAlignAttr('left'); - else - $attr[$n] = ''; - } - - // Parsing span elements, including code spans, character escapes, - // and inline HTML tags, so that pipes inside those gets ignored. - $head = $this->parseSpan($head); - $headers = preg_split('/ *[|] */', $head); - $col_count = count($headers); - $attr = array_pad($attr, $col_count, ''); - - // Write column headers. - $text = "\n"; - $text .= "\n"; - $text .= "\n"; - foreach ($headers as $n => $header) { - $text .= " " . $this->runSpanGamut(trim($header)) . "\n"; - } - $text .= "\n"; - $text .= "\n"; - - // Split content by row. - $rows = explode("\n", trim($content, "\n")); - - $text .= "\n"; - foreach ($rows as $row) { - // Parsing span elements, including code spans, character escapes, - // and inline HTML tags, so that pipes inside those gets ignored. - $row = $this->parseSpan($row); - - // Split row by cell. - $row_cells = preg_split('/ *[|] */', $row, $col_count); - $row_cells = array_pad($row_cells, $col_count, ''); - - $text .= "\n"; - foreach ($row_cells as $n => $cell) { - $text .= " " . $this->runSpanGamut(trim($cell)) . "\n"; - } - $text .= "\n"; - } - $text .= "\n"; - $text .= "
    "; - - return $this->hashBlock($text) . "\n"; - } - - /** - * Form HTML definition lists. - * @param string $text - * @return string - */ - protected function doDefLists($text) { - $less_than_tab = $this->tab_width - 1; - - // Re-usable pattern to match any entire dl list: - $whole_list_re = '(?> - ( # $1 = whole list - ( # $2 - [ ]{0,' . $less_than_tab . '} - ((?>.*\S.*\n)+) # $3 = defined term - \n? - [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition - ) - (?s:.+?) - ( # $4 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another term - [ ]{0,' . $less_than_tab . '} - (?: \S.*\n )+? # defined term - \n? - [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition - ) - (?! # Negative lookahead for another definition - [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition - ) - ) - ) - )'; // mx - - $text = preg_replace_callback('{ - (?>\A\n?|(?<=\n\n)) - ' . $whole_list_re . ' - }mx', - array($this, '_doDefLists_callback'), $text); - - return $text; - } - - /** - * Callback for processing definition lists - * @param array $matches - * @return string - */ - protected function _doDefLists_callback($matches) { - // Re-usable patterns to match list item bullets and number markers: - $list = $matches[1]; - - // Turn double returns into triple returns, so that we can make a - // paragraph for the last item in a list, if necessary: - $result = trim($this->processDefListItems($list)); - $result = "
    \n" . $result . "\n
    "; - return $this->hashBlock($result) . "\n\n"; - } - - /** - * Process the contents of a single definition list, splitting it - * into individual term and definition list items. - * @param string $list_str - * @return string - */ - protected function processDefListItems($list_str) { - - $less_than_tab = $this->tab_width - 1; - - // Trim trailing blank lines: - $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); - - // Process definition terms. - $list_str = preg_replace_callback('{ - (?>\A\n?|\n\n+) # leading line - ( # definition terms = $1 - [ ]{0,' . $less_than_tab . '} # leading whitespace - (?!\:[ ]|[ ]) # negative lookahead for a definition - # mark (colon) or more whitespace. - (?> \S.* \n)+? # actual term (not whitespace). - ) - (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed - # with a definition mark. - }xm', - array($this, '_processDefListItems_callback_dt'), $list_str); - - // Process actual definitions. - $list_str = preg_replace_callback('{ - \n(\n+)? # leading line = $1 - ( # marker space = $2 - [ ]{0,' . $less_than_tab . '} # whitespace before colon - \:[ ]+ # definition mark (colon) - ) - ((?s:.+?)) # definition text = $3 - (?= \n+ # stop at next definition mark, - (?: # next term or end of text - [ ]{0,' . $less_than_tab . '} \:[ ] | -
    | \z - ) - ) - }xm', - array($this, '_processDefListItems_callback_dd'), $list_str); - - return $list_str; - } - - /** - * Callback for
    elements in definition lists - * @param array $matches - * @return string - */ - protected function _processDefListItems_callback_dt($matches) { - $terms = explode("\n", trim($matches[1])); - $text = ''; - foreach ($terms as $term) { - $term = $this->runSpanGamut(trim($term)); - $text .= "\n
    " . $term . "
    "; - } - return $text . "\n"; - } - - /** - * Callback for
    elements in definition lists - * @param array $matches - * @return string - */ - protected function _processDefListItems_callback_dd($matches) { - $leading_line = $matches[1]; - $marker_space = $matches[2]; - $def = $matches[3]; - - if ($leading_line || preg_match('/\n{2,}/', $def)) { - // Replace marker with the appropriate whitespace indentation - $def = str_repeat(' ', strlen($marker_space)) . $def; - $def = $this->runBlockGamut($this->outdent($def . "\n\n")); - $def = "\n". $def ."\n"; - } - else { - $def = rtrim($def); - $def = $this->runSpanGamut($this->outdent($def)); - } - - return "\n
    " . $def . "
    \n"; - } - - /** - * Adding the fenced code block syntax to regular Markdown: - * - * ~~~ - * Code block - * ~~~ - * - * @param string $text - * @return string - */ - protected function doFencedCodeBlocks($text) { - - $text = preg_replace_callback('{ - (?:\n|\A) - # 1: Opening marker - ( - (?:~{3,}|`{3,}) # 3 or more tildes/backticks. - ) - [ ]* - (?: - \.?([-_:a-zA-Z0-9]+) # 2: standalone class name - )? - [ ]* - (?: - ' . $this->id_class_attr_catch_re . ' # 3: Extra attributes - )? - [ ]* \n # Whitespace and newline following marker. - - # 4: Content - ( - (?> - (?!\1 [ ]* \n) # Not a closing marker. - .*\n+ - )+ - ) - - # Closing marker. - \1 [ ]* (?= \n ) - }xm', - array($this, '_doFencedCodeBlocks_callback'), $text); - - return $text; - } - - /** - * Callback to process fenced code blocks - * @param array $matches - * @return string - */ - protected function _doFencedCodeBlocks_callback($matches) { - $classname =& $matches[2]; - $attrs =& $matches[3]; - $codeblock = $matches[4]; - - if ($this->code_block_content_func) { - $codeblock = call_user_func($this->code_block_content_func, $codeblock, $classname); - } else { - $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); - } - - $codeblock = preg_replace_callback('/^\n+/', - array($this, '_doFencedCodeBlocks_newlines'), $codeblock); - - $classes = array(); - if ($classname !== "") { - if ($classname[0] === '.') { - $classname = substr($classname, 1); - } - $classes[] = $this->code_class_prefix . $classname; - } - $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes); - $pre_attr_str = $this->code_attr_on_pre ? $attr_str : ''; - $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str; - $codeblock = "$codeblock
    "; - - return "\n\n".$this->hashBlock($codeblock)."\n\n"; - } - - /** - * Replace new lines in fenced code blocks - * @param array $matches - * @return string - */ - protected function _doFencedCodeBlocks_newlines($matches) { - return str_repeat("empty_element_suffix", - strlen($matches[0])); - } - - /** - * Redefining emphasis markers so that emphasis by underscore does not - * work in the middle of a word. - * @var array - */ - protected $em_relist = array( - '' => '(?:(? '(? '(? '(?:(? '(? '(? '(?:(? '(? '(? tags - * @return string HTML output - */ - protected function formParagraphs($text, $wrap_in_p = true) { - // Strip leading and trailing lines: - $text = preg_replace('/\A\n+|\n+\z/', '', $text); - - $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); - - // Wrap

    tags and unhashify HTML blocks - foreach ($grafs as $key => $value) { - $value = trim($this->runSpanGamut($value)); - - // Check if this should be enclosed in a paragraph. - // Clean tag hashes & block tag hashes are left alone. - $is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); - - if ($is_p) { - $value = "

    $value

    "; - } - $grafs[$key] = $value; - } - - // Join grafs in one text, then unhash HTML tags. - $text = implode("\n\n", $grafs); - - // Finish by removing any tag hashes still present in $text. - $text = $this->unhash($text); - - return $text; - } - - - /** - * Footnotes - Strips link definitions from text, stores the URLs and - * titles in hash references. - * @param string $text - * @return string - */ - protected function stripFootnotes($text) { - $less_than_tab = $this->tab_width - 1; - - // Link defs are in the form: [^id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,' . $less_than_tab . '}\[\^(.+?)\][ ]?: # note_id = $1 - [ ]* - \n? # maybe *one* newline - ( # text = $2 (no blank lines allowed) - (?: - .+ # actual text - | - \n # newlines but - (?!\[.+?\][ ]?:\s)# negative lookahead for footnote or link definition marker. - (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed - # by non-indented content - )* - ) - }xm', - array($this, '_stripFootnotes_callback'), - $text); - return $text; - } - - /** - * Callback for stripping footnotes - * @param array $matches - * @return string - */ - protected function _stripFootnotes_callback($matches) { - $note_id = $this->fn_id_prefix . $matches[1]; - $this->footnotes[$note_id] = $this->outdent($matches[2]); - return ''; // String that will replace the block - } - - /** - * Replace footnote references in $text [^id] with a special text-token - * which will be replaced by the actual footnote marker in appendFootnotes. - * @param string $text - * @return string - */ - protected function doFootnotes($text) { - if (!$this->in_anchor) { - $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); - } - return $text; - } - - /** - * Append footnote list to text - * @param string $text - * @return string - */ - protected function appendFootnotes($text) { - $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', - array($this, '_appendFootnotes_callback'), $text); - - if ( ! empty( $this->footnotes_ordered ) ) { - $this->_doFootnotes(); - if ( ! $this->omit_footnotes ) { - $text .= "\n\n"; - $text .= "
    \n"; - $text .= "empty_element_suffix . "\n"; - $text .= $this->footnotes_assembled; - $text .= "
    "; - } - } - return $text; - } - - - /** - * Generates the HTML for footnotes. Called by appendFootnotes, even if - * footnotes are not being appended. - * @return void - */ - protected function _doFootnotes() { - $attr = array(); - if ($this->fn_backlink_class !== "") { - $class = $this->fn_backlink_class; - $class = $this->encodeAttribute($class); - $attr['class'] = " class=\"$class\""; - } - $attr['role'] = " role=\"doc-backlink\""; - $num = 0; - - $text = "
      \n\n"; - while (!empty($this->footnotes_ordered)) { - $footnote = reset($this->footnotes_ordered); - $note_id = key($this->footnotes_ordered); - unset($this->footnotes_ordered[$note_id]); - $ref_count = $this->footnotes_ref_count[$note_id]; - unset($this->footnotes_ref_count[$note_id]); - unset($this->footnotes[$note_id]); - - $footnote .= "\n"; // Need to append newline before parsing. - $footnote = $this->runBlockGamut("$footnote\n"); - $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', - array($this, '_appendFootnotes_callback'), $footnote); - - $num++; - $note_id = $this->encodeAttribute($note_id); - - // Prepare backlink, multiple backlinks if multiple references - // Do not create empty backlinks if the html is blank - $backlink = ""; - if (!empty($this->fn_backlink_html)) { - for ($ref_num = 1; $ref_num <= $ref_count; ++$ref_num) { - if (!empty($this->fn_backlink_title)) { - $attr['title'] = ' title="' . $this->encodeAttribute($this->fn_backlink_title) . '"'; - } - if (!empty($this->fn_backlink_label)) { - $attr['label'] = ' aria-label="' . $this->encodeAttribute($this->fn_backlink_label) . '"'; - } - $parsed_attr = $this->parseFootnotePlaceholders( - implode('', $attr), - $num, - $ref_num - ); - $backlink_text = $this->parseFootnotePlaceholders( - $this->fn_backlink_html, - $num, - $ref_num - ); - $ref_count_mark = $ref_num > 1 ? $ref_num : ''; - $backlink .= " $backlink_text"; - } - $backlink = trim($backlink); - } - - // Add backlink to last paragraph; create new paragraph if needed. - if (!empty($backlink)) { - if (preg_match('{

      $}', $footnote)) { - $footnote = substr($footnote, 0, -4) . " $backlink

      "; - } else { - $footnote .= "\n\n

      $backlink

      "; - } - } - - $text .= "
    1. \n"; - $text .= $footnote . "\n"; - $text .= "
    2. \n\n"; - } - $text .= "
    \n"; - - $this->footnotes_assembled = $text; - } - - /** - * Callback for appending footnotes - * @param array $matches - * @return string - */ - protected function _appendFootnotes_callback($matches) { - $node_id = $this->fn_id_prefix . $matches[1]; - - // Create footnote marker only if it has a corresponding footnote *and* - // the footnote hasn't been used by another marker. - if (isset($this->footnotes[$node_id])) { - $num =& $this->footnotes_numbers[$node_id]; - if (!isset($num)) { - // Transfer footnote content to the ordered list and give it its - // number - $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; - $this->footnotes_ref_count[$node_id] = 1; - $num = $this->footnote_counter++; - $ref_count_mark = ''; - } else { - $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1; - } - - $attr = ""; - if ($this->fn_link_class !== "") { - $class = $this->fn_link_class; - $class = $this->encodeAttribute($class); - $attr .= " class=\"$class\""; - } - if ($this->fn_link_title !== "") { - $title = $this->fn_link_title; - $title = $this->encodeAttribute($title); - $attr .= " title=\"$title\""; - } - $attr .= " role=\"doc-noteref\""; - - $attr = str_replace("%%", $num, $attr); - $node_id = $this->encodeAttribute($node_id); - - return - "". - "$num". - ""; - } - - return "[^" . $matches[1] . "]"; - } - - /** - * Build footnote label by evaluating any placeholders. - * - ^^ footnote number - * - %% footnote reference number (Nth reference to footnote number) - * @param string $label - * @param int $footnote_number - * @param int $reference_number - * @return string - */ - protected function parseFootnotePlaceholders($label, $footnote_number, $reference_number) { - return str_replace( - array('^^', '%%'), - array($footnote_number, $reference_number), - $label - ); - } - - - /** - * Abbreviations - strips abbreviations from text, stores titles in hash - * references. - * @param string $text - * @return string - */ - protected function stripAbbreviations($text) { - $less_than_tab = $this->tab_width - 1; - - // Link defs are in the form: [id]*: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,' . $less_than_tab . '}\*\[(.+?)\][ ]?: # abbr_id = $1 - (.*) # text = $2 (no blank lines allowed) - }xm', - array($this, '_stripAbbreviations_callback'), - $text); - return $text; - } - - /** - * Callback for stripping abbreviations - * @param array $matches - * @return string - */ - protected function _stripAbbreviations_callback($matches) { - $abbr_word = $matches[1]; - $abbr_desc = $matches[2]; - if ($this->abbr_word_re) { - $this->abbr_word_re .= '|'; - } - $this->abbr_word_re .= preg_quote($abbr_word); - $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); - return ''; // String that will replace the block - } - - /** - * Find defined abbreviations in text and wrap them in elements. - * @param string $text - * @return string - */ - protected function doAbbreviations($text) { - if ($this->abbr_word_re) { - // cannot use the /x modifier because abbr_word_re may - // contain significant spaces: - $text = preg_replace_callback('{' . - '(?abbr_word_re . ')' . - '(?![\w\x1A])' . - '}', - array($this, '_doAbbreviations_callback'), $text); - } - return $text; - } - - /** - * Callback for processing abbreviations - * @param array $matches - * @return string - */ - protected function _doAbbreviations_callback($matches) { - $abbr = $matches[0]; - if (isset($this->abbr_desciptions[$abbr])) { - $desc = $this->abbr_desciptions[$abbr]; - if (empty($desc)) { - return $this->hashPart("$abbr"); - } - $desc = $this->encodeAttribute($desc); - return $this->hashPart("$abbr"); - } - return $matches[0]; - } -} diff --git a/md/MarkdownInterface.inc.php b/md/MarkdownInterface.inc.php deleted file mode 100755 index c4e9ac7..0000000 --- a/md/MarkdownInterface.inc.php +++ /dev/null @@ -1,9 +0,0 @@ - - * @copyright 2004-2019 Michel Fortin - * @copyright (Original Markdown) 2004-2006 John Gruber - */ - -namespace md; - -/** - * Markdown Parser Interface - */ -interface MarkdownInterface { - /** - * Initialize the parser and return the result of its transform method. - * This will work fine for derived classes too. - * - * @api - * - * @param string $text - * @return string - */ - public static function defaultTransform($text); - - /** - * Main function. Performs some preprocessing on the input text - * and pass it through the document gamut. - * - * @api - * - * @param string $text - * @return string - */ - public function transform($text); -} diff --git a/pages/Centered status bar.md b/pages/Centered status bar.md deleted file mode 100644 index 830746a..0000000 --- a/pages/Centered status bar.md +++ /dev/null @@ -1,22 +0,0 @@ -Centered status bar -=================== - -Thanks to [[Configuring the bar]] and the `es` modules, we can position the status text in the center similar to the [splitstatus](https://dwm.suckless.org/patches/splitstatus) patch. - -To do this, start off by copying `bar.h` to `bar.rl.h`. This is optional, but I highly recommend it. Now, you'll want to add a module like this. - -`{ -1, 0, bar_align_center, width_status_es, draw_status_es, click_status_es, 0, "extra status" },` - -We're using `bar_align_center` because we want it in the center, that's the point here. We're using `es` modules because we want to have status text in both the center and the usual right. In the default configuration, you'll (probably) want to remove the title module, or move it to the other bar to get the aesthetic you want. Now that you have the modules configured, compile this using `make clean install`. - -To use the `es` modules, you simply add `;` somewhere in the status text. Any text after will be considered extrastatus text. For example `speedwm -s "Hello;World"` will draw Hello as regular status text and World as extra status text in the center of the bar. - -### Usage in the status bar - -The above is all cool and all, but if we want to use it with the built in status bar, we need to integrate it into the modules. There are many different ways this could be done, but we're going to do it the easiest here. In this example, we're going to put the time in the center and the rest will be in the normal status bar. - -Copy `status.h` to `status.rl.h` and `vim status.rl.h`. Now we can remove the `module_time` module, because a duplicate is unnecessary. Let's add a module to the array like this. - -`{ ";", "module_time --print", 1, 1 },` - -Of course, the `;` here switches to the centered status. Now we can run `make clean install` and restart `speedwm_status`. You should see your expected changes and the time should be in the center now. diff --git a/pages/Client rules.md b/pages/Client rules.md deleted file mode 100644 index c5c08fd..0000000 --- a/pages/Client rules.md +++ /dev/null @@ -1,130 +0,0 @@ -Client rules -============ - -The `Rule` array allows you to specify rules for X11 clients based on factors such as WM_CLASS and WM_NAME. In the English language, that means you can specify how clients are tiled based on the class, instance or title of said client. - -To get this information, you can use the X11 utility `xprop` to get information about a client. If you want to see in detail how the rule system works, refer to function `applyrules` and the `Rule` struct in `speedwm.c`. - -### Rule structure (user-friendly) - -1. Class - -Type: `const char *` - -2. Instance - -Type: `const char *` - -3. Title - -Type: `const char *` - -4. Tags - -Type: `unsigned int` - -5. isfloating - -Type: `int` - -6. ispermanent - -Type: `int` - -7. isterminal - -Type: `int` - -8. noswallow - -Type: `int` - -9. Monitor - -Type: `int` - -10. unmanaged - -Type: `int` - -11. ignoretransient - -Type: `int` - -12. floatx - -Type: `int` - -13. floaty - -Type: `int` - -14. floatw - -Type: `int` - -15. floath - -Type: `int` - -16. scratchkey - -Type: `const char` - -### Rule structure (internally) - -`typedef struct {` - -`const char *class;` - -`const char *instance;` - -`const char *title;` - -`unsigned int tags;` - -`int isfloating;` - -`int ispermanent;` - -`int isterminal;` - -`int noswallow;` - -`int monitor;` - -`int unmanaged;` - -`int ignoretransient;` - -`int floatx, floaty, floatw, floath;` - -`const char scratchkey;` - -`} Rule;` - -### Class - -Every X11 client has a class. Even the window manager, speedwm in this case which has the class `speedwm` has a class. speedwm is **not** responsible for setting a client's class, clients using X11 libraries should set this themselves. speedwm just retrieves this information when a client is mapped. - -As mentioned previously, you can get the class for a client by running the command-line utility `xprop` on any client. Running `xprop` on speedwm's bar for example will return: - -` -[anon@arch ~]$ xprop -WM_CLASS(STRING) = "speedwm", "speedwm" -` - -Running it and clicking on the root window however will return information such as the different tags and their glyphs, supported atoms, loaded xrdb resources and information such as the focused client which is not relevant here. - -Now, some clients may have multiple classes, `st` for example has both `st` and `St`. Note the class of the program you want to use. Let's say, we want to set a rule for Chromium. Running `xprop | grep CLASS` returns the following information. - -` -[anon@arch ~]$ xprop | grep CLASS -WM_CLASS(STRING) = "chromium", "Chromium" -` - -This means our class here is `chromium`. That would also be the value of `const char *class` or simply the class. This means if the class matches what we specified (ie. `chromium`), and provided the instance and title also matches an existing client, we set the other values to what is specified. - -### Instance - -This allows us to specify which instance of the class diff --git a/pages/Configuring the bar.md b/pages/Configuring the bar.md deleted file mode 100644 index b24d21b..0000000 --- a/pages/Configuring the bar.md +++ /dev/null @@ -1,178 +0,0 @@ -Configuring the bar -=================== - -As of 1.8, speedwm has a module system. It is based on the [barmodules](https://github.com/bakkeby/patches/blob/master/dwm/dwm-barmodules-6.2.diff) patch for dwm and allows extensive control over the way the speedwm bar functions. This control has its own header, `bar.h`. - -`bar.h` contains a somewhat detailed list of all possible options here, but more importantly it contains a `barrules` array. This array similar to the `rules` array allows extensive control over where each bar module is placed and how it functions. In theory, this means you could put 22 instances of the same, boring tags on one bar, although why would one do that? - -Each module can be aligned to any part of the bar (See 'Alignment' for possible values). If, let's say multiple modules both align to the right next to the center split (middle), the first module takes priority. - -### BarRule structure (user-friendly) - -1. Monitor - -Type: `int` - -2. Bar - -Type: `int` - -3. Alignment - -Type: `int` - -4. Width function - -Type: `int (*widthfunc)` - -5. Draw function - -Type: `int (*drawfunc)` - -6. Click function - -Type: `int (*clickfunc)` - -7. Value - -Type: `int` - -8. Name - -Type: `char *` - -### BarRule structure (internally) - -`typedef struct {` - -`int monitor;` - -`int bar;` - -`int alignment;` - -`int (*widthfunc)(Bar *bar, BarWidthArg *a);` - -`int (*drawfunc)(Bar *bar, BarDrawArg *a);` - -`int (*clickfunc)(Bar *bar, Arg *arg, BarClickArg *a);` - -`int val;` - -`char *name;` - -`int x, w;` - -`} BarRule;` - -### Module list - -Below is a list of all modules bundled with speedwm. The source code for these modules are all in `bar/` and declared in `bar/items.c` and `bar/items.h`. If you want to add more, you can just declare them in the same way and add them to the `barrules` array if you want to use them. - -- ltsymbol: Standard, basic layout icon. -- tags: Basic tags, without powerlines. -- tags_pwl: Tags with powerlines. -- systray: Basic X11 system tray. -- status_basic: Basic status bar. -- status_basic_es: Basic status bar. -- status: Clickable status bar with color support through status2d. -- status_es: Clickable status bar with color support through status2d (Extra status). -- status_pwl: Non-clickable status bar with powerlines. It supports colors by cycling through colorschemes. -- status_pwl_es: Non-clickable status bar with powerlines. It supports colors by cycling through colorschemes (Extra status). -- title: Title, shows all windows, including hidden windows. -- title_basic: Basic title, shows focused window. - -### Monitor - -The monitor value allows you to specify which monitor the module should be placed on. In addition to this, you can also choose to only draw the module on the focused monitor. - --1: Show the module on all monitors. -0: Show on the main monitor (monitor 0). -1: Show on monitor #1 (This can be any monitor you want). - -### Bar - -This value allows you to specify which bar the module is placed on. speedwm supports two (0 and 1) bars. 0 is the main bar, which is by default placed at the top. 1 is the second bar which is only visible if modules actively use it. If the main bar is placed on the top, the second bar is placed on the bottom and vice versa. - -0: Place the module on the main bar -1: Place the module on the extra bar - -### Alignment - -This value allows you to specify an alignment for the module in question. As previously mentioned, the first module takes priority if multiple modules have the same alignment. -The 'center split' refers to the middle of the bar, and that's where any free space/remainder of the screen ends up for other modules to use if desired. - -- bar_align_left: Force the module to be placed on the left side of the bar if possible. -- bar_align_right: Force the module to be placed on the right side of the bar if possible. -- bar_align_center: Force the module to be placed in the center of the bar if possible. -- bar_align_left_left: Force the module to be placed on the left side of the bar next to the center split. -- bar_align_left_right: Force the module to be placed on the right side of the bar next to the center split. -- bar_align_left_center: Force the module to be placed on the center in the middle of the remaining space left of the center split on the left.. -- bar_align_right_left: Force the module to be placed on the left side of the bar next to the center split. -- bar_align_right_right: Force the module to be placed on the right side of the bar next to the center split. -- bar_align_right_center: Force the module to be placed on the center in the middle of the remaining space left of the center split on the right. -- bar_align_none: No specific alignment. This will give the module the remaining space. - -### Width - -'Width' refers to the function to call which returns the width of a module. The syntax below applies to all default modules. - -Syntax: width_ -Example: width_tags_pwl - -### Draw - -'Draw' refers to the function to call which draws the module on the bar. The syntax below applies to all default modules. - -Syntax: draw_ -Example: draw_tags_pwl - -### Click - -'Click' refers to the function to call which checks if you clicked on said module. The syntax below applies to all default modules. - -Syntax: click_ -Example: click_tags_pwl - -### Value - -**NOTE: Support for this was added in version 1.9 of speedwm, and speedwm 1.8 does not have it. Any modules using it will be incompatible with speedwm 1.8. I highly recommend upgrading to 1.9 for this (and many more) reason.** - -'Value' here is simply an integer (a number) which the different functions can access and read to (possibly) determine different functionality. Most modules don't use it, in fact speedwm 1.9 doesn't even come with any modules that use this, however in an effort to make writing modules easy, it is included in the base build. - -It should be noted that passing `0` here does not *disable* it, but sets it to `0`. For most modules, it doesn't matter what you pass but it is recommended that you simply pass `0`. - -Syntax: -Example: 12 - -### Module name - -The module name really doesn't mean anything at all, it is just useful for debugging. - -### Example module - -With all that said, you should now be able to add a module. In case you weren't able to follow along, here is an example of how you can add powerline tags on the focused monitor. - -1. `{ 'A',` -2. `0,` -3. `bar_align_left,` -4. `width_tags_pwl,` -5. `draw_tags_pwl,` -6. `click_tags_pwl,` -7. `0,` -8. `"my cool powerline tags" },` - -Combined into one line: `{ 'A', 0, bar_align_left, width-tags_pwl, draw_tags_pwl, click_tags_pwl, 0, "my cool powerline tags" },` - -Let's break down the above. - -1. 'A' here refers to the focused monitor, indicating that we want to place it on the focused monitor. -2. 0 here means we want to place it on the primary bar. -3. bar_align_left indicates we want to align it to the left part of the bar, you know, where tags usually are. -4. width_tags_pwl is the function we call to get the width. -5. draw_tags_pwl is the function we call to draw the bar. -6. click_tags_pwl is the function we call to check if we clicked on that module. -7. 0 here is the value we allow the function to access. The value doesn't matter for most modules but 0 is used here. -8. A label for our module, it's only useful for debugging. - -Feel free to copy the above to `bar.h` if you want to experiment with it. diff --git a/pages/Getting Started.md b/pages/Getting Started.md deleted file mode 100755 index a43d1a0..0000000 --- a/pages/Getting Started.md +++ /dev/null @@ -1,183 +0,0 @@ -Getting Started ---------------- - -[speedwm](https://speedie.gq/projects/speedwm.php) is a window manager forked -from [dwm](https://dwm.suckless.org) (also known as dynamic window manager). -It manages the user's open windows and tiles them according to a set layout. -This is what makes it dynamic, unlike windows managers like i3 which you may -be used to. - -### This is an X11 window manager, you need to use X. - -Yes, this is an X11 window manager. I do not like Wayland and it's -philosophies, and I will not -support it for multiple reasons. See [[Wayland support]] for my reasoning -behind this. Hate me all you want for it! - -If it isn't clear, `xorg-server` as well as `xinit` or `sx` is pretty much -expected. You can also use display managers like `sddm` or `lightdm` although -it should be mentioned that `ly` is **known** to have issues with dwm and -therefore also -speedwm. Do note that setting up X11 is out of the scope of this wiki, and you -need to figure out how to do that yourself. - -### Supported operating systems - -This is not some arbitrary requirement. While it may run if it's not listed -here, I will not be providing support due to having a lack of experience with -said operating system. The main operating systems that **do not** support -speedwm are macOS and Microsoft Windows. UNIX like operating systems are the -most likely to run it. - -- Nearly all GNU/Linux distributions - - NixOS and GNU Guix may require separate instructions. I will not provide - support for these, use the existing documentation to set it up. -- FreeBSD, OpenBSD, NetBSD - - There are likely more BSDs that can run speedwm, but I cannot support all - of them. Try it and see if it works. - -### Installation on Gentoo GNU/Linux - -Gentoo has slightly different instructions for setting up speedwm. While you -can follow along with the generic installation instructions, I have a Gentoo -overlay with packages for all speedwm versions. - -To get started, add [my -overlay](https://codeberg.org/speedie/speedie-overlay). Then simply `emerge -x11-wm/speedwm x11-wm/libspeedwm x11-wm/speedwm-extras`. Optionally, you may -`emerge x11-misc/spde` instead, which is a metapackage for a lot of stuff -including fonts, and general programs that work well for me. - -If you want to install speedwm using Git, do this by adding the following -lines: - -`=x11-wm/speedwm-9999 **` - -`=x11-wm/libspeedwm-9999 **` - -`=x11-wm/speedwm-extras-9999 **` - -to `/etc/portage/package.accept_keywords` and then emerging the packages as -per the instructions above. - -### Installation on generic GNU/Linux distributions - -Installing speedwm on most GNU/Linux distributions is very simple. First, -determine if you want to install it using Git (the absolute latest version) or -using a stable tarball. - -As of 26/01/2023, 1.8 is the latest tarball release -which is not very stable. For this reason, it is recommended that you `git -clone` the repository. If you do not have `git`, install it using your -distribution's package manager. If you're (still) going to be using a 'stable' -tarball, you do not need to install `git`. - -While the list of dependencies will vary depending on the speedwm version -you're going to install (see docs/dependencies.md for your specific version), -below is a list for the latest release, 1.8 and soon to be 1.9. - -- libXft -- libXinerama - - Used for multi-monitor support. It can be disabled if you do not need it - by commenting the XINERAMA libraries in `toggle.mk`. -- imlib2 - - Used for tag previews and window icons. It can be disabled if you do not - need it. To do this, comment out `IMLIB2LIBS` in `toggle.mk` and set - `USEIMLIB2`, `USEWINICON` and `USETAGPREVIEW` to `0` in `toggle.h`. -- pango -- yajl - - Used for IPC support. It can be disabled if you do not need it. To do - this, comment out `YAJLINC` and `YAJLLIBS` in `toggle.mk` and set `USEIPC` - to `0` in `toggle.h`. -- tcc - - This is a compiler. It is used because it is much faster than `clang` or - `gcc` (although at the expense of debugging and compatibility). You can - swap it out by passing `CC=cc` to the `make` command later when we compile - speedwm. - -#### Installation using `git` - -This assumes you have `git` installed. - -`cd` into a location where your normal user (not root) has permission to both -read and write. Do not clone the speedwm repository in `~/.config` as speedwm -will write configuration files to that location. - -**Note: Cloning the repository to `~/.config` is fine -if the speedwm source code directory is **not** `speedwm` but speedwm -will use the `~/.config/speedwm` directory to store configuration files (not -source code).** - -From here on, we're going to assume you are in the location `~/Documents`! Run -`git clone https://codeberg.org/speedie/speedwm.git speedwm` to clone the -repository into a directory named `speedwm`. Provided the repository hasn't -moved and you have a working internet connection, you should have received a -copy of the speedwm source code. - -You can now `cd speedwm` into it so we can actually install it. If you need to -make changes to `toggle.h`, `toggle.mk`, `host.mk` or any other C source code, -now is the time to do it. - -Now, it's time to compile it! Provided you have all dependencies installed, -this should be very, very easy and quick. Run `make clean install` as root to install -speedwm. The binary will be in `/usr/bin/speedwm`. If you need to use a -different compiler (tcc in Arch repositories has a few issues), you can run -`make CC=cc clean install` to use the system default compiler. Alternatively -use `gcc` instead of `cc` or whatever you want. - -After installation, it is *highly* recommended that you move your source code -directory to a safe place. speedwm is a source based window manager and -**most** (but not all) changes you make to it are going to be done by -recompiling the window manager. This is, of course done with the same `make -clean install` command you used earlier. - -I recommend you do this by forking the speedwm repository, and putting it on a -Git repository somewhere. That way, you can always clone your specific -version. - -**Warning: If you lose your source code, you will be -**unable** to make any further changes to speedwm.** - -Now follow along with 'Using speedwm'. - -#### Installation using a tarball - -Installation using a tarball works pretty much the same. Visit [the releases -page](https://codeberg.org/speedie/speedwm/releases) and get the latest - (or an old if you want) tarball. Avoid the 'Source Code (ZIP)' and 'Source - Code (TAR.GZ)' options, get the 'speedwm-.tar.gz' file. - -`cd` into a location where your normal user (not root) has permission to both -read and write. Make sure `~/.config/speedwm` is not used by anything. - -Now we need to unpack the tarball and get our source code. To do this, you can -use the `tar` command. I will spare you the time reading the man page and the -command to unpack the tarball is `tar -xpvf -/path/to/the/speedwm/tarball.tar.gz`. The `-x` argument here means extract. -`-p` means preserve permissions. The `-v` means verbose, we want to see -what's going on. `-f` means file, we want to specify a file to unpack. - -After unpacking it, there should be one directory; `speedwm-`. Let's -`cd speedwm-` into it. Now it's time to compile speedwm! - -Provided you have all dependencies installed, this should be very, very easy -and quick. Run `make clean install` as root to install speedwm. The binary -will be in `/usr/bin/speedwm`. If you need to use a different compiler (tcc in -Arch repostories has a few issues), you can run `make CC=cc clean install` to -use the system default compiler. Alternatively use `gcc` instead of `cc` or -whatever you want. - -After installation, it is *highly* recommended that you move your source code -directory to a safe place. speedwm is a source based window manager and -**most** (but not all) changes you make to it are going to be done by -recompiling the window manager. This is, of course done with the same `make -clean install` command you used earlier. - -I recommend you do this by putting the source code on a -Git or subversion repository somewhere. That way, you can always clone your specific -version. - -**Warning: If you lose your source code, you will be -**unable** to make any further changes to speedwm.** - -Now follow along with 'Using speedwm'. diff --git a/pages/Home.md b/pages/Home.md deleted file mode 100755 index 849dc67..0000000 --- a/pages/Home.md +++ /dev/null @@ -1,27 +0,0 @@ -Welcome to the speedwm wiki! ----------------------------- - -![image](https://codeberg.org/speedie/speedwm/raw/branch/master/docs/preview.png) - -[speedwm](https://speedie.gq/projects/speedwm.php) is a window manager forked -from [dwm](https://dwm.suckless.org) (also known as dynamic window manager). -It manages the user's open windows and tiles them according to a set layout. -This is what makes it dynamic, unlike windows managers like i3 which you may -be used to. - -Just like dwm, speedwm also tries to be minimal but also brings functionality -and aesthetics to the table without patching or other work. It is a good -middle ground between creating your own dwm build from scratch and bloated -window managers like awesome which are not primarily configured by editing source code. - -Tiling window managers (unlike floating window managers that you may be used to) tile windows based on a set layout making them easy to get productive on. They also encourage the user to use their keyboard instead of the mouse so that the user doesn't have to move his hands much but there are also mouse binds and more can be added by the user if desired. - -You have reached the wiki for speedwm, the main source of information -regarding the project. Any information too detailed or complex to be part of the speedwm -release is placed here. Because it's a wiki, anyone may submit changes to the -wiki. The wiki is also free/libre (as in freedom) software and you can have a -copy. See [this git repository](https://codeberg.org/speedie/speedwm-wiki) for -more information. - -Not sure where to begin with speedwm? See [[Getting Started]] for a nice way -to get into it! diff --git a/pages/Keybinds.md b/pages/Keybinds.md deleted file mode 100644 index 9ac39c2..0000000 --- a/pages/Keybinds.md +++ /dev/null @@ -1,167 +0,0 @@ -Keybinds -======== - -Like the `BarRules` array mentioned, there is a `Key keys` array in `keybinds.h` which contains all keybinds speedwm will recognize. While this isn't the only way to add keybinds in speedwm, it does not require any additional software to be installed. - -### Key structure (user-friendly) - -1. Event - -Type: `int` - -2. Modifier - -Type: `unsigned int` - -3. Chain key - -Type: `KeySym` - -4. Key - -Type: `KeySym` - -5. Function - -Type: `void (*func)` - -6. Function arguments - -Type: `const Arg` - -### Key structure (internally) - -`typedef struct {` - -`int type;` - -`unsigned int mod;` - -`KeySym chain;` - -`KeySym keysym;` - -`void (*func)(const Arg *);` - -`const Arg arg;` - -`} Key;` - -### Event - -The event value allow you to specify when a keybind is executed. Internally this is known as `int type` and it specifies when the function is executed. - -- KeyPress: Activate immediately on key press. -- KeyRelease: Activate immediately on key release. - -### Modifier - -There are a lot of different modifiers, this list is only going to list the ones declared in speedwm. You can, of course declare more if necessary although it should be noted that doing so is out of the scope of this documentation. We will be focusing on the defined modifiers which are defined in `speedwm.c` like this: - -`/* Modifiers */` -`#define CONTROL ControlMask` -`#define SHIFT ShiftMask` -`#define ALT Mod1Mask` -`#define ALTR Mod3Mask` -`#define SUPER Mod4Mask` -`#define SUPERR Mod5Mask` - -Below is a list of defined modifiers: - -- CONTROL Left Control (Ctrl) key. -- SHIFT Left Shift key. -- ALT Left Alt key. -- SUPER Left Super (Windows) key. -- SUPERR Right Super (Windows) key. - -In keybinds.h, MODIFIER1 and MODIFIER2 are also defined. MODIFIER1 is defined in order to make modifying keybinds easier. MODIFIER1 is by default defined as SUPER or Mod4Mask. For instance, if you want to use MODIFIER1 as your modifier, `MODIFIER1` would be the right value here. - -Do note that you can may use multiple modifiers. Do this by adding two or more modifiers separated by a pipe (MODIFIER1|SHIFT) - -### Chain key - -This value *is* mandatory, but it does not have to be used. speedwm has supported chained keybinds since 0.4. Chained keybinds allow more keybinds as like the name implies, the user has to press multiple keys to activate it. You can think of it as in Vim where there's different modes. - -The first key that needs to be pressed to activate a chain needs to be the key specified here. In order to see a list of possible keys, see `/usr/include/X11/keysymdef.h`. If, let's say we want to use simply the letter `a` as the key to start a chain, the value here would be `XK_a`. - -If we want a normal key, one that is **not** chained, we can accomplish that by simply setting the Chain key to `-1`. You can see this in the `keypress()` function in `speedwm.c`. This line of code is responsible for this behavior. - -`if (keysym == keys[i].keysym && keys[i].chain == -1` - -### Key - -The next value, similar to the Chain key also needs to be a keysym. If the key is a chained key, this is the second key that needs to be pressed. If it isn't a chained key, this is the key that needs to be pressed while the Modifier is pressed. - -In order to see a list of possible keys, see `/usr/include/X11/keysymdef.h`. Note that this path may differ depending on your operating system. - -There are a lot more keys technically defined, see `/usr/include/X11/XF86keysym.h` for a list of media keys. - -### Function - -Many functions expect `const Arg *arg` to be passed to them. However this value does require any function argument to be specified because it simply passes the next value to the function and calls it. - -There is no list of functions, but `speedwm.c` has a lot of declared functions which you may use in keybinds provided the function expects `const Arg *arg`. - -### Function arguments - -This is the actual argument passed to the function we're calling when the keybind is activated. Explaining this well would be fairly simple, but instead of doing so I recommend you read the `typedef union Arg` in `speedwm.c`. It looks like this: - -`typedef union {` - `long i;` - `unsigned long ui;` - `float f;` - `const void *v;` -`} Arg;` - -In short, Arg is a list of different types, which may be used to set different things in the argument. -Passing a float (such as mfact) through would mean I should override `.f`, passing an integer (such as barposition) through would mean I should override `.i`. There's also `.v` for `void` and `.ui` for tags. This is not used unless you want to mess with tag keybinds. - -When you don't care about the value given to the function, you may simply enter a `0`. - -### Example keybind - -With all that said, you probably get the idea of how it works. But you still don't know how to put all this knowledge together. - -1. `{ KeyPress,` -2. `MODIFIER1|SHIFT,` -3. `-1,` -4. `XK_w,` -5. `spawn,` -6. `cmd( "firefox" ) },` - -Combined into one line: `{ KeyPress, MODIFIER1|SHIFT, -1, XK_w, spawn, cmd( "firefox" ) },` - -Let's break down the above. - -1. This is our type. If it's `KeyPress`, it will be activated when the keybind is pressed. If it is `KeyRelease` it will be activated when the keybind is released. -2. This is our modifier. `MODIFIER1` is defined in `keybinds.h`. We're adding SHIFT to it, (defined in `speedwm.c`) which means we have to press BOTH `MODIFIER1` and `SHIFT` at the same time to activate this keybind. -3. This is our **chain** key. `-1` here indicates that we do not want it to be chained. We want a regular keybind. See the example below for an example *with* a chained keybind instead. -4. This is our regular key. `XK_w` is defined in `/usr/include/X11/keysymdef.h` on most operating systems and it means we have to press `w` on our keyboard along with the modifier to activate this keybind. -5. This is our function. We call this, passing the next value (`const Arg *arg`) to it. -6. This is our function argument. Do note that in this case `cmd()` is a macro and it is defined in `speedwm.c`. This macro will pass the contents of the macro to a shell it will spawn. - -Feel free to copy the above to `keybinds.h` if you want to experiment with it. - -### Example chained keybind - -1. `{ KeyPress,` -2. `MODIFIER1|SHIFT,` -3. `XK_a,` -4. `XK_w,` -5. `togglebar,` -6. `{0} },` - -Combined into one line: `{ KeyPress, MODIFIER1|SHIFT, XK_a, XK_w, togglebar, {0} },` - -Let's break down the above. - -1. This is our type. If it's `KeyPress`, it will be activated when the keybind is pressed. If it is `KeyRelease` it will be activated when the keybind is released. -2. This is our modifier. `MODIFIER1` is defined in `keybinds.h`. We're adding SHIFT to it, (defined in `speedwm.c`) which means we have to press BOTH `MODIFIER1` and `SHIFT` at the same time to activate this keybind. -3. This is our **chain** key. `XK_a` here is the key we have to press along with our modifier to activate this keybind. `XK_a` is defined in `/usr/include/X11/keysymdef.h` on most operating systems. -4. This is our regular key. `XK_w` is defined in `/usr/include/X11/keysymdef.h` on most operating systems and it means we have to press `w` on our keyboard to activate this keybind. Note that we do **not** need to press the modifier here, because it is a chained keybind. -5. This is our function. We call this, passing the next value (`const Arg *arg`) to it. -6. This is our function argument. We simply pass `0` here because we don't need to pass anything to the function, because the function does not care. - -Feel free to copy the above to `keybinds.h` if you want to experiment with it. - -This should give you a brief idea of how keybinds work in speedwm. Most of this carries over to `dwm` as well, although it does not have some of this stuff. It should be noted that as I mentioned previously, you don't HAVE to use this system. You can use external programs to handle keybinds, and `libspeedwm` to perform actions in speedwm. sxkbd is one popular program for this purpose and window managers like `bspwm` use it. However such a solution is out of the scope of this documentation! diff --git a/pages/Managing changes.md b/pages/Managing changes.md deleted file mode 100755 index 6a88134..0000000 --- a/pages/Managing changes.md +++ /dev/null @@ -1,14 +0,0 @@ -Managing changes ----------------- - -speedwm's Makefile has a nice feature which allows you to compile one header into the binary while keeping the original unmodified. - -If I want to make a change to, let's say `bar.h` in my personal build I just `cp bar.h bar.rl.h`, make changes to `bar.rl.h` and recompile. `bar.h` will be intact, but my changes from bar.rl.h will be applied in the compiled binary. - -This feature is currently available for: - -- bar.h -- options.h -- keybinds.h -- mouse.h -- status.h diff --git a/pages/Restoring the dwm bar.md b/pages/Restoring the dwm bar.md deleted file mode 100644 index 9aeca73..0000000 --- a/pages/Restoring the dwm bar.md +++ /dev/null @@ -1,167 +0,0 @@ -Restoring the dwm bar -===================== - -This wiki article describes how to restore the default dwm look to the bar. This should look nearly identical if not exactly the same as dwm-6.4, and can be done in like 2 minutes. - -### Restoring the dwm modules - -To do this, you must first restore the original modules dwm uses. To do this, you can edit `bar.h`. However, what I recommend you do is copy `bar.h` to `bar.rl.h`. The `rl` headers will be compiled into the binary without replacing the original files and so is nice if you want a configuration without pushing it to the Git repository. Of course, this is optional. - -In `bar.rl.h`, you'll want to remove any modules not present in default dwm such as all the powerline modules and systray. You can choose to keep things like the systray if you want, but this article is about being as close to regular dwm as possible. - -If you want, you can copy my `barrules` array below: - -`{ -1, 0, bar_align_left, width_tags, draw_tags, click_tags, 0, "tags" },` - -`{ -1, 0, bar_align_left, width_ltsymbol, draw_ltsymbol, click_ltsymbol, 0, "layout" },` - -`{ -1, 0, bar_align_right, width_status_basic, draw_status_basic, click_status_basic, 0, "status" },` - -`{ -1, 0, bar_align_none, width_title_basic, draw_title_basic, click_title_basic, 0, "title" },` - -As you can see, you'll want to set some of the modules to the `basic` variant. With that done, go ahead and recompile speedwm using `make clean install`. -Then follow along with 'Restoring settings'. - -### Restoring settings - -Now that we have the old modules, we'll want to restore the colors, fonts, and other things to the dwm settings. This includes disabling gaps, padding, and any other features dwm does not have. - -To do this, edit `~/.config/speedwm/speedwmrc`. You *can* add all the .Xresources values yourself, or you can just copy my list of values below into your own config. I should note though that you may not achieve perfect results if your config already has other options. For best results, start with a blank `speedwmrc`. - -`speedwm.fonts.font: monospace 10` - -`speedwm.gaps.enable: 0` - -`speedwm.color.hiddentitle: 0` - -`speedwm.color.selectedtitle: 1` - -`speedwm.color.layout: 0` - -`speedwm.client.map: 0` - -`speedwm.client.hide.border: 0` - -`speedwm.client.hide.unselected.border: 0` - -`speedwm.tiling.resizehints: 1` - -`speedwm.bar.alpha: 0` - -`speedwm.bar.position: 1` - -`speedwm.bar.height: 4` - -`speedwm.bar.paddingih: 0` - -`speedwm.bar.paddingiv: 0` - -`speedwm.bar.paddingoh: 0` - -`speedwm.bar.paddingov: 0` - -`speedwm.bar.hide.emptytags: 0` - -`speedwm.bar.hide.floating: 0` - -`speedwm.bar.hide.layout: 0` - -`speedwm.bar.hide.status: 0` - -`speedwm.bar.hide.title: 0` - -`speedwm.bar.hide.clientindicator: 0` - -`speedwm.bar.titleposition: 0` - -`speedwm.bar.hide.systray: 1` - -`speedwm.bar.hide.sticky: 1` - -`speedwm.bar.hide.icon: 1` - -`speedwm.border.size: 1` - -`speedwm.text.layout1: []=` - -`speedwm.text.layout2: ><>` - -`speedwm.text.layout3: [M]` - -`speedwm.text.tag1.empty: 1` - -`speedwm.text.tag2.empty: 2` - -`speedwm.text.tag3.empty: 3` - -`speedwm.text.tag4.empty: 4` - -`speedwm.text.tag5.empty: 5` - -`speedwm.text.tag6.empty: 6` - -`speedwm.text.tag7.empty: 7` - -`speedwm.text.tag8.empty: 8` - -`speedwm.text.tag9.empty: 9` - -`speedwm.text.tag1.used: 1` - -`speedwm.text.tag2.used: 2` - -`speedwm.text.tag3.used: 3` - -`speedwm.text.tag4.used: 4` - -`speedwm.text.tag5.used: 5` - -`speedwm.text.tag6.used: 6` - -`speedwm.text.tag7.used: 7` - -`speedwm.text.tag8.used: 8` - -`speedwm.text.tag9.used: 9` - -`speedwm.col.tag1: #005577` - -`speedwm.col.tag2: #005577` - -`speedwm.col.tag3: #005577` - -`speedwm.col.tag4: #005577` - -`speedwm.col.tag5: #005577` - -`speedwm.col.tag6: #005577` - -`speedwm.col.tag7: #005577` - -`speedwm.col.tag8: #005577` - -`speedwm.col.tag9: #005577` - -`speedwm.col.titlenorm: #222222` - -`speedwm.col.titlesel: #005577` - -`speedwm.col.titlehid: #222222` - -`speedwm.col.windowbordernorm: #444444` - -`speedwm.col.windowbordersel: #005577` - -`speedwm.col.textnorm: #bbbbbb` - -`speedwm.col.textsel: #eeeeee` - -`speedwm.status.defaultstatus: dwm-6.4` - -Append this to your `speedwmrc` and then simply restart using `libspeedwm --perform core_wm_restart`. - -**NOTE: If you're using .Xresources, you'll likely notice that colors are not being overridden. You can stop overriding colors, or you can disable .Xresources support in toggle.h, but do note that doing this means you'll have to edit `options.h` with the values above.** - -### Done - -After doing the above, you should have a configuration that looks more or less identical to dwm 6.4. If you want to take it a step further, you can disable things like tag previews, window icons and task switcher through `toggle.h` if resources is your concern. diff --git a/pages/Rounded corners.md b/pages/Rounded corners.md deleted file mode 100755 index 33343dc..0000000 --- a/pages/Rounded corners.md +++ /dev/null @@ -1,90 +0,0 @@ -Rounded corners ---------------- - -speedwm versions before 1.9 had built in rounded corner support done using standard X11 libraries. This worked relatively well, but only for clients, not the bar. In 1.9 however, this was removed. The removal was done because if you like rounded corners, chances are you already have a compositor like `picom` installed on your system anyway. - -`picom` does rounded corners for any program, and that includes the speedwm bar, and it does it better than speedwm did, so it made no sense to keep it around in speedwm causing possible future bugs. - -### Rounded corners using `picom` - -To enable rounded corners in speedwm, install picom. - -For Gentoo: `emerge --ask picom` - -For Arch: `pacman -S picom` - -Once `picom` is installed, you can add `picom &` to `~/.config/speedwm/autostart.sh` which will allow it to automatically run on speedwm startup. Alternatively, add it to another file which is autostarted, such as `~/.xinitrc`. - -`picom` has a configuration file in `~/.config/picom/picom.conf`. Here you can do a bunch of cool things, but importantly you can enable rounded corners. A good start would be to add the following to the file: - -`corner-radius = 10.0;` - -`rounded-corners-exclude = [` - -`"class_g = 'Dunst'",` - -`];` - -`round-borders = 10;` - -`round-borders-exclude = [` - -`#"class_g = 'Chromium'",` - -`];` - -You can adjust `round-borders` and `corner-radius` depending on how sharp you want the window borders. Similar to speedwm rules, you can exclude certain clients based on class. There are a few examples here by default. Settings should apply immediately when the file is saved which is very convenient. In case it doesn't though, restart `picom`. - -### Excluding the speedwm bar - -Some users may not want to round the bar, specifically if you're not using any barpadding. In that case, simply add a rule like this: - -`rounded-corners-exclude = [` - -`"class_g = 'speedwm'",` - -`];` - -to your `picom.conf` configuration file. - -### speedwm configuration - -It may be a good idea to disable window borders in the speedwm configuration. This isn't required of course, but window borders can look a bit out of place. Otherwise, you may want to consider increasing the size. Add `speedwm.border.size: 0` to `~/.config/speedwm/speedwmrc` to disable the window border for clients in speedwm. - -It also does not make much sense to use rounded corners without padding, so I set outer horizontal and outer vertical padding to 5 like so: - -`speedwm.bar.paddingoh: 5` - -`speedwm.bar.paddingov: 5` - -I also want a smaller bar, but instead of decreasing the font size, I choose to decrease bar height by 2 like so: - -`speedwm.bar.height: -2` - -Gaps are set to 10 by default, but because 10 pixels of padding is too much, I choose to decrease inner and outer gaps like this: - -`speedwm.gaps.sizeih: 5` - -`speedwm.gaps.sizeiv: 5` - -`speedwm.gaps.sizeoh: 5` - -`speedwm.gaps.sizeov: 5` - -My configuration looks like this. Feel free to copy it to your own `speedwmrc`. - -`speedwm.border.size: 0` - -`speedwm.bar.paddingoh: 5` - -`speedwm.bar.paddingov: 5` - -`speedwm.bar.height: -2` - -`speedwm.gaps.sizeih: 5` - -`speedwm.gaps.sizeiv: 5` - -`speedwm.gaps.sizeoh: 5` - -`speedwm.gaps.sizeov: 5` diff --git a/pages/Using the wiki.md b/pages/Using the wiki.md deleted file mode 100644 index 81100cc..0000000 --- a/pages/Using the wiki.md +++ /dev/null @@ -1,24 +0,0 @@ -Using the wiki -============== - -Lost? If you don't know where to go, you can click the icon on the top bar. The `All` button allows you to get a view of all articles that have been posted on the wiki. - -There is also a search bar at the top of every page which allows you to search for any article that has been posted. - -## Basic wiki features - -The wiki, based on a fork of w2wiki allows you to create new articles, edit existing articles, read existing articles (that's pretty much given), [host it yourself](https://codeberg.org/speedie/speedwm-wiki), and delete articles. - -Now, please note that I am giving you this power, and with great power comes great responsibility. I want everyone to be able to help with the project. However, if it gets abused by people then I will have to remove this functionality and go back to using purely Git. - -So please don't ruin it for everyone. If the wiki has to be shut down due to your vandalism, we hate you forever. That said, we do make Git backups fairly often (I will not say how often to prevent vandalism), so if an article is deleted it should be possible to restore it with minor changes lost. - -## The sidebar - -The sidebar is a markdown page like any other and can also be edited as any other. It is supposed to be used as a list of links, but of course there is no limit to what you can do with it. - -To edit it, click `All` and edit `_sidebar`. From there, you can follow regular markdown syntax. - -## Testing locally - -Please, please, please test locally if you're new to markdown. That way, you avoid (for example) deleting pages by accident. You can easily test an identical (minus some pages perhaps) copy of the wiki locally by installing `php` with your distro's package manager and cloning [the repo](https://codeberg.org/speedie/speedwm-wiki) somewhere. If you don't know what you're doing, just cd into it, run `php -S localhost:1337` to start PHP, open any web browser and go to `localhost:1337`. Of course, the `1337` here can be swapped out for almost any value, it's just what I happen to go with. \ No newline at end of file diff --git a/pages/Wayland support.md b/pages/Wayland support.md deleted file mode 100755 index 98878ed..0000000 --- a/pages/Wayland support.md +++ /dev/null @@ -1,2 +0,0 @@ -Wayland, and why it sucks. --------------------------- diff --git a/pages/Where do I go?.md b/pages/Where do I go?.md deleted file mode 100644 index 9cf2323..0000000 --- a/pages/Where do I go?.md +++ /dev/null @@ -1,24 +0,0 @@ -Where do I go? -============== - -Lost? If you don't know where to go, you can click the icon on the top bar. The `All` button allows you to get a view of all articles that have been posted on the wiki. - -There is also a search bar at the top of every page which allows you to search for any article that has been posted. - -## Basic wiki features - -The wiki, based on a fork of w2wiki allows you to create new articles, edit existing articles, read existing articles (that's pretty much given), [host it yourself](https://codeberg.org/speedie/speedwm-wiki), and delete articles. - -Now, please note that I am giving you this power, and with great power comes great responsibility. I want everyone to be able to help with the project. However, if it gets abused by people then I will have to remove this functionality and go back to using purely Git. - -So please don't ruin it for everyone. If the wiki has to be shut down due to your vandalism, we hate you forever. That said, we do make Git backups fairly often (I will not say how often to prevent vandalism), so if an article is deleted it should be possible to restore it with minor changes lost. - -## The sidebar - -The sidebar is a markdown page like any other and can also be edited as any other. It is supposed to be used as a list of links, but of course there is no limit to what you can do with it. - -To edit it, click `All` and edit `_sidebar`. From there, you can follow regular markdown syntax. - -## Testing locally - -Please, please, please test locally if you're new to markdown. That way, you avoid (for example) deleting pages by accident. You can easily test an identical (minus some pages perhaps) copy of the wiki locally by installing `php` with your distro's package manager and cloning [the repo](https://codeberg.org/speedie/speedwm-wiki) somewhere. If you don't know what you're doing, just cd into it, run `php -S localhost:1337` to start PHP, open any web browser and go to `localhost:1337`. Of course, the `1337` here can be swapped out for almost any value, it's just what I happen to go with. \ No newline at end of file diff --git a/pages/_sidebar.md b/pages/_sidebar.md deleted file mode 100755 index 402ee93..0000000 --- a/pages/_sidebar.md +++ /dev/null @@ -1,12 +0,0 @@ -Basics -====== - -- [[Home]] -- [[Where do I go?]] -- [[Getting Started]] - -### Deeper - -- [[Client rules]] -- [[Keybinds]] -- [[Configuring the bar]] diff --git a/run.sh b/run.sh deleted file mode 100755 index 65633a6..0000000 --- a/run.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# crontab this to run every X minutes -# 5 * * * * /usr/bin/run.sh - -die() { printf "%s\n" "$*"; exit 1; } - -WIKINAME="speedwm-wiki" -POST_DIR="$1" -[ -z "$1" ] && POST_DIR="/var/www/page/$WIKINAME/pages" - -[ -e "$POST_DIR" ] || die "You must specify a VALID path. Edit $0." - -cd "$POST_DIR" || die "Does not exist." - -[ -e "/tmp/markdown-log" ] && mv /tmp/markdown-log /tmp/markdown-log-2 -find ./*md > /tmp/markdown-log - -[ -e "/tmp/markdown-log-2" ] || exit 0 - -[ -z "$(diff -up /tmp/markdown-log /tmp/markdown-log-2)" ] && exit 0 - -git add ./*.md -git commit -am "Add articles" - -printf "%s - Added articles" "$(date)" > /tmp/markdown-crontab-log - -exit 0 diff --git a/test.sh b/test.sh deleted file mode 100755 index 4579eb7..0000000 --- a/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -printf "Testing locally..\nOpen 'localhost:1337' in your web browser.\n" -php -S localhost:1337 diff --git a/tests/travis-ci-apache.conf b/tests/travis-ci-apache.conf deleted file mode 100755 index 3eedbe6..0000000 --- a/tests/travis-ci-apache.conf +++ /dev/null @@ -1,21 +0,0 @@ - - DocumentRoot %TRAVIS_BUILD_DIR% - - - Options FollowSymLinks MultiViews ExecCGI - AllowOverride All - Require all granted - - - # Wire up Apache to use Travis CI's php-fpm. - - AddHandler php5-fcgi .php - Action php5-fcgi /php5-fcgi - Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi - FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:9000 -pass-header Authorization - - - Require all granted - - -