mirror of
https://github.com/sorenpeter/timeline.git
synced 2025-12-15 19:07:01 +00:00
Merge branch 'tinyMDE'
Markdown UI via tinyMDE and Markdown render, Plus youtube embedding
This commit is contained in:
commit
eca76165db
11 changed files with 2318 additions and 324 deletions
1994
libs/Parsedown.php
Normal file
1994
libs/Parsedown.php
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,155 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Slimdown - A simple regex-based Markdown parser in PHP. Supports the
|
||||
* following elements (and can be extended via `Slimdown::add_rule()`):
|
||||
*
|
||||
* - Headers
|
||||
* - Links
|
||||
* - Bold
|
||||
* - Emphasis
|
||||
* - Deletions
|
||||
* - Quotes
|
||||
* - Code blocks
|
||||
* - Inline code
|
||||
* - Blockquotes
|
||||
* - Ordered/unordered lists
|
||||
* - Horizontal rules
|
||||
* - Images
|
||||
*
|
||||
* Author: Johnny Broadway <johnny@johnnybroadway.com>
|
||||
* Website: https://github.com/jbroadway/slimdown
|
||||
* License: MIT
|
||||
*/
|
||||
class Slimdown {
|
||||
public static $rules = array (
|
||||
'/```(.*?)```/s' => self::class .'::code_parse', // code blocks
|
||||
'/\n(#+)\s+(.*)/' => self::class .'::header', // headers
|
||||
'/\!\[([^\[]*?)\]\(([^\)]+)\)/' => self::class .'::img', // images
|
||||
'/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links
|
||||
'/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<strong>\2</strong>', // bold
|
||||
'/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<em>\2</em>', // emphasis
|
||||
'/(\~\~)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<del>\2</del>', // del
|
||||
'/\:\"(.*?)\"\:/' => '<q>\1</q>', // quote
|
||||
'/`(.*?)`/' => '<code>\1</code>', // inline code
|
||||
'/\n\*(.*)/' => self::class .'::ul_list', // ul lists
|
||||
'/\n[0-9]+\.(.*)/' => self::class .'::ol_list', // ol lists
|
||||
'/\n(>|\>)(.*)/' => self::class .'::blockquote', // blockquotes
|
||||
'/\n-{5,}/' => "\n<hr />", // horizontal rule
|
||||
'/\n([^\n]+)\n/' => self::class .'::para', // add paragraphs
|
||||
'/<\/ul>\s?<ul>/' => '', // fix extra ul
|
||||
'/<\/ol>\s?<ol>/' => '', // fix extra ol
|
||||
'/<\/blockquote><blockquote>/' => "\n", // fix extra blockquote
|
||||
'/<a href=\'(.*?)\'>/' => self::class .'::fix_link', // fix links
|
||||
'/<img src=\'(.*?)\'/' => self::class .'::fix_img', // fix images
|
||||
'/<p>{{{([0-9]+)}}}<\/p>/s' => self::class .'::reinsert_code_blocks' // re-insert code blocks
|
||||
);
|
||||
|
||||
private static $code_blocks = [];
|
||||
|
||||
private static function code_parse ($regs) {
|
||||
$item = $regs[1];
|
||||
$item = htmlentities ($item, ENT_COMPAT);
|
||||
$item = str_replace ("\n\n", '<br>', $item);
|
||||
$item = str_replace ("\n", '<br>', $item);
|
||||
while (mb_substr ($item, 0, 4) === '<br>') {
|
||||
$item = mb_substr ($item, 4);
|
||||
}
|
||||
while (mb_substr ($item, -4) === '<br>') {
|
||||
$item = mb_substr ($item, 0, -4);
|
||||
}
|
||||
// Store code blocks with placeholders to avoid other regexes affecting them
|
||||
self::$code_blocks[] = sprintf ("<pre><code>%s</code></pre>", trim ($item));
|
||||
return sprintf ("{{{%d}}}", count (self::$code_blocks) - 1);
|
||||
}
|
||||
|
||||
private static function reinsert_code_blocks ($regs) {
|
||||
// Reinsert the stored code blocks at the end
|
||||
$index = $regs[1];
|
||||
return self::$code_blocks[$index];
|
||||
}
|
||||
|
||||
private static function para ($regs) {
|
||||
$line = $regs[1];
|
||||
$trimmed = trim ($line);
|
||||
if (preg_match ('/^<\/?(ul|ol|li|h|p|bl|table|tr|th|td|code)/', $trimmed)) {
|
||||
return "\n" . $line . "\n";
|
||||
}
|
||||
if (! empty ($trimmed)) {
|
||||
//return sprintf ("\n<p>%s</p>\n", $trimmed);
|
||||
return sprintf ("\n%s\n", $trimmed);
|
||||
}
|
||||
return $trimmed;
|
||||
}
|
||||
|
||||
private static function ul_list ($regs) {
|
||||
$item = $regs[1];
|
||||
return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim ($item));
|
||||
}
|
||||
|
||||
private static function ol_list ($regs) {
|
||||
$item = $regs[1];
|
||||
return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim ($item));
|
||||
}
|
||||
|
||||
private static function blockquote ($regs) {
|
||||
$item = $regs[2];
|
||||
return sprintf ("\n<blockquote>%s</blockquote>", trim ($item));
|
||||
}
|
||||
|
||||
private static function header ($regs) {
|
||||
list ($tmp, $chars, $header) = $regs;
|
||||
$level = strlen ($chars);
|
||||
return sprintf ('<h%d>%s</h%d>', $level, trim ($header), $level);
|
||||
}
|
||||
|
||||
private static function link ($regs) {
|
||||
list ($tmp, $text, $link) = $regs;
|
||||
// Substitute _ and * in links so they don't break the URLs
|
||||
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
|
||||
return sprintf ('<a href=\'%s\'>%s</a>', $link, $text);
|
||||
}
|
||||
|
||||
private static function img ($regs) {
|
||||
list ($tmp, $text, $link) = $regs;
|
||||
// Substitute _ and * in links so they don't break the URLs
|
||||
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
|
||||
return sprintf ('<img src=\'%s\' alt=\'%s\' />', $link, $text);
|
||||
//return sprintf ('<img src=\'/thumb?image=%s\' alt=\'%s\' />', $link, $text); // added support for thumbnail generation on the fly
|
||||
}
|
||||
|
||||
private static function fix_link ($regs) {
|
||||
// Replace substitutions so links are preserved
|
||||
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
|
||||
return sprintf ('<a href=\'%s\'>', $fixed_link);
|
||||
}
|
||||
|
||||
private static function fix_img ($regs) {
|
||||
// Replace substitutions so links are preserved
|
||||
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
|
||||
return sprintf ('<img src=\'%s\'', $fixed_link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rule.
|
||||
*/
|
||||
public static function add_rule ($regex, $replacement) {
|
||||
self::$rules[$regex] = $replacement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render some Markdown into HTML.
|
||||
*/
|
||||
public static function render ($text) {
|
||||
self::$code_blocks = [];
|
||||
$text = "\n" . $text . "\n";
|
||||
foreach (self::$rules as $regex => $replacement) {
|
||||
if (is_callable ( $replacement)) {
|
||||
$text = preg_replace_callback ($regex, $replacement, $text);
|
||||
} else {
|
||||
$text = preg_replace ($regex, $replacement, $text);
|
||||
}
|
||||
}
|
||||
return trim ($text);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Slimdown - A simple regex-based Markdown parser in PHP. Supports the
|
||||
* following elements (and can be extended via `Slimdown::add_rule()`):
|
||||
*
|
||||
* - Headers
|
||||
* - Links
|
||||
* - Bold
|
||||
* - Emphasis
|
||||
* - Deletions
|
||||
* - Quotes
|
||||
* - Code blocks
|
||||
* - Inline code
|
||||
* - Blockquotes
|
||||
* - Ordered/unordered lists
|
||||
* - Horizontal rules
|
||||
* - Images
|
||||
*
|
||||
* Author: Johnny Broadway <johnny@johnnybroadway.com>
|
||||
* Website: https://github.com/jbroadway/slimdown
|
||||
* License: MIT
|
||||
*/
|
||||
class Slimdown {
|
||||
public static $rules = array (
|
||||
'/```(.*?)```/s' => self::class .'::code_parse', // code blocks
|
||||
//'/\n(#+)(.*)/' => self::class .'::header', // headers
|
||||
'/\n(#\s+)(.*)/' => self::class .'::header', // headers - only with a space between # and text, to avoid matching with `#hashtags`
|
||||
//'/\!\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::img', // images
|
||||
'/\!\[(.*?)\]\(([^\)]+)\)/' => self::class .'::img', // images 2
|
||||
'/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links
|
||||
'/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<strong>\2</strong>', // bold
|
||||
'/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<em>\2</em>', // emphasis
|
||||
'/(\~\~)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<del>\2</del>', // del
|
||||
'/\:\"(.*?)\"\:/' => '<q>\1</q>', // quote
|
||||
'/`(.*?)`/' => '<code>\1</code>', // inline code
|
||||
'/\n\*(.*)/' => self::class .'::ul_list', // ul lists
|
||||
'/\n[0-9]+\.(.*)/' => self::class .'::ol_list', // ol lists
|
||||
'/\n(>|\>)(.*)/' => self::class .'::blockquote', // blockquotes
|
||||
'/\n-{5,}/' => "\n<hr />", // horizontal rule
|
||||
'/\n([^\n]+)\n/' => self::class .'::para', // add paragraphs
|
||||
'/<\/ul>\s?<ul>/' => '', // fix extra ul
|
||||
'/<\/ol>\s?<ol>/' => '', // fix extra ol
|
||||
'/<\/blockquote><blockquote>/' => "\n", // fix extra blockquote
|
||||
'/<a href=\'(.*?)\'>/' => self::class .'::fix_link', // fix links
|
||||
'/<img src=\'(.*?)\'/' => self::class .'::fix_img', // fix images
|
||||
'/<p>{{{([0-9]+)}}}<\/p>/s' => self::class .'::reinsert_code_blocks' // re-insert code blocks
|
||||
);
|
||||
|
||||
private static $code_blocks = [];
|
||||
|
||||
private static function code_parse ($regs) {
|
||||
$item = $regs[1];
|
||||
$item = htmlentities ($item, ENT_COMPAT);
|
||||
$item = str_replace ("\n\n", '<br>', $item);
|
||||
$item = str_replace ("\n", '<br>', $item);
|
||||
while (mb_substr ($item, 0, 4) === '<br>') {
|
||||
$item = mb_substr ($item, 4);
|
||||
}
|
||||
while (mb_substr ($item, -4) === '<br>') {
|
||||
$item = mb_substr ($item, 0, -4);
|
||||
}
|
||||
// Store code blocks with placeholders to avoid other regexes affecting them
|
||||
self::$code_blocks[] = sprintf ("<pre><code>%s</code></pre>", trim ($item));
|
||||
return sprintf ("{{{%d}}}", count (self::$code_blocks) - 1);
|
||||
}
|
||||
|
||||
private static function reinsert_code_blocks ($regs) {
|
||||
// Reinsert the stored code blocks at the end
|
||||
$index = $regs[1];
|
||||
return self::$code_blocks[$index];
|
||||
}
|
||||
|
||||
private static function para ($regs) {
|
||||
$line = $regs[1];
|
||||
$trimmed = trim ($line);
|
||||
if (preg_match ('/^<\/?(ul|ol|li|h|p|bl|table|tr|th|td|code)/', $trimmed)) {
|
||||
return "\n" . $line . "\n";
|
||||
}
|
||||
if (! empty ($trimmed)) {
|
||||
//return sprintf ("\n<p>%s</p>\n", $trimmed);
|
||||
return sprintf ("\n%s\n", $trimmed); // avoind addin <p>-tags and extra vetical margins
|
||||
}
|
||||
return $trimmed;
|
||||
}
|
||||
|
||||
private static function ul_list ($regs) {
|
||||
$item = $regs[1];
|
||||
return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim ($item));
|
||||
}
|
||||
|
||||
private static function ol_list ($regs) {
|
||||
$item = $regs[1];
|
||||
return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim ($item));
|
||||
}
|
||||
|
||||
private static function blockquote ($regs) {
|
||||
$item = $regs[2];
|
||||
return sprintf ("\n<blockquote>%s</blockquote>", trim ($item));
|
||||
}
|
||||
|
||||
private static function header ($regs) {
|
||||
list ($tmp, $chars, $header) = $regs;
|
||||
$level = strlen ($chars);
|
||||
return sprintf ('<h%d>%s</h%d>', $level, trim ($header), $level);
|
||||
}
|
||||
|
||||
private static function link ($regs) {
|
||||
list ($tmp, $text, $link) = $regs;
|
||||
// Substitute _ and * in links so they don't break the URLs
|
||||
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
|
||||
return sprintf ('<a href=\'%s\'>%s</a>', $link, $text);
|
||||
}
|
||||
|
||||
private static function img ($regs) {
|
||||
list ($tmp, $text, $link) = $regs;
|
||||
// Substitute _ and * in links so they don't break the URLs
|
||||
$link = str_replace (['_', '*'], ['{^^^}', '{~~~}'], $link);
|
||||
return sprintf ('<img src=\'%s\' alt=\'%s\' />', $link, $text);
|
||||
}
|
||||
|
||||
private static function fix_link ($regs) {
|
||||
// Replace substitutions so links are preserved
|
||||
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
|
||||
return sprintf ('<a href=\'%s\'>', $fixed_link);
|
||||
}
|
||||
|
||||
private static function fix_img ($regs) {
|
||||
// Replace substitutions so links are preserved
|
||||
$fixed_link = str_replace (['{^^^}', '{~~~}'], ['_', '*'], $regs[1]);
|
||||
return sprintf ('<img src=\'%s\'', $fixed_link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rule.
|
||||
*/
|
||||
public static function add_rule ($regex, $replacement) {
|
||||
self::$rules[$regex] = $replacement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render some Markdown into HTML.
|
||||
*/
|
||||
public static function render ($text) {
|
||||
self::$code_blocks = [];
|
||||
$text = "\n" . $text . "\n";
|
||||
foreach (self::$rules as $regex => $replacement) {
|
||||
if (is_callable ( $replacement)) {
|
||||
$text = preg_replace_callback ($regex, $replacement, $text);
|
||||
} else {
|
||||
$text = preg_replace ($regex, $replacement, $text);
|
||||
}
|
||||
}
|
||||
return trim ($text);
|
||||
}
|
||||
}
|
||||
|
|
@ -169,7 +169,6 @@ a.author {
|
|||
line-height: 1;
|
||||
}
|
||||
|
||||
|
||||
.profile p {
|
||||
margin: 0.2rem 0;
|
||||
color: var(--text-light);
|
||||
|
|
@ -273,14 +272,33 @@ article .twt-msg {
|
|||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
article .twt-msg p {
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
article .twt-msg > blockquote {
|
||||
margin: 0;
|
||||
margin: 0.5rem 0;
|
||||
border-left: thick solid grey;
|
||||
padding: 0.25rem 0.5rem;
|
||||
display: inline-block;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
article .twt-msg ul,
|
||||
article .twt-msg ol {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
article .twt-msg li {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
article .twt-msg pre {
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
article .twt-msg img {
|
||||
margin: 0.25rem -0.25rem;
|
||||
display: block;
|
||||
|
|
@ -294,6 +312,14 @@ article .twt-msg > img:last-child {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
article .embed-video {
|
||||
margin-top: 0.5rem;
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 16/9;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
article small {
|
||||
font-size: small;
|
||||
}
|
||||
|
|
@ -320,7 +346,7 @@ article small a:hover {
|
|||
|
||||
#new_twt {
|
||||
border: none;
|
||||
text-align: center
|
||||
/* text-align: center*/
|
||||
}
|
||||
|
||||
#new_twt input[type="submit"] {
|
||||
|
|
|
|||
233
libs/tiny-mde.css
Normal file
233
libs/tiny-mde.css
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
.TinyMDE {
|
||||
/* background-color:#fff;
|
||||
color:#000;
|
||||
font-size:16px;
|
||||
line-height:24px;
|
||||
outline: none;
|
||||
padding:5px; */
|
||||
|
||||
color: var(--text);
|
||||
background-color: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
padding: 0.5rem;
|
||||
margin: 0.5rem 0;
|
||||
border-radius: var(--standard-border-radius);
|
||||
min-height: 6rem;
|
||||
}
|
||||
|
||||
/*
|
||||
.TMBlankLine {
|
||||
height:24px;
|
||||
}
|
||||
|
||||
.TMH1, .TMSetextH1 {
|
||||
font-size:22px;
|
||||
line-height:32px;
|
||||
font-weight:bold;
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
.TMSetextH1 {
|
||||
margin-bottom:0px;
|
||||
}
|
||||
|
||||
.TMSetextH1Marker {
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
.TMH2, .TMSetextH2 {
|
||||
font-size:20px;
|
||||
line-height:28px;
|
||||
font-weight:bold;
|
||||
margin-bottom:4px;
|
||||
}
|
||||
*/
|
||||
|
||||
.TMMark_TMCode {
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.TMFencedCodeBacktick, .TMFencedCodeTilde, .TMIndentedCode, .TMCode {
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
background-color: var(--accent-bg);
|
||||
}
|
||||
|
||||
.TMCodeFenceBacktickOpen, .TMCodeFenceTildeOpen {
|
||||
border-bottom: 1px solid var(--border);
|
||||
font-family: monospace;
|
||||
font-size:.9em;
|
||||
}
|
||||
|
||||
.TMCodeFenceBacktickClose, .TMCodeFenceTildeClose {
|
||||
border-top: 1px solid var(--border);
|
||||
font-family: monospace;
|
||||
font-size:.9em;
|
||||
}
|
||||
|
||||
.TMInfoString {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.TMCode {
|
||||
border:1px solid var(--border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.TMBlockquote {
|
||||
font-style: italic;
|
||||
border-left:2px solid var(--border);
|
||||
padding-left:10px;
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
/*
|
||||
.TMMark {
|
||||
color:#a0a0a0;
|
||||
}
|
||||
|
||||
.TMMark_TMH1, .TMMark_TMH2 {
|
||||
color:#ff8080;
|
||||
}
|
||||
*/
|
||||
|
||||
.TMMark_TMUL, .TMMark_TMOL {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.TMImage {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #00ff00;
|
||||
}
|
||||
|
||||
.TMLink {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: var(--accent);
|
||||
}
|
||||
|
||||
.TMLinkLabel {
|
||||
text-decoration: underline;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.TMLinkLabel_Definition, .TMLinkLabel_Valid {
|
||||
color: #40c040;
|
||||
}
|
||||
|
||||
.TMLinkLabel_Invalid {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.TMLinkTitle {
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
.TMLinkDestination, .TMAutolink {
|
||||
text-decoration: underline;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/*
|
||||
.TMHR {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.TMHR:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 50%;
|
||||
left: 40%;
|
||||
border-bottom: 2px solid #808080;
|
||||
width: 20%;
|
||||
z-index:0;
|
||||
}
|
||||
*/
|
||||
|
||||
.TMHTML, .TMHTMLBlock {
|
||||
font-family:monospace;
|
||||
font-size:.9em;
|
||||
color:#8000ff;
|
||||
}
|
||||
|
||||
.TMHTMLBlock {
|
||||
color:#6000c0;
|
||||
}
|
||||
|
||||
.TMCommandBar {
|
||||
/* background-color:#f8f8f8;
|
||||
height:24px;
|
||||
border:4px solid #f8f8f8; */
|
||||
box-sizing: content-box;
|
||||
display:flex;
|
||||
user-select: none;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.TMCommandBar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.TMCommandButton {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
height:24px;
|
||||
width:24px;
|
||||
padding:3px;
|
||||
margin-right:4px;
|
||||
color: var(--text-light);
|
||||
fill: var(--text-light);
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
font-size:20px;
|
||||
line-height:18px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.TMCommandDivider {
|
||||
box-sizing: content-box;
|
||||
height:24px;
|
||||
margin-left:4px;
|
||||
margin-right:8px;
|
||||
width:0px;
|
||||
/* border-left:1px solid var(--border);*/
|
||||
/* border-right:1px solid #ffffff;*/
|
||||
border-left:1px solid var(--border);
|
||||
}
|
||||
|
||||
.TMCommandButton_Active {
|
||||
font-weight: bold;
|
||||
color: var(--accent-bg);
|
||||
fill: var(--accent-bg);
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
.TMCommandButton_Inactive {
|
||||
/* background-color:#f8f8f8;*/
|
||||
background-color: var(--accent-bg);
|
||||
}
|
||||
|
||||
.TMCommandButton_Disabled {
|
||||
/* color:#a0a0a0;
|
||||
fill:#a0a0a0; */
|
||||
color: var(--text-light);
|
||||
fill: var(--text-light);
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.TMCommandButton_Active:hover,
|
||||
.TMCommandButton_Disabled:hover,
|
||||
.TMCommandButton_Inactive:hover {
|
||||
/* background-color:#e0e0ff;*/
|
||||
/* fill:#000000;*/
|
||||
fill: var(--accent);
|
||||
|
||||
}
|
||||
}
|
||||
1
libs/tiny-mde.min.css
vendored
Normal file
1
libs/tiny-mde.min.css
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.TinyMDE{background-color:#fff;color:#000;font-size:16px;line-height:24px;outline:none;padding:5px}.TMBlankLine{height:24px}.TMH1,.TMSetextH1{font-size:22px;font-weight:700;line-height:32px;margin-bottom:8px}.TMSetextH1{margin-bottom:0}.TMSetextH1Marker{margin-bottom:8px}.TMH2,.TMSetextH2{font-size:20px;font-weight:700;line-height:28px;margin-bottom:4px}.TMMark_TMCode{font-family:monospace;font-size:.9em}.TMCode,.TMFencedCodeBacktick,.TMFencedCodeTilde,.TMIndentedCode{background-color:#e0e0e0;font-family:monospace;font-size:.9em}.TMCodeFenceBacktickOpen,.TMCodeFenceTildeOpen{border-bottom:1px solid silver;font-family:monospace;font-size:.9em}.TMCodeFenceBacktickClose,.TMCodeFenceTildeClose{border-top:1px solid silver;font-family:monospace;font-size:.9em}.TMInfoString{color:#00f}.TMCode{border:1px solid silver;border-radius:2px}.TMBlockquote{border-left:2px solid silver;font-style:italic;margin-left:10px;padding-left:10px}.TMMark{color:#a0a0a0}.TMMark_TMH1,.TMMark_TMH2,.TMMark_TMOL,.TMMark_TMUL{color:#ff8080}.TMImage{text-decoration:underline;text-decoration-color:#0f0}.TMLink{text-decoration:underline;text-decoration-color:#00f}.TMLinkLabel{font-family:monospace;text-decoration:underline}.TMLinkLabel_Definition,.TMLinkLabel_Valid{color:#40c040}.TMLinkLabel_Invalid{color:red}.TMLinkTitle{font-style:italic}.TMAutolink,.TMLinkDestination{color:#00f;text-decoration:underline}.TMHR{position:relative}.TMHR:before{border-bottom:2px solid grey;bottom:50%;content:"";left:40%;position:absolute;width:20%;z-index:0}.TMHTML,.TMHTMLBlock{color:#8000ff;font-family:monospace;font-size:.9em}.TMHTMLBlock{color:#6000c0}.TMCommandBar{-ms-overflow-style:none;background-color:#f8f8f8;border:4px solid #f8f8f8;box-sizing:content-box;display:flex;height:24px;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none;-webkit-user-select:none;user-select:none}.TMCommandBar::-webkit-scrollbar{display:none}.TMCommandButton{fill:#404040;box-sizing:border-box;color:#404040;cursor:pointer;display:inline-block;font-family:sans-serif;font-size:20px;height:24px;line-height:18px;margin-right:4px;padding:3px;text-align:center;vertical-align:middle;width:24px}.TMCommandDivider{border-left:1px solid silver;border-right:1px solid #fff;box-sizing:content-box;height:24px;margin-left:4px;margin-right:8px;width:0}.TMCommandButton_Active{fill:navy;background-color:#c0c0ff;color:navy;font-weight:700}.TMCommandButton_Inactive{background-color:#f8f8f8}.TMCommandButton_Disabled{fill:#a0a0a0;color:#a0a0a0}@media (hover:hover){.TMCommandButton_Active:hover,.TMCommandButton_Disabled:hover,.TMCommandButton_Inactive:hover{fill:#000;background-color:#e0e0ff}}
|
||||
1
libs/tiny-mde.min.js
vendored
Normal file
1
libs/tiny-mde.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -125,6 +125,8 @@ function getImagesFromTwt(string $twtString) {
|
|||
function getTagsFromTwt(string $twtString) {
|
||||
//$pattern = '/(?<!\()\B#\w+(?!\))/iu';
|
||||
$pattern = '/(?<=\B)#(\w+)/';
|
||||
//$pattern = '/(?<=\s)#(\w+)/';
|
||||
//$pattern = '/\s#(\w+)/';
|
||||
//$pattern = "/\(#\w{7}\)/";
|
||||
//$pattern = '/(?<=\s|^)#(\w+)/';
|
||||
// TODO: Fix so it does not match with url#fragments (\B vs \s)
|
||||
|
|
@ -181,7 +183,8 @@ function replaceLinksFromTwt(string $twtString) {
|
|||
// 1. Look into how yarnd handles this
|
||||
|
||||
// Regular expression pattern to match URLs
|
||||
$pattern = '/(?<!\S)(\b(https?|ftp|gemini|spartan|gopher):\/\/\S+|\b(?!:\/\/)\w+(?:\.\w+)+(?:\/\S+)?)(?!\S)/';
|
||||
//$pattern = '/(?<!\S)(\b(https?|ftp|gemini|spartan|gopher):\/\/\S+|\b(?!:\/\/)\w+(?:\.\w+)+(?:\/\S+)?)(?!\S)/';
|
||||
$pattern = '/(?<!\S)(?<!href="|">)(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/is';
|
||||
|
||||
// Replace URLs with clickable links
|
||||
$replacement = '<a href="$1">$1</a>';
|
||||
|
|
@ -209,7 +212,9 @@ function replaceImagesFromTwt(string $twtString) {
|
|||
}
|
||||
|
||||
function replaceTagsFromTwt(string $twtString) {
|
||||
$pattern = '/#(\w+)?/';
|
||||
//$pattern = '/#(\w+)?/';
|
||||
$pattern = '/(?<=\s)#(\w+)/';
|
||||
|
||||
//$replacement = '<a href="#">#\1</a>'; // Dummy link
|
||||
$replacement = '<a href="?search=$1" class="tag">#${1}</a>';
|
||||
$result = preg_replace($pattern, $replacement, $twtString);
|
||||
|
|
@ -217,6 +222,25 @@ function replaceTagsFromTwt(string $twtString) {
|
|||
return $result;
|
||||
}
|
||||
|
||||
function embedYoutubeFromTwt(string $twtString) {
|
||||
|
||||
// original regex source: https://gist.github.com/afeld/1254889#gistcomment-1253992
|
||||
$pattern = '/(?:youtube(?:-nocookie)?\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/mi';
|
||||
|
||||
if(preg_match_all($pattern, $twtString, $youtubeLinks)) {
|
||||
|
||||
$youtubeLinks = array_unique($youtubeLinks[1]); // Remove dublicate cause by raw URLs conceverter to links
|
||||
|
||||
foreach ($youtubeLinks as $videoID) {
|
||||
$twtString .= '<iframe loading="lazy" src="https://www.youtube.com/embed/'.$videoID.'" class="embed-video" allow="encrypted-media" title="" allowfullscreen="allowfullscreen" frameborder="0"></iframe>';
|
||||
}
|
||||
}
|
||||
|
||||
$result = $twtString;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
function getTimeElapsedString($timestamp, $full = false) {
|
||||
$now = new DateTime;
|
||||
|
|
@ -407,12 +431,17 @@ function getTwtsFromTwtxtString($url) {
|
|||
|
||||
// For some reason I was having trouble finding this nomenclature
|
||||
// that's why I leave the UTF-8 representation for future reference
|
||||
$twtContent = str_replace("\u{2028}", "\n<br>\n", $twtContent);
|
||||
//$twtContent = str_replace("\u{2028}", "\n<br>\n", $twtContent);
|
||||
$twtContent = str_replace("\u{2028}", "\n", $twtContent);
|
||||
|
||||
$twtContent = replaceMarkdownLinksFromTwt($twtContent);
|
||||
$twtContent = replaceImagesFromTwt($twtContent);
|
||||
//$twtContent = Slimdown::render($twtContent);
|
||||
$twtContent = replaceLinksFromTwt($twtContent); // TODO:
|
||||
//$twtContent = replaceMarkdownLinksFromTwt($twtContent);
|
||||
//$twtContent = replaceImagesFromTwt($twtContent);
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
$twtContent = $Parsedown->text($twtContent);
|
||||
|
||||
$twtContent = embedYoutubeFromTwt($twtContent);
|
||||
//$twtContent = replaceLinksFromTwt($twtContent);
|
||||
|
||||
// Get and remove the hash
|
||||
$hash = getReplyHashFromTwt($twtContent);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ declare (strict_types = 1);
|
|||
require_once('libs/session.php');
|
||||
require_once('libs/twtxt.php');
|
||||
require_once('libs/hash.php');
|
||||
require_once('libs/Slimdown.php');
|
||||
require_once('libs/Parsedown.php');
|
||||
|
||||
const TWTS_PER_PAGE = 50;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ $profile = getTwtsFromTwtxtString($config['public_txt_url']);
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="<?= $baseURL ?>/media/logo.png">
|
||||
<?php if( isset($_SESSION['password'])) { ?>
|
||||
<script src="<?= $baseURL ?>/libs/tiny-mde.min.js"></script>
|
||||
<!-- <link rel="stylesheet" type="text/css" href="<?= $baseURL ?>/libs/tiny-mde.min.css" /> -->
|
||||
<link rel="stylesheet" type="text/css" href="<?= $baseURL ?>/libs/tiny-mde.css" />
|
||||
<?php } ?>
|
||||
<link rel="stylesheet" type="text/css" href="<?= $baseURL ?>/libs/simple.css">
|
||||
<link rel="stylesheet" type="text/css" href="<?= $baseURL ?>/libs/timeline.css">
|
||||
<link rel="stylesheet" type="text/css" href="<?= $baseURL ?>/custom.css">
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// TODO: Give a warning if the file is not found
|
||||
$config = parse_ini_file('private/config.ini');
|
||||
|
||||
|
||||
if ($config['debug_mode']) {
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
|
|
@ -151,12 +152,27 @@ if (isset($_GET['hash'])) {
|
|||
<article id="new_twt">
|
||||
<form method="POST">
|
||||
<div id="posting">
|
||||
<div id="toolbar"></div>
|
||||
<textarea class="textinput" id="new_post" name="new_post"
|
||||
rows="4" cols="100" autofocus required onfocus="var val=this.value; this.value=''; this.value= val;"
|
||||
placeholder="Your twt"><?= $textareaValue ?></textarea>
|
||||
<!-- <br> -->
|
||||
<input type="submit" value="Post" name="submit">
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var tinyMDE = new TinyMDE.Editor({
|
||||
element: "new_post",
|
||||
// content: "Type your twt"
|
||||
});
|
||||
var commandBar = new TinyMDE.CommandBar({
|
||||
element: "toolbar",
|
||||
editor: tinyMDE,
|
||||
commands: ['bold', 'italic', 'strikethrough', 'ul', 'ol', 'blockquote', 'code', '|', 'insertLink', 'insertImage'],
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</form>
|
||||
</article>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue