Browse Source

updates

master
eorn 2 years ago
parent
commit
64ec991b1e
  1. 3
      .gitmodules
  2. 2
      apps/bitwardenrs/docker-compose.yml
  3. 1
      apps/castopod
  4. 5
      apps/codimd/docker-compose.yml
  5. 6
      apps/funkwhale/docker-compose.yml
  6. 2
      apps/gitea/docker-compose.yml
  7. 202
      apps/mailu/docker-compose.yml
  8. 4
      apps/matrix/docker-compose.yml
  9. 133
      apps/monitor/docker-compose.yml
  10. 2
      apps/rss-bridge/docker-compose.yml
  11. 102
      apps/shaarli/plugins/markdown/README.md
  12. 5
      apps/shaarli/plugins/markdown/help.html
  13. 173
      apps/shaarli/plugins/markdown/markdown.css
  14. 4
      apps/shaarli/plugins/markdown/markdown.meta
  15. 365
      apps/shaarli/plugins/markdown/markdown.php

3
.gitmodules

@ -13,3 +13,6 @@
[submodule "apps/spacedeck-open"]
path = apps/spacedeck-open
url = https://github.com/spacedeck/spacedeck-open
[submodule "apps/castopod"]
path = apps/castopod
url = https://code.podlibre.org/podlibre/castopod

2
apps/bitwardenrs/docker-compose.yml

@ -2,7 +2,7 @@ version: '3'
services:
bitwarden:
image: bitwardenrs/server:1.16.3-alpine
image: bitwardenrs/server:1.17.0-alpine
restart: always
networks:
- myweb

1
apps/castopod

@ -0,0 +1 @@
Subproject commit 79a20a3bc88d53c9fd10acc39d3650c897d9569c

5
apps/codimd/docker-compose.yml

@ -13,7 +13,8 @@ services:
- myweb
codimd:
image: linuxserver/codimd:1.6.0-ls33
#image: linuxserver/codimd:1.6.0-ls33
image: linuxserver/codimd:latest
restart: unless-stopped
depends_on:
- dbcodimd
@ -31,7 +32,7 @@ services:
- "traefik.http.routers.codimdtls.tls=true"
- "traefik.http.routers.codimdtls.tls.certresolver=letsencrypt"
- "traefik.http.routers.codimdtls.tls.domains[0].main=*.goe.land"
# - "traefik.http.services.codimd.loadbalancer.server.port=9001"
# - "traefik.http.services.codimd.loadbalancer.server.port=9001"
- "traefik.docker.network=myweb"
networks:

6
apps/funkwhale/docker-compose.yml

@ -20,7 +20,7 @@ services:
celeryworker:
image: funkwhale/funkwhale:1.0
image: funkwhale/funkwhale:1.0.1
#image: funkwhale/funkwhale:develop
restart: unless-stopped
networks:
@ -37,7 +37,7 @@ services:
- "${MEDIA_ROOT}:${MEDIA_ROOT}"
celerybeat:
image: funkwhale/funkwhale:1.0
image: funkwhale/funkwhale:1.0.1
restart: unless-stopped
networks:
- myweb
@ -49,7 +49,7 @@ services:
apifunkwhale:
image: funkwhale/funkwhale:1.0
image: funkwhale/funkwhale:1.0.1
#image: funkwhale/funkwhale:develop
restart: unless-stopped
networks:

2
apps/gitea/docker-compose.yml

@ -12,7 +12,7 @@ services:
- myweb
gitea:
image: gitea/gitea:1.12.4
image: gitea/gitea:1.12.5
restart: unless-stopped
depends_on:
- dbgitea

202
apps/mailu/docker-compose.yml

@ -0,0 +1,202 @@
# This file is auto-generated by the Mailu configuration wizard.
# Please read the documentation before attempting any change.
# Generated for compose flavor
version: '2.2'
services:
# External dependencies
redis:
image: redis:alpine
restart: always
volumes:
- "/srv/apps/mailu/redis:/data"
# Core services
front:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
logging:
driver: json-file
ports:
#- "192.168.0.14:80:80"
#- "::1:80:80"
#- "192.168.0.14:443:443"
#- "::1:443:443"
- "192.168.9.20:25:25"
#- "::1:25:25"
- "192.168.9.20:465:465"
#- "::1:465:465"
- "192.168.9.20:587:587"
#- "::1:587:587"
- "192.168.9.20:110:110"
#- "::1:110:110"
- "192.168.9.20:995:995"
#- "::1:995:995"
- "192.168.9.20:143:143"
#- "::1:143:143"
- "192.168.9.20:993:993"
#- "::1:993:993"
#- "0.0.0.0:25:25"
#- "0.0.0.0:465:465"
#- "0.0.0.0:587:587"
#- "0.0.0.0:110:110"
#- "0.0.0.0:995:995"
#- "0.0.0.0:143:143"
#- "0.0.0.0:993:993"
#- "25:25"
#- "465:465"
#- "587:587"
#- "110:110"
#- "995:995"
#- "143:143"
#- "993:993"
volumes:
- "/srv/apps/mailu/certs:/certs"
- "/srv/apps/mailu/overrides/nginx:/overrides"
networks:
- myweb
- default
labels:
- "traefik.enable=true"
- "traefik.http.routers.courriel.rule=Host(`mail.goe.land`)"
- "traefik.http.routers.courriel.entrypoints=web"
- "traefik.http.routers.courrieltls.rule=Host(`mail.goe.land`)"
- "traefik.http.routers.courrieltls.entrypoints=websecure"
- "traefik.http.routers.courrieltls.tls=true"
- "traefik.http.routers.courrieltls.tls.certresolver=letsencrypt"
- "traefik.http.routers.courrieltls.tls.domains[0].main=*.goe.land"
#- "traefik.http.routers.courrieltls.tls.domains[0].sans=mail.goe.land"
- "traefik.http.services.courriel.loadbalancer.server.port=80"
- "traefik.docker.network=myweb"
resolver:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}unbound:${MAILU_VERSION:-1.7}
env_file: mailu.env
restart: always
networks:
default:
ipv4_address: 192.168.203.254
admin:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
#ports:
# - 127.0.0.1:8080:80
volumes:
- "/srv/apps/mailu/data:/data"
- "/srv/apps/mailu/dkim:/dkim"
depends_on:
- redis
networks:
- default
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.admincourriel.rule=Host(`admincourriel.goe.land`)"
# - "traefik.http.routers.admincourriel.entrypoints=web"
# - "traefik.http.routers.admincourrieltls.rule=Host(`admincourriel.goe.land`)"
# - "traefik.http.routers.admincourrieltls.entrypoints=websecure"
# - "traefik.http.routers.admincourrieltls.tls=true"
# - "traefik.http.routers.admincourrieltls.tls.certresolver=sample"
# - "traefik.docker.network=myweb"
imap:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
networks:
- default
volumes:
- "/srv/apps/mailu/mail:/mail"
- "/srv/apps/mailu/overrides:/overrides"
depends_on:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
networks:
- default
volumes:
- "/srv/apps/mailu/overrides:/overrides"
depends_on:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
volumes:
- "/srv/apps/mailu/filter:/var/lib/rspamd"
- "/srv/apps/mailu/dkim:/dkim"
- "/srv/apps/mailu/overrides/rspamd:/etc/rspamd/override.d"
depends_on:
- front
networks:
- default
# Optional services
# antivirus:
# image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}clamav:${MAILU_VERSION:-1.7}
# restart: always
# env_file: mailu.env
# volumes:
# - "/srv/apps/mailu/filter:/data"
# fetchmail:
# image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}fetchmail:${MAILU_VERSION:-1.7}
# restart: always
# env_file: mailu.env
# Webmail
webmail:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}roundcube:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
volumes:
- "/srv/apps/mailu/webmail:/data"
networks:
- default
depends_on:
- imap
database:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postgresql:${MAILU_VERSION:-1.7}
restart: always
env_file: mailu.env
volumes:
- "/srv/apps/mailu/data/psql_db:/data"
- "/srv/apps/mailu/data/psql_backup:/backup"
networks:
- default
certdumper:
image: mailu/traefik-certdumper:master
#image: unixfox/mailu-traefik-certdumper
restart: always
env_file: mailu.env
environment:
- DOMAIN=\*.goe.land
- TRAEFIK_VERSION=v2
# networks:
# - myweb
volumes:
- "/srv/core/front/certs:/traefik"
- "./certs:/output"
networks:
myweb:
external: true
default:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.203.0/24

4
apps/matrix/docker-compose.yml

@ -14,7 +14,7 @@ services:
synapse:
#image: docker.tedomum.net/tedomum/synapse:tedomum-prod
image: matrixdotorg/synapse:v1.21.2
image: matrixdotorg/synapse:v1.22.1
restart: unless-stopped
depends_on:
- dbsynapse
@ -45,7 +45,7 @@ services:
riot:
image: vectorim/riot-web:v1.7.10
image: vectorim/riot-web:v1.7.12
restart: unless-stopped
networks:
- myweb

133
apps/monitor/docker-compose.yml

@ -1,133 +0,0 @@
version: '3'
services:
grafana:
image: grafana/grafana:6.4.4
restart: unless-stopped
networks:
- myweb
volumes:
- './data/grafana:/var/lib/grafana'
env_file: .env
user: "472"
depends_on:
- loki
- prometheus
labels:
- "traefik.enable=true"
- "traefik.http.routers.surveillance.rule=Host(`surveillance.goe.land`)"
- "traefik.http.routers.surveillance.entrypoints=web"
- "traefik.http.routers.surveillancetls.rule=Host(`surveillance.goe.land`)"
- "traefik.http.routers.surveillancetls.entrypoints=websecure"
- "traefik.http.routers.surveillancetls.tls=true"
- "traefik.http.routers.surveillancetls.tls.certresolver=letsencrypt"
- "traefik.http.routers.surveillancetls.tls.domains[0].main=*.goe.land"
- "traefik.docker.network=myweb"
- "traefik.http.services.surveillance.loadbalancer.server.port=3000"
loki:
image: grafana/loki:v0.4.0
restart: unless-stopped
ports:
- 3100:3100
depends_on:
- promtail
volumes:
- ./data/loki:/data/loki
command: -config.file=/etc/loki/local-config.yaml
networks:
- myweb
env_file: .env
promtail:
image: grafana/promtail:v0.4.0
restart: unless-stopped
ports:
- 9080:9080
networks:
- myweb
volumes:
- '/var/log:/var/log:ro'
command: -config.file=/etc/promtail/docker-config.yaml
env_file: .env
prometheus:
image: prom/prometheus:v2.13.1
restart: unless-stopped
# depends_on:
# - cadvisor
ports:
- 9090:9090
networks:
- myweb
volumes:
- './data/prometheus_config:/etc/prometheus'
- './data/prometheus_data:/prometheus'
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
env_file: .env
#labels:
# - "traefik.enable=true"
# - "traefik.http.routers.prometheus.rule=Host(`prometheus.goe.land`)"
# - "traefik.http.routers.prometheus.entrypoints=web"
# - "traefik.http.routers.prometheustls.rule=Host(`prometheus.goe.land`)"
# - "traefik.http.routers.prometheustls.entrypoints=websecure"
# - "traefik.http.routers.prometheustls.tls=true"
# - "traefik.http.routers.prometheustls.tls.certresolver=sample"
# - "traefik.docker.network=myweb"
# - "traefik.http.services.prometheus.loadbalancer.server.port=9090"
cadvisor:
image: google/cadvisor:v0.33.0
restart: unless-stopped
ports:
- 8080:8080
networks:
- myweb
volumes:
- '/:/rootfs:ro'
- '/var/run:/var/run:rw'
- '/sys:/sys:ro'
- '/var/lib/docker/:/var/lib/docker:ro'
env_file: .env
# rediscadvisor:
# image: redis:5.0.6-alpine3.10
# restart: unless-stopped
# ports:
# - 6379:6379
# networks:
# - myweb
# nodeexporter:
# image: prom/node-exporter:v0.18.1
# restart: unless-stopped
# ports:
# - 9100:9100
# networks:
# - myweb
# volumes:
# - '/proc:/host/proc:ro'
# - '/sys:/host/sys:ro'
# - '/:/rootfs:ro'
# env_file: .env
# command:
# - '--path.procfs=/host/proc'
# - '--path.sysfs=/host/sys'
# - '--collector.filesystem.ignored-mount-points'
# - ^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)
networks:
myweb:
external: true

2
apps/rss-bridge/docker-compose.yml

@ -2,7 +2,7 @@ version: '3'
services:
rssbridge:
image: rssbridge/rss-bridge:2020-02-26
image: rssbridge/rss-bridge:2020-11-10
restart: unless-stopped
networks:
- myweb

102
apps/shaarli/plugins/markdown/README.md

@ -1,102 +0,0 @@
## Markdown Shaarli plugin
Convert all your shaares description to HTML formatted Markdown.
[Read more about Markdown syntax](http://daringfireball.net/projects/markdown/syntax).
Markdown processing is done with [Parsedown library](https://github.com/erusev/parsedown).
### Installation
As a default plugin, it should already be in `tpl/plugins/` directory.
If not, download and unpack it there.
The directory structure should look like:
```
--- plugins
|--- markdown
|--- help.html
|--- markdown.css
|--- markdown.meta
|--- markdown.php
|--- README.md
```
To enable the plugin, just check it in the plugin administration page.
You can also add `markdown` to your list of enabled plugins in `data/config.json.php`
(`general.enabled_plugins` list).
This should look like:
```
"general": {
"enabled_plugins": [
"markdown",
[...]
],
}
```
Parsedown parsing library is imported using Composer. If you installed Shaarli using `git`,
or the `master` branch, run
composer update --no-dev --prefer-dist
### No Markdown tag
If the tag `nomarkdown` is set for a shaare, it won't be converted to Markdown syntax.
> Note: this is a special tag, so it won't be displayed in link list.
### HTML escape
By default, HTML tags are escaped. You can enable HTML tags rendering
by setting `security.markdwon_escape` to `false` in `data/config.json.php`:
```json
{
"security": {
"markdown_escape": false
}
}
```
With this setting, Markdown support HTML tags. For example:
> <strong>strong</strong><strike>strike</strike>
Will render as:
> <strong>strong</strong><strike>strike</strike>
**Warning:**
* This setting might present **security risks** (XSS) on shared instances, even though tags
such as script, iframe, etc should be disabled.
* If you want to shaare HTML code, it is necessary to use inline code or code blocks.
* If your shaared descriptions contained HTML tags before enabling the markdown plugin,
enabling it might break your page.
### Known issue
#### Redirector
If you're using a redirector, you *need* to add a space after a link,
otherwise the rest of the line will be `urlencode`.
```
[link](http://domain.tld)-->test
```
Will consider `http://domain.tld)-->test` as URL.
Instead, add an additional space.
```
[link](http://domain.tld) -->test
```
> Won't fix because a `)` is a valid part of an URL.

5
apps/shaarli/plugins/markdown/help.html

@ -1,5 +0,0 @@
<div class="md_help">
%s
<a href="http://daringfireball.net/projects/markdown/syntax" title="%s">
%s</a>.
</div>

173
apps/shaarli/plugins/markdown/markdown.css

@ -1,173 +0,0 @@
/**
* Credit to Simon Laroche <https://github.com/simonlc/Markdown-CSS>
* whom created the CSS which this file is based on.
* License: Unlicense <http://unlicense.org/>
*/
.markdown p{
margin:0.75em 0;
}
.markdown img{
max-width:100%;
}
.markdown h1, .markdown h2, .markdown h3, .markdown h4, .markdown h5, .markdown h6{
font-weight:normal;
font-style:normal;
line-height:1em;
margin:0.75em 0;
}
.markdown h4, .markdown h5, .markdown h6{ font-weight: bold; }
.markdown h1{ font-size:2.5em; }
.markdown h2{ font-size:2em; }
.markdown h3{ font-size:1.5em; }
.markdown h4{ font-size:1.2em; }
.markdown h5{ font-size:1em; }
.markdown h6{ font-size:0.9em; }
.markdown blockquote{
color:#666666;
padding-left: 3em;
border-left: 0.5em #EEE solid;
margin:0.75em 0;
}
.markdown hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa;border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; }
.markdown pre, .markdown code, .markdown kbd, .markdown samp {
font-family: monospace, 'courier new';
font-size: 0.98em;
}
.markdown pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
.markdown b, .markdown strong { font-weight: bold; }
.markdown dfn, .markdown em { font-style: italic; }
.markdown ins { background: #ff9; color: #000; text-decoration: none; }
.markdown mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
.markdown sub, .markdown sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
.markdown sup { top: -0.5em; }
.markdown sub { bottom: -0.25em; }
.markdown ul, .markdown ol { margin: 1em 0; padding: 0 0 0 2em; }
.markdown li p:last-child { margin:0 }
.markdown dd { margin: 0 0 0 2em; }
.markdown img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
.markdown table { border-collapse: collapse; border-spacing: 0; }
.markdown td { vertical-align: top; }
@media only screen and (min-width: 480px) {
.markdown {font-size:0.9em;}
}
@media only screen and (min-width: 768px) {
.markdown {font-size:1em;}
}
#linklist .markdown li {
padding: 0;
border: none;
background: none;
}
#linklist .markdown ul li {
list-style: circle;
}
#linklist .markdown ol li {
list-style: decimal;
}
.markdown table {
padding: 0;
}
.markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0;
}
.markdown table tr:nth-child(2n) {
background-color: #f8f8f8;
}
.markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px;
}
.markdown table tr td {
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px;
}
.markdown table tr th :first-child, .markdown table tr td :first-child {
margin-top: 0;
}
.markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0;
}
.markdown pre {
background-color: #eee;
padding: 4px 9px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
overflow: auto;
box-shadow: 0 -1px 0 #e5e5e5,0 0 1px rgba(0,0,0,0.12),0 1px 2px rgba(0,0,0,0.24);
}
.markdown pre code {
color: black;
font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.7;
font-size: 11.5px;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
.markdown :not(pre) code {
background-color: #eee;
padding: 1px 3px;
border-radius: 1px;
box-shadow: 0 -1px 0 #e5e5e5,0 0 1px rgba(0,0,0,0.12),0 1px 1px rgba(0,0,0,0.24);
}
#pageheader .md_help {
color: white;
}
/*
Remove header links style
*/
#pageheader .md_help a {
color: lightgray;
font-weight: bold;
text-decoration: underline;
background: none;
box-shadow: none;
padding: 0;
margin: 0;
}
#pageheader .md_help a:hover {
color: white;
}

4
apps/shaarli/plugins/markdown/markdown.meta

@ -1,4 +0,0 @@
description="Render shaare description with Markdown syntax.<br><strong>Warning</strong>:
If your shaared descriptions contained HTML tags before enabling the markdown plugin,
enabling it might break your page.
See the <a href=\"https://github.com/shaarli/Shaarli/tree/master/plugins/markdown#html-rendering\">README</a>."

365
apps/shaarli/plugins/markdown/markdown.php

@ -1,365 +0,0 @@
<?php
/**
* Plugin Markdown.
*
* Shaare's descriptions are parsed with Markdown.
*/
use Shaarli\Config\ConfigManager;
use Shaarli\Plugin\PluginManager;
use Shaarli\Router;
/*
* If this tag is used on a shaare, the description won't be processed by Parsedown.
*/
define('NO_MD_TAG', 'nomarkdown');
/**
* Parse linklist descriptions.
*
* @param array $data linklist data.
* @param ConfigManager $conf instance.
*
* @return mixed linklist data parsed in markdown (and converted to HTML).
*/
function hook_markdown_render_linklist($data, $conf)
{
foreach ($data['links'] as &$value) {
if (!empty($value['tags']) && noMarkdownTag($value['tags'])) {
$value = stripNoMarkdownTag($value);
continue;
}
$value['description_src'] = $value['description'];
$value['description'] = process_markdown(
$value['description'],
$conf->get('security.markdown_escape', true),
$conf->get('security.allowed_protocols')
);
}
return $data;
}
/**
* Parse feed linklist descriptions.
*
* @param array $data linklist data.
* @param ConfigManager $conf instance.
*
* @return mixed linklist data parsed in markdown (and converted to HTML).
*/
function hook_markdown_render_feed($data, $conf)
{
foreach ($data['links'] as &$value) {
if (!empty($value['tags']) && noMarkdownTag($value['tags'])) {
$value = stripNoMarkdownTag($value);
continue;
}
$value['description'] = reverse_feed_permalink($value['description']);
$value['description'] = process_markdown(
$value['description'],
$conf->get('security.markdown_escape', true),
$conf->get('security.allowed_protocols')
);
}
return $data;
}
/**
* Parse daily descriptions.
*
* @param array $data daily data.
* @param ConfigManager $conf instance.
*
* @return mixed daily data parsed in markdown (and converted to HTML).
*/
function hook_markdown_render_daily($data, $conf)
{
//var_dump($data);die;
// Manipulate columns data
foreach ($data['linksToDisplay'] as &$value) {
if (!empty($value['tags']) && noMarkdownTag($value['tags'])) {
$value = stripNoMarkdownTag($value);
continue;
}
$value['formatedDescription'] = process_markdown(
$value['formatedDescription'],
$conf->get('security.markdown_escape', true),
$conf->get('security.allowed_protocols')
);
}
return $data;
}
/**
* Check if noMarkdown is set in tags.
*
* @param string $tags tag list
*
* @return bool true if markdown should be disabled on this link.
*/
function noMarkdownTag($tags)
{
return preg_match('/(^|\s)'. NO_MD_TAG .'(\s|$)/', $tags);
}
/**
* Remove the no-markdown meta tag so it won't be displayed.
*
* @param array $link Link data.
*
* @return array Updated link without no markdown tag.
*/
function stripNoMarkdownTag($link)
{
if (! empty($link['taglist'])) {
$offset = array_search(NO_MD_TAG, $link['taglist']);
if ($offset !== false) {
unset($link['taglist'][$offset]);
}
}
if (!empty($link['tags'])) {
str_replace(NO_MD_TAG, '', $link['tags']);
}
return $link;
}
/**
* When link list is displayed, include markdown CSS.
*
* @param array $data includes data.
*
* @return mixed - includes data with markdown CSS file added.
*/
function hook_markdown_render_includes($data)
{
if ($data['_PAGE_'] == Router::$PAGE_LINKLIST
|| $data['_PAGE_'] == Router::$PAGE_DAILY
|| $data['_PAGE_'] == Router::$PAGE_EDITLINK
) {
$data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css';
}
return $data;
}
/**
* Hook render_editlink.
* Adds an help link to markdown syntax.
*
* @param array $data data passed to plugin
*
* @return array altered $data.
*/
function hook_markdown_render_editlink($data)
{
// Load help HTML into a string
$txt = file_get_contents(PluginManager::$PLUGINS_PATH .'/markdown/help.html');
$translations = [
t('Description will be rendered with'),
t('Markdown syntax documentation'),
t('Markdown syntax'),
];
$data['edit_link_plugin'][] = vsprintf($txt, $translations);
// Add no markdown 'meta-tag' in tag list if it was never used, for autocompletion.
if (! in_array(NO_MD_TAG, $data['tags'])) {
$data['tags'][NO_MD_TAG] = 0;
}
return $data;
}
/**
* Remove HTML links auto generated by Shaarli core system.
* Keeps HREF attributes.
*
* @param string $description input description text.
*
* @return string $description without HTML links.
*/
function reverse_text2clickable($description)
{
$descriptionLines = explode(PHP_EOL, $description);
$descriptionOut = '';
$codeBlockOn = false;
$lineCount = 0;
foreach ($descriptionLines as $descriptionLine) {
// Detect line of code: starting with 4 spaces,
// except lists which can start with +/*/- or `2.` after spaces.
$codeLineOn = preg_match('/^ +(?=[^\+\*\-])(?=(?!\d\.).)/', $descriptionLine) > 0;
// Detect and toggle block of code
if (!$codeBlockOn) {
$codeBlockOn = preg_match('/^```/', $descriptionLine) > 0;
} elseif (preg_match('/^```/', $descriptionLine) > 0) {
$codeBlockOn = false;
}
$hashtagTitle = ' title="Hashtag [^"]+"';
// Reverse `inline code` hashtags.
$descriptionLine = preg_replace(
'!(`[^`\n]*)<a href="[^ ]*"'. $hashtagTitle .'>([^<]+)</a>([^`\n]*`)!m',
'$1$2$3',
$descriptionLine
);
// Reverse all links in code blocks, only non hashtag elsewhere.
$hashtagFilter = (!$codeBlockOn && !$codeLineOn) ? '(?!'. $hashtagTitle .')': '(?:'. $hashtagTitle .')?';
$descriptionLine = preg_replace(
'#<a href="[^ ]*"'. $hashtagFilter .'>([^<]+)</a>#m',
'$1',
$descriptionLine
);
// Make hashtag links markdown ready, otherwise the links will be ignored with escape set to true
if (!$codeBlockOn && !$codeLineOn) {
$descriptionLine = preg_replace(
'#<a href="([^ ]*)"'. $hashtagTitle .'>([^<]+)</a>#m',
'[$2]($1)',
$descriptionLine
);
}
$descriptionOut .= $descriptionLine;
if ($lineCount++ < count($descriptionLines) - 1) {
$descriptionOut .= PHP_EOL;
}
}
return $descriptionOut;
}
/**
* Remove <br> tag to let markdown handle it.
*
* @param string $description input description text.
*
* @return string $description without <br> tags.
*/
function reverse_nl2br($description)
{
return preg_replace('!<br */?>!im', '', $description);
}
/**
* Remove HTML spaces '&nbsp;' auto generated by Shaarli core system.
*
* @param string $description input description text.
*
* @return string $description without HTML links.
*/
function reverse_space2nbsp($description)
{
return preg_replace('/(^| )&nbsp;/m', '$1 ', $description);
}
function reverse_feed_permalink($description)
{
return preg_replace('@&#8212; <a href="([^"]+)" title="[^"]+">(\w+)</a>$@im', '&#8212; [$2]($1)', $description);
}
/**
* Replace not whitelisted protocols with http:// in given description.
*
* @param string $description input description text.
* @param array $allowedProtocols list of allowed protocols.
*
* @return string $description without malicious link.
*/
function filter_protocols($description, $allowedProtocols)
{
return preg_replace_callback(
'#]\((.*?)\)#is',
function ($match) use ($allowedProtocols) {
return ']('. whitelist_protocols($match[1], $allowedProtocols) .')';
},
$description
);
}
/**
* Remove dangerous HTML tags (tags, iframe, etc.).
* Doesn't affect <code> content (already escaped by Parsedown).
*
* @param string $description input description text.
*
* @return string given string escaped.
*/
function sanitize_html($description)
{
$escapeTags = array(
'script',
'style',
'link',
'iframe',
'frameset',
'frame',
);
foreach ($escapeTags as $tag) {
$description = preg_replace_callback(
'#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is',
function ($match) {
return escape($match[0]);
},
$description
);
}
$description = preg_replace(
'#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is',
'$1',
$description
);
return $description;
}
/**
* Render shaare contents through Markdown parser.
* 1. Remove HTML generated by Shaarli core.
* 2. Reverse the escape function.
* 3. Generate markdown descriptions.
* 4. Sanitize sensible HTML tags for security.
* 5. Wrap description in 'markdown' CSS class.
*
* @param string $description input description text.
* @param bool $escape escape HTML entities
*
* @return string HTML processed $description.
*/
function process_markdown($description, $escape = true, $allowedProtocols = [])
{
$parsedown = new Parsedown();
$processedDescription = $description;
$processedDescription = reverse_nl2br($processedDescription);
$processedDescription = reverse_space2nbsp($processedDescription);
$processedDescription = reverse_text2clickable($processedDescription);
$processedDescription = filter_protocols($processedDescription, $allowedProtocols);
$processedDescription = unescape($processedDescription);
$processedDescription = $parsedown
->setMarkupEscaped($escape)
->setBreaksEnabled(true)
->text($processedDescription);
$processedDescription = sanitize_html($processedDescription);
if (!empty($processedDescription)) {
$processedDescription = '<div class="markdown">'. $processedDescription . '</div>';
}
return $processedDescription;
}
/**
* This function is never called, but contains translation calls for GNU gettext extraction.
*/
function markdown_dummy_translation()
{
// meta
t('Render shaare description with Markdown syntax.<br><strong>Warning</strong>:
If your shaared descriptions contained HTML tags before enabling the markdown plugin,
enabling it might break your page.
See the <a href="https://github.com/shaarli/Shaarli/tree/master/plugins/markdown#html-rendering">README</a>.');
}
Loading…
Cancel
Save