mirror of
https://github.com/typemill/typemill.git
synced 2025-10-17 07:36:24 +02:00
Version 1.2.8 Image Management
This commit is contained in:
2
cache/lastCache.txt
vendored
2
cache/lastCache.txt
vendored
@@ -1 +1 @@
|
||||
1541856493
|
||||
1543829895
|
@@ -2,4 +2,5 @@
|
||||
|
||||
**MODERN WEB PUBLISHING FOR WRITERS**
|
||||
|
||||
*Typemill is a user-friendly and lightweight open source CMS for publishing text-works like prosa, lyrics, manuals, documentations, studies and more. Just download and start.*
|
||||
*Typemill is a user-friendly and lightweight open source CMS for publishing text-works like prosa, lyrics, manuals, documentations, studies and more. Just download and start.*
|
||||
|
||||
|
BIN
media/original/5bf950ebf2abc-original.png
Normal file
BIN
media/original/5bf950ebf2abc-original.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
13
readme.md
13
readme.md
@@ -45,7 +45,18 @@ The GitHub-version has no vendor-folder, so you have to update and include all l
|
||||
|
||||
If you did not use composer before, please go to the [composer website](http://getcomposer.org) and start to learn.
|
||||
|
||||
To run TYPEMILL on a **live** system, simply upload the files to your server.
|
||||
To run TYPEMILL on a **live** system, simply upload the files to your server
|
||||
|
||||
## Make Folders Writable.
|
||||
|
||||
Make sure that the following folders and all their content are writable (permission 774 recursively):
|
||||
|
||||
* cache
|
||||
* content
|
||||
* media
|
||||
* settings
|
||||
|
||||
You can use your ftp-software for that.
|
||||
|
||||
## Setup
|
||||
|
||||
|
@@ -6,6 +6,7 @@ use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
use Typemill\Models\Folder;
|
||||
use Typemill\Models\Write;
|
||||
use Typemill\Models\ProcessImage;
|
||||
use Typemill\Extensions\ParsedownExtension;
|
||||
|
||||
class ContentApiController extends ContentController
|
||||
@@ -755,6 +756,7 @@ class ContentApiController extends ContentController
|
||||
/* get params from call */
|
||||
$this->params = $request->getParams();
|
||||
$this->uri = $request->getUri();
|
||||
$errors = false;
|
||||
|
||||
# set structure
|
||||
if(!$this->setStructure($draft = true)){ return $response->withJson(array('data' => false, 'errors' => $this->errors), 404); }
|
||||
@@ -792,6 +794,25 @@ class ContentApiController extends ContentController
|
||||
# check if id exists
|
||||
if(!isset($this->content[$this->params['block_id']])){ return $response->withJson(array('data' => false, 'errors' => 'The ID of the content-block is wrong.'), 404); }
|
||||
|
||||
# check if block is image
|
||||
$contentBlock = $this->content[$this->params['block_id']];
|
||||
$contentBlockStart = substr($contentBlock, 0, 2);
|
||||
if($contentBlockStart == '[!' OR $contentBlockStart == '![')
|
||||
{
|
||||
# extract image path
|
||||
preg_match("/\((.*?)\)/",$contentBlock,$matches);
|
||||
if(isset($matches[1]))
|
||||
{
|
||||
$imageBaseName = explode('-', $matches[1]);
|
||||
$imageBaseName = str_replace('media/live/', '', $imageBaseName[0]);
|
||||
$processImage = new ProcessImage();
|
||||
if(!$processImage->deleteImage($imageBaseName))
|
||||
{
|
||||
$errors = 'Could not delete some of the images, please check manually';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# delete the block
|
||||
unset($this->content[$this->params['block_id']]);
|
||||
$this->content = array_values($this->content);
|
||||
@@ -821,6 +842,41 @@ class ContentApiController extends ContentController
|
||||
return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404);
|
||||
}
|
||||
|
||||
return $response->withJson(array('markdown' => $pageMarkdown, 'errors' => false));
|
||||
return $response->withJson(array('markdown' => $pageMarkdown, 'errors' => $errors));
|
||||
}
|
||||
|
||||
public function createImage(Request $request, Response $response, $args)
|
||||
{
|
||||
/* get params from call */
|
||||
$this->params = $request->getParams();
|
||||
$this->uri = $request->getUri();
|
||||
|
||||
$imageProcessor = new ProcessImage();
|
||||
|
||||
if($imageProcessor->createImage($this->params['image'], $this->settings['images'], $name = false))
|
||||
{
|
||||
return $response->withJson(array('errors' => false));
|
||||
}
|
||||
|
||||
return $response->withJson(array('errors' => 'could not store image to temporary folder'));
|
||||
}
|
||||
|
||||
public function publishImage(Request $request, Response $response, $args)
|
||||
{
|
||||
$params = $request->getParsedBody();
|
||||
|
||||
$imageProcessor = new ProcessImage();
|
||||
|
||||
$imageUrl = $imageProcessor->publishImage($this->settings['images'], $name = false);
|
||||
if($imageUrl)
|
||||
{
|
||||
$params['markdown'] = str_replace('imgplchldr', $imageUrl, $params['markdown']);
|
||||
|
||||
$request = $request->withParsedBody($params);
|
||||
|
||||
return $this->updateBlock($request, $response, $args);
|
||||
}
|
||||
|
||||
return $response->withJson(array('errors' => 'could not store image to temporary folder'));
|
||||
}
|
||||
}
|
@@ -23,7 +23,7 @@ class ContentBackendController extends ContentController
|
||||
# get params from call
|
||||
$this->uri = $request->getUri();
|
||||
$this->params = isset($args['params']) ? ['url' => $this->uri->getBasePath() . '/' . $args['params']] : ['url' => $this->uri->getBasePath()];
|
||||
|
||||
|
||||
# set structure
|
||||
if(!$this->setStructure($draft = true)){ return $this->renderIntern404($response, array( 'navigation' => true, 'content' => $this->errors )); }
|
||||
|
||||
@@ -71,7 +71,7 @@ class ContentBackendController extends ContentController
|
||||
$content = trim($contentParts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->render($response, 'editor/editor-raw.twig', array('navigation' => $this->structure, 'title' => $title, 'content' => $content, 'item' => $this->item, 'settings' => $this->settings ));
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ class ContentBackendController extends ContentController
|
||||
|
||||
public function showBlox(Request $request, Response $response, $args)
|
||||
{
|
||||
|
||||
# get params from call
|
||||
$this->uri = $request->getUri();
|
||||
$this->params = isset($args['params']) ? ['url' => $this->uri->getBasePath() . '/' . $args['params']] : ['url' => $this->uri->getBasePath()];
|
||||
@@ -100,7 +101,7 @@ class ContentBackendController extends ContentController
|
||||
|
||||
# set the status for published and drafted
|
||||
$this->setPublishStatus();
|
||||
|
||||
|
||||
# set path
|
||||
$this->setItemPath($this->item->fileType);
|
||||
|
||||
@@ -133,12 +134,16 @@ class ContentBackendController extends ContentController
|
||||
$contentArray = $parsedown->text($block);
|
||||
|
||||
/* parse markdown-content-array to content-string */
|
||||
$content[$key] = $parsedown->markup($contentArray);
|
||||
$content[$key] = $parsedown->markup($contentArray);
|
||||
}
|
||||
|
||||
# extract title and delete from content array, array will start at 1 after that.
|
||||
$title = $content[0];
|
||||
unset($content[0]);
|
||||
$title = '# add title';
|
||||
if(isset($content[0]))
|
||||
{
|
||||
$title = $content[0];
|
||||
unset($content[0]);
|
||||
}
|
||||
|
||||
return $this->render($response, 'editor/editor-blox.twig', array('navigation' => $this->structure, 'title' => $title, 'content' => $content, 'item' => $this->item, 'settings' => $this->settings ));
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ class SettingsController extends Controller
|
||||
/* store them as default theme data with author, year, default settings and field-definitions */
|
||||
$themedata[$themeName] = $themeSettings;
|
||||
}
|
||||
|
||||
|
||||
if(isset($themeSettings['forms']['fields']))
|
||||
{
|
||||
$fields = $this->getFields($userSettings, 'themes', $themeName, $themeSettings);
|
||||
@@ -271,6 +271,12 @@ class SettingsController extends Controller
|
||||
$themeName = isset($params['theme']) ? $params['theme'] : false;
|
||||
$userInput = isset($params[$themeName]) ? $params[$themeName] : false;
|
||||
$validate = new Validation();
|
||||
$themeSettings = \Typemill\Settings::getObjectSettings('themes', $themeName);
|
||||
|
||||
if(isset($themeSettings['settings']['images']))
|
||||
{
|
||||
$userSettings = ['images' => $themeSettings['settings']['images']];
|
||||
}
|
||||
|
||||
/* set theme name and delete theme settings from user settings for the case, that the new theme has no settings */
|
||||
$userSettings['theme'] = $themeName;
|
||||
|
@@ -333,12 +333,12 @@ class ParsedownExtension extends \ParsedownExtra
|
||||
}
|
||||
|
||||
$block = trim($block, "\n");
|
||||
|
||||
|
||||
$cleanBlocks[] = $block;
|
||||
}
|
||||
return $cleanBlocks;
|
||||
}
|
||||
|
||||
|
||||
public function arrayBlocksToMarkdown(array $arrayBlocks)
|
||||
{
|
||||
$markdown = '';
|
||||
|
325
system/Models/ProcessImage.php
Normal file
325
system/Models/ProcessImage.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
namespace Typemill\Models;
|
||||
|
||||
class ProcessImage
|
||||
{
|
||||
public function createImage(string $image, array $desiredSizes, $name)
|
||||
{
|
||||
# fix error from jpeg-library
|
||||
ini_set ('gd.jpeg_ignore_warning', 1);
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
|
||||
# clear temporary folder
|
||||
$this->clearTempFolder();
|
||||
|
||||
# decode the image from base64-string
|
||||
$imageDecoded = $this->decodeImage($image);
|
||||
$imageData = $imageDecoded["image"];
|
||||
$imageType = $imageDecoded["type"];
|
||||
|
||||
# transform image-stream into image
|
||||
$image = imagecreatefromstring($imageData);
|
||||
|
||||
# get the size of the original image
|
||||
$imageSize = $this->getImageSize($image);
|
||||
|
||||
# check the desired sizes and calculate the height, if not set
|
||||
$desiredSizes = $this->setHeight($imageSize, $desiredSizes);
|
||||
|
||||
# resize the images
|
||||
$resizedImages = $this->imageResize($image, $imageSize, $desiredSizes, $imageType);
|
||||
|
||||
$basePath = getcwd() . DIRECTORY_SEPARATOR . 'media';
|
||||
$tmpFolder = $basePath . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->saveOriginal($tmpFolder, $imageData, 'original', $imageType);
|
||||
|
||||
if($imageType == "gif" && $this->detectAnimatedGif($imageData))
|
||||
{
|
||||
$this->saveOriginal($tmpFolder, $imageData, 'live', $imageType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
# temporary store resized images
|
||||
foreach($resizedImages as $key => $resizedImage)
|
||||
{
|
||||
$this->saveImage($tmpFolder, $resizedImage, $key, $imageType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function detectAnimatedGif($image_file_contents)
|
||||
{
|
||||
$is_animated = preg_match('#(\x00\x21\xF9\x04.{4}\x00\x2C.*){2,}#s', $image_file_contents);
|
||||
if ($is_animated == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function publishImage(array $desiredSizes)
|
||||
{
|
||||
/* get images from tmp folder */
|
||||
$basePath = getcwd() . DIRECTORY_SEPARATOR . 'media';
|
||||
$tmpFolder = $basePath . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
|
||||
$originalFolder = $basePath . DIRECTORY_SEPARATOR . 'original' . DIRECTORY_SEPARATOR;
|
||||
$liveFolder = $basePath . DIRECTORY_SEPARATOR . 'live' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$name = uniqid();
|
||||
|
||||
$files = scandir($tmpFolder);
|
||||
$success = true;
|
||||
|
||||
foreach($files as $file)
|
||||
{
|
||||
if (!in_array($file, array(".","..")))
|
||||
{
|
||||
$tmpfilename = explode(".", $file);
|
||||
|
||||
if($tmpfilename[0] == 'original')
|
||||
{
|
||||
$success = rename($tmpFolder . $file, $originalFolder . $name . '-' . $file);
|
||||
}
|
||||
else
|
||||
{
|
||||
$success = rename($tmpFolder . $file, $liveFolder . $name . '-' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($success)
|
||||
{
|
||||
return 'media/live/' . $name . '-live.' . $tmpfilename[1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function decodeImage(string $image)
|
||||
{
|
||||
$imageParts = explode(";base64,", $image);
|
||||
$imageType = explode("/", $imageParts[0]);
|
||||
$imageData = base64_decode($imageParts[1]);
|
||||
|
||||
if ($imageData !== false)
|
||||
{
|
||||
return array("image" => $imageData, "type" => $imageType[1]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getImageSize($image)
|
||||
{
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
return array('width' => $width, 'height' => $height);
|
||||
}
|
||||
|
||||
public function setHeight(array $imageSize, array $desiredSizes)
|
||||
{
|
||||
foreach($desiredSizes as $key => $desiredSize)
|
||||
{
|
||||
if($desiredSize['width'] > $imageSize['width'])
|
||||
{
|
||||
$desiredSizes[$key] = $imageSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!isset($desiredSize['height']))
|
||||
{
|
||||
$resizeFactor = $imageSize['width'] / $desiredSize['width'];
|
||||
$desiredSizes[$key]['height'] = round( ($imageSize['height'] / $resizeFactor), 0);
|
||||
}
|
||||
}
|
||||
return $desiredSizes;
|
||||
}
|
||||
|
||||
public function imageResize($imageData, array $imageSize, array $desiredSizes, $imageType)
|
||||
{
|
||||
$copiedImages = array();
|
||||
$source_aspect_ratio = $imageSize['width'] / $imageSize['height'];
|
||||
|
||||
#check transparency
|
||||
$transparent_index = false;
|
||||
|
||||
if ($imageType = ("png" || "gif"))
|
||||
{
|
||||
$transparent_index = imagecolortransparent($imageData);
|
||||
}
|
||||
|
||||
foreach($desiredSizes as $key => $desiredSize)
|
||||
{
|
||||
$desired_aspect_ratio = $desiredSize['width'] / $desiredSize['height'];
|
||||
|
||||
if ( $source_aspect_ratio > $desired_aspect_ratio )
|
||||
{
|
||||
# when source image is wider
|
||||
$temp_height = $desiredSize['height'];
|
||||
$temp_width = ( int ) ($desiredSize['height'] * $source_aspect_ratio);
|
||||
$temp_width = round($temp_width, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
# when source image is similar or taller
|
||||
$temp_width = $desiredSize['width'];
|
||||
$temp_height = ( int ) ($desiredSize['width'] / $source_aspect_ratio);
|
||||
$temp_height = round($temp_height, 0);
|
||||
}
|
||||
|
||||
# Create a temporary GD image with desired size
|
||||
$temp_gdim = imagecreatetruecolor( $temp_width, $temp_height );
|
||||
|
||||
if ($transparent_index >= 0 && $imageType == "gif")
|
||||
{
|
||||
imagepalettecopy($imageData, $temp_gdim);
|
||||
imagefill($temp_gdim, 0, 0, $transparent_index);
|
||||
imagecolortransparent($temp_gdim, $transparent_index);
|
||||
imagetruecolortopalette($temp_gdim, true, 256);
|
||||
}
|
||||
elseif($transparent_index >= 0 && $imageType == "png")
|
||||
{
|
||||
imagealphablending($temp_gdim, false);
|
||||
imagesavealpha($temp_gdim,true);
|
||||
$transparent = imagecolorallocatealpha($temp_gdim, 255, 255, 255, 127);
|
||||
imagefilledrectangle($temp_gdim, 0, 0, $temp_width, $temp_height, $transparent);
|
||||
}
|
||||
|
||||
imagecopyresampled(
|
||||
$temp_gdim,
|
||||
$imageData,
|
||||
0, 0,
|
||||
0, 0,
|
||||
$temp_width, $temp_height,
|
||||
$imageSize['width'], $imageSize['height']
|
||||
);
|
||||
|
||||
# Copy cropped region from temporary image into the desired GD image
|
||||
$x0 = ( $temp_width - $desiredSize['width'] ) / 2;
|
||||
$y0 = ( $temp_height - $desiredSize['height'] ) / 2;
|
||||
|
||||
$desired_gdim = imagecreatetruecolor( $desiredSize['width'], $desiredSize['height'] );
|
||||
|
||||
if ($transparent_index >= 0 && $imageType == "gif")
|
||||
{
|
||||
# GIF
|
||||
imagepalettecopy($imageData, $desired_gdim);
|
||||
imagefill($desired_gdim, 0, 0, $transparent_index);
|
||||
imagecolortransparent($desired_gdim, $transparent_index);
|
||||
imagetruecolortopalette($desired_gdim, true, 256);
|
||||
}
|
||||
if ($transparent_index >= 0 && $imageType == "png")
|
||||
{
|
||||
imagealphablending($desired_gdim, false);
|
||||
imagesavealpha($desired_gdim,true);
|
||||
$transparent = imagecolorallocatealpha($desired_gdim, 255, 255, 255, 127);
|
||||
imagefilledrectangle($desired_gdim, 0, 0, $desiredSize['width'], $desiredSize['height'], $transparent);
|
||||
}
|
||||
|
||||
imagecopy(
|
||||
$desired_gdim,
|
||||
$temp_gdim,
|
||||
0, 0,
|
||||
$x0, $y0,
|
||||
$desiredSize['width'], $desiredSize['height']
|
||||
);
|
||||
$copiedImages[$key] = $desired_gdim;
|
||||
}
|
||||
return $copiedImages;
|
||||
}
|
||||
|
||||
public function saveOriginal($folder, $image, $name, $type)
|
||||
{
|
||||
if(!file_exists($folder))
|
||||
{
|
||||
mkdir($folder, 0774, true);
|
||||
}
|
||||
|
||||
$path = $folder . $name . '.' . $type;
|
||||
|
||||
file_put_contents($path, $image);
|
||||
}
|
||||
|
||||
public function saveImage($folder, $image, $name, $type)
|
||||
{
|
||||
if(!file_exists($folder))
|
||||
{
|
||||
mkdir($folder, 0774, true);
|
||||
}
|
||||
|
||||
if($type == "png")
|
||||
{
|
||||
$result = imagepng( $image, $folder . '/' . $name . '.png' );
|
||||
}
|
||||
elseif($type == "gif")
|
||||
{
|
||||
$result = imagegif( $image, $folder . '/' . $name . '.gif' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = imagejpeg( $image, $folder . '/' . $name . '.jpeg' );
|
||||
$type = 'jpeg';
|
||||
}
|
||||
|
||||
imagedestroy($image);
|
||||
|
||||
if($result)
|
||||
{
|
||||
return $name . '.' . $type;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function clearTempFolder()
|
||||
{
|
||||
$folder = getcwd() . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
|
||||
$files = scandir($folder);
|
||||
$result = true;
|
||||
|
||||
foreach($files as $file)
|
||||
{
|
||||
if (!in_array($file, array(".","..")))
|
||||
{
|
||||
$filelink = $folder . $file;
|
||||
if(!unlink($filelink))
|
||||
{
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function deleteImage($name)
|
||||
{
|
||||
$baseFolder = getcwd() . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR;
|
||||
$original = $baseFolder . 'original' . DIRECTORY_SEPARATOR . $name . '*';
|
||||
$live = $baseFolder . 'live' . DIRECTORY_SEPARATOR . $name . '*';
|
||||
$success = true;
|
||||
|
||||
foreach(glob($original) as $image)
|
||||
{
|
||||
if(!unlink($image))
|
||||
{
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(glob($live) as $image)
|
||||
{
|
||||
if(!unlink($image))
|
||||
{
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@@ -18,4 +18,7 @@ $app->post('/api/v1/basefolder', ContentApiController::class . ':createBaseFolde
|
||||
|
||||
$app->put('/api/v1/block', ContentApiController::class . ':updateBlock')->setName('api.block.update')->add(new RestrictApiAccess($container['router']));
|
||||
$app->delete('/api/v1/block', ContentApiController::class . ':deleteBlock')->setName('api.block.delete')->add(new RestrictApiAccess($container['router']));
|
||||
$app->put('/api/v1/moveblock', ContentApiController::class . ':moveBlock')->setName('api.block.move')->add(new RestrictApiAccess($container['router']));
|
||||
$app->put('/api/v1/moveblock', ContentApiController::class . ':moveBlock')->setName('api.block.move')->add(new RestrictApiAccess($container['router']));
|
||||
|
||||
$app->post('/api/v1/image', ContentApiController::class . ':createImage')->setName('api.image.create')->add(new RestrictApiAccess($container['router']));
|
||||
$app->put('/api/v1/image', ContentApiController::class . ':publishImage')->setName('api.image.publish')->add(new RestrictApiAccess($container['router']));
|
@@ -11,12 +11,13 @@ class Settings
|
||||
|
||||
if($userSettings)
|
||||
{
|
||||
$settings = array_merge($settings, $userSettings);
|
||||
$settings['setup'] = false;
|
||||
$imgSettings = $settings['images'];
|
||||
$settings = array_merge($settings, $userSettings);
|
||||
$settings['setup'] = false;
|
||||
}
|
||||
|
||||
$settings['themePath'] = $settings['rootPath'] . $settings['themeFolder'] . DIRECTORY_SEPARATOR . $settings['theme'];
|
||||
|
||||
$settings['images'] = isset($userSettings['images']) ? array_merge($imgSettings, $userSettings['images']) : $imgSettings;
|
||||
$settings['themePath'] = $settings['rootPath'] . $settings['themeFolder'] . DIRECTORY_SEPARATOR . $settings['theme'];
|
||||
|
||||
return array('settings' => $settings);
|
||||
}
|
||||
|
||||
@@ -44,9 +45,10 @@ class Settings
|
||||
'contentFolder' => 'content',
|
||||
'cache' => true,
|
||||
'cachePath' => $rootPath . 'cache',
|
||||
'version' => '1.2.7',
|
||||
'version' => '1.2.8',
|
||||
'setup' => true,
|
||||
'welcome' => true
|
||||
'welcome' => true,
|
||||
'images' => ['live' => ['width' => 720], 'mlibrary' => ['width' => 50, 'height' => 50]],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -87,7 +89,7 @@ class Settings
|
||||
|
||||
$yaml = new Models\WriteYaml();
|
||||
$settings = array_merge($userSettings, $settings);
|
||||
|
||||
|
||||
/* write settings to yaml */
|
||||
$yaml->updateYaml('settings', 'settings.yaml', $settings);
|
||||
}
|
||||
|
@@ -33,9 +33,10 @@
|
||||
<div class="forgotpw"><a href="https://typemill.net/writers/forgot-password" target="_blank">Forgot password?</a></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<a href="{{ base_url() }}">back to startpage</a>
|
||||
</footer>
|
||||
{% endblock %}
|
@@ -1,6 +1,15 @@
|
||||
Font license info
|
||||
|
||||
|
||||
## Entypo
|
||||
|
||||
Copyright (C) 2012 by Daniel Bruce
|
||||
|
||||
Author: Daniel Bruce
|
||||
License: SIL (http://scripts.sil.org/OFL)
|
||||
Homepage: http://www.entypo.com
|
||||
|
||||
|
||||
## Font Awesome
|
||||
|
||||
Copyright (C) 2016 by Dave Gandy
|
||||
|
@@ -6,46 +6,46 @@
|
||||
"units_per_em": 1000,
|
||||
"ascent": 850,
|
||||
"glyphs": [
|
||||
{
|
||||
"uid": "c709da589c923ba3c2ad48d9fc563e93",
|
||||
"css": "cancel",
|
||||
"code": 59392,
|
||||
"src": "entypo"
|
||||
},
|
||||
{
|
||||
"uid": "381da2c2f7fd51f8de877c044d7f439d",
|
||||
"css": "picture",
|
||||
"code": 59393,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "f9cbf7508cd04145ade2800169959eef",
|
||||
"css": "font",
|
||||
"code": 59392,
|
||||
"code": 59394,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "e99461abfef3923546da8d745372c995",
|
||||
"css": "cog",
|
||||
"code": 59393,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "381da2c2f7fd51f8de877c044d7f439d",
|
||||
"css": "picture",
|
||||
"code": 59394,
|
||||
"code": 59395,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "8b9e6a8dd8f67f7c003ed8e7e5ee0857",
|
||||
"css": "off",
|
||||
"code": 59395,
|
||||
"code": 59396,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "d7271d490b71df4311e32cdacae8b331",
|
||||
"css": "home",
|
||||
"code": 59396,
|
||||
"code": 59397,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "44e04715aecbca7f266a17d5a7863c68",
|
||||
"css": "plus",
|
||||
"code": 59397,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "e15f0d620a7897e2035c18c80142f6d9",
|
||||
"css": "link-ext",
|
||||
"code": 61582,
|
||||
"code": 59398,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
@@ -54,6 +54,12 @@
|
||||
"code": 61618,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "e15f0d620a7897e2035c18c80142f6d9",
|
||||
"css": "link-ext",
|
||||
"code": 61582,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "5408be43f7c42bccee419c6be53fdef5",
|
||||
"css": "doc-text",
|
||||
@@ -65,24 +71,6 @@
|
||||
"css": "folder-empty",
|
||||
"code": 61716,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "d3b3f17bc3eb7cd809a07bbd4d178bee",
|
||||
"css": "resize-vertical",
|
||||
"code": 59398,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "6605ee6441bf499ffa3c63d3c7409471",
|
||||
"css": "move",
|
||||
"code": 61511,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "5211af474d3a9848f67f945e2ccaf143",
|
||||
"css": "cancel",
|
||||
"code": 59399,
|
||||
"src": "fontawesome"
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,13 +1,11 @@
|
||||
|
||||
.icon-font:before { content: '\e800'; } /* '' */
|
||||
.icon-cog:before { content: '\e801'; } /* '' */
|
||||
.icon-picture:before { content: '\e802'; } /* '' */
|
||||
.icon-off:before { content: '\e803'; } /* '' */
|
||||
.icon-home:before { content: '\e804'; } /* '' */
|
||||
.icon-plus:before { content: '\e805'; } /* '' */
|
||||
.icon-resize-vertical:before { content: '\e806'; } /* '' */
|
||||
.icon-cancel:before { content: '\e807'; } /* '' */
|
||||
.icon-move:before { content: '\f047'; } /* '' */
|
||||
.icon-cancel:before { content: '\e800'; } /* '' */
|
||||
.icon-picture:before { content: '\e801'; } /* '' */
|
||||
.icon-font:before { content: '\e802'; } /* '' */
|
||||
.icon-cog:before { content: '\e803'; } /* '' */
|
||||
.icon-off:before { content: '\e804'; } /* '' */
|
||||
.icon-home:before { content: '\e805'; } /* '' */
|
||||
.icon-plus:before { content: '\e806'; } /* '' */
|
||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||
.icon-resize-full-alt:before { content: '\f0b2'; } /* '' */
|
||||
.icon-doc-text:before { content: '\f0f6'; } /* '' */
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,13 +1,11 @@
|
||||
|
||||
.icon-font { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-vertical { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-move { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-font { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-full-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-doc-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
16
system/author/css/fontello/css/fontello-ie7.css
vendored
16
system/author/css/fontello/css/fontello-ie7.css
vendored
@@ -10,15 +10,13 @@
|
||||
/* font-size: 120%; */
|
||||
}
|
||||
|
||||
.icon-font { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-vertical { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-move { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-font { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-resize-full-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-doc-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
30
system/author/css/fontello/css/fontello.css
vendored
30
system/author/css/fontello/css/fontello.css
vendored
@@ -1,11 +1,11 @@
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.eot?89525311');
|
||||
src: url('../font/fontello.eot?89525311#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?89525311') format('woff2'),
|
||||
url('../font/fontello.woff?89525311') format('woff'),
|
||||
url('../font/fontello.ttf?89525311') format('truetype'),
|
||||
url('../font/fontello.svg?89525311#fontello') format('svg');
|
||||
src: url('../font/fontello.eot?52515879');
|
||||
src: url('../font/fontello.eot?52515879#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?52515879') format('woff2'),
|
||||
url('../font/fontello.woff?52515879') format('woff'),
|
||||
url('../font/fontello.ttf?52515879') format('truetype'),
|
||||
url('../font/fontello.svg?52515879#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.svg?89525311#fontello') format('svg');
|
||||
src: url('../font/fontello.svg?52515879#fontello') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -55,15 +55,13 @@
|
||||
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
||||
}
|
||||
|
||||
.icon-font:before { content: '\e800'; } /* '' */
|
||||
.icon-cog:before { content: '\e801'; } /* '' */
|
||||
.icon-picture:before { content: '\e802'; } /* '' */
|
||||
.icon-off:before { content: '\e803'; } /* '' */
|
||||
.icon-home:before { content: '\e804'; } /* '' */
|
||||
.icon-plus:before { content: '\e805'; } /* '' */
|
||||
.icon-resize-vertical:before { content: '\e806'; } /* '' */
|
||||
.icon-cancel:before { content: '\e807'; } /* '' */
|
||||
.icon-move:before { content: '\f047'; } /* '' */
|
||||
.icon-cancel:before { content: '\e800'; } /* '' */
|
||||
.icon-picture:before { content: '\e801'; } /* '' */
|
||||
.icon-font:before { content: '\e802'; } /* '' */
|
||||
.icon-cog:before { content: '\e803'; } /* '' */
|
||||
.icon-off:before { content: '\e804'; } /* '' */
|
||||
.icon-home:before { content: '\e805'; } /* '' */
|
||||
.icon-plus:before { content: '\e806'; } /* '' */
|
||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||
.icon-resize-full-alt:before { content: '\f0b2'; } /* '' */
|
||||
.icon-doc-text:before { content: '\f0f6'; } /* '' */
|
||||
|
@@ -229,11 +229,11 @@ body {
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('./font/fontello.eot?63828600');
|
||||
src: url('./font/fontello.eot?63828600#iefix') format('embedded-opentype'),
|
||||
url('./font/fontello.woff?63828600') format('woff'),
|
||||
url('./font/fontello.ttf?63828600') format('truetype'),
|
||||
url('./font/fontello.svg?63828600#fontello') format('svg');
|
||||
src: url('./font/fontello.eot?74591350');
|
||||
src: url('./font/fontello.eot?74591350#iefix') format('embedded-opentype'),
|
||||
url('./font/fontello.woff?74591350') format('woff'),
|
||||
url('./font/fontello.ttf?74591350') format('truetype'),
|
||||
url('./font/fontello.svg?74591350#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -298,24 +298,20 @@ body {
|
||||
</div>
|
||||
<div class="container" id="icons">
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xe800"><i class="demo-icon icon-font"></i> <span class="i-name">icon-font</span><span class="i-code">0xe800</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe801"><i class="demo-icon icon-cog"></i> <span class="i-name">icon-cog</span><span class="i-code">0xe801</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe802"><i class="demo-icon icon-picture"></i> <span class="i-name">icon-picture</span><span class="i-code">0xe802</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe803"><i class="demo-icon icon-off"></i> <span class="i-name">icon-off</span><span class="i-code">0xe803</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe800"><i class="demo-icon icon-cancel"></i> <span class="i-name">icon-cancel</span><span class="i-code">0xe800</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe801"><i class="demo-icon icon-picture"></i> <span class="i-name">icon-picture</span><span class="i-code">0xe801</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe802"><i class="demo-icon icon-font"></i> <span class="i-name">icon-font</span><span class="i-code">0xe802</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe803"><i class="demo-icon icon-cog"></i> <span class="i-name">icon-cog</span><span class="i-code">0xe803</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xe804"><i class="demo-icon icon-home"></i> <span class="i-name">icon-home</span><span class="i-code">0xe804</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe805"><i class="demo-icon icon-plus"></i> <span class="i-name">icon-plus</span><span class="i-code">0xe805</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe806"><i class="demo-icon icon-resize-vertical"></i> <span class="i-name">icon-resize-vertical</span><span class="i-code">0xe806</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe807"><i class="demo-icon icon-cancel"></i> <span class="i-name">icon-cancel</span><span class="i-code">0xe807</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf047"><i class="demo-icon icon-move"></i> <span class="i-name">icon-move</span><span class="i-code">0xf047</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe804"><i class="demo-icon icon-off"></i> <span class="i-name">icon-off</span><span class="i-code">0xe804</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe805"><i class="demo-icon icon-home"></i> <span class="i-name">icon-home</span><span class="i-code">0xe805</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe806"><i class="demo-icon icon-plus"></i> <span class="i-name">icon-plus</span><span class="i-code">0xe806</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf0b2"><i class="demo-icon icon-resize-full-alt"></i> <span class="i-name">icon-resize-full-alt</span><span class="i-code">0xf0b2</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0f6"><i class="demo-icon icon-doc-text"></i> <span class="i-name">icon-doc-text</span><span class="i-code">0xf0f6</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf114"><i class="demo-icon icon-folder-empty"></i> <span class="i-name">icon-folder-empty</span><span class="i-code">0xf114</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
Binary file not shown.
@@ -6,23 +6,19 @@
|
||||
<font id="fontello" horiz-adv-x="1000" >
|
||||
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
|
||||
<missing-glyph horiz-adv-x="1000" />
|
||||
<glyph glyph-name="font" unicode="" d="M405 538l-95-251q18 0 76-1t89-1q11 0 32 1-48 141-102 252z m-405-617l1 44q13 4 31 7t32 6 28 8 25 17 17 28l132 344 156 404h72q4-8 6-12l114-268q19-43 60-144t63-153q9-19 33-80t40-94q11-26 19-32 11-9 49-17t47-11q4-22 4-32 0-3-1-8t0-7q-35 0-106 5t-107 4q-42 0-120-4t-99-4q0 24 2 43l73 16q1 0 7 1t9 2 8 3 9 4 6 4 5 6 1 8q0 9-17 54t-40 99-24 56l-251 1q-14-32-43-109t-28-91q0-12 8-21t24-14 27-7 32-5 23-2q1-11 1-32 0-5-1-16-33 0-98 6t-97 6q-5 0-15-3t-12-2q-45-8-105-8z" horiz-adv-x="928.6" />
|
||||
<glyph glyph-name="cancel" unicode="" d="M452 194q18-18 18-43t-18-43q-18-16-43-16t-43 16l-132 152-132-152q-18-16-43-16t-43 16q-16 18-16 43t16 43l138 156-138 158q-16 18-16 43t16 43q18 16 43 16t43-16l132-152 132 152q18 16 43 16t43-16q18-18 18-43t-18-43l-138-158z" horiz-adv-x="470" />
|
||||
|
||||
<glyph glyph-name="cog" unicode="" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 16 20 16h124q7 0 13-5t7-12l15-103q28-9 51-20l79 59q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-12 0-7-4-13-9-12-29-37t-30-40q15-28 23-54l102-16q7-1 12-7t4-13z" horiz-adv-x="857.1" />
|
||||
<glyph glyph-name="picture" unicode="" d="M357 529q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
|
||||
|
||||
<glyph glyph-name="picture" unicode="" d="M357 529q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
|
||||
<glyph glyph-name="font" unicode="" d="M405 538l-95-251q18 0 76-1t89-1q11 0 32 1-48 141-102 252z m-405-617l1 44q13 4 31 7t32 6 28 8 25 17 17 28l132 344 156 404h72q4-8 6-12l114-268q19-43 60-144t63-153q9-19 33-80t40-94q11-26 19-32 11-9 49-17t47-11q4-22 4-32 0-3-1-8t0-7q-35 0-106 5t-107 4q-42 0-120-4t-99-4q0 24 2 43l73 16q1 0 7 1t9 2 8 3 9 4 6 4 5 6 1 8q0 9-17 54t-40 99-24 56l-251 1q-14-32-43-109t-28-91q0-12 8-21t24-14 27-7 32-5 23-2q1-11 1-32 0-5-1-16-33 0-98 6t-97 6q-5 0-15-3t-12-2q-45-8-105-8z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="off" unicode="" d="M857 350q0-87-34-166t-91-137-137-92-166-34-167 34-136 92-92 137-34 166q0 102 45 191t126 151q24 18 54 14t46-28q18-23 14-53t-28-47q-54-41-84-101t-30-127q0-58 23-111t61-91 91-61 111-23 110 23 92 61 61 91 22 111q0 68-30 127t-84 101q-23 18-28 47t14 53q17 24 47 28t53-14q81-61 126-151t45-191z m-357 429v-358q0-29-21-50t-50-21-51 21-21 50v358q0 29 21 50t51 21 50-21 21-50z" horiz-adv-x="857.1" />
|
||||
<glyph glyph-name="cog" unicode="" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 16 20 16h124q7 0 13-5t7-12l15-103q28-9 51-20l79 59q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-12 0-7-4-13-9-12-29-37t-30-40q15-28 23-54l102-16q7-1 12-7t4-13z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="home" unicode="" d="M786 296v-267q0-15-11-25t-25-11h-214v214h-143v-214h-214q-15 0-25 11t-11 25v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-3-7 1-12 6l-35 41q-4 6-3 13t6 12l401 334q18 15 42 15t43-15l136-113v108q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q6-4 6-12t-4-13z" horiz-adv-x="928.6" />
|
||||
<glyph glyph-name="off" unicode="" d="M857 350q0-87-34-166t-91-137-137-92-166-34-167 34-136 92-92 137-34 166q0 102 45 191t126 151q24 18 54 14t46-28q18-23 14-53t-28-47q-54-41-84-101t-30-127q0-58 23-111t61-91 91-61 111-23 110 23 92 61 61 91 22 111q0 68-30 127t-84 101q-23 18-28 47t14 53q17 24 47 28t53-14q81-61 126-151t45-191z m-357 429v-358q0-29-21-50t-50-21-51 21-21 50v358q0 29 21 50t51 21 50-21 21-50z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="plus" unicode="" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
|
||||
<glyph glyph-name="home" unicode="" d="M786 296v-267q0-15-11-25t-25-11h-214v214h-143v-214h-214q-15 0-25 11t-11 25v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-3-7 1-12 6l-35 41q-4 6-3 13t6 12l401 334q18 15 42 15t43-15l136-113v108q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q6-4 6-12t-4-13z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="resize-vertical" unicode="" d="M393 671q0-14-11-25t-25-10h-71v-572h71q15 0 25-10t11-25-11-25l-143-143q-10-11-25-11t-25 11l-143 143q-10 10-10 25t10 25 25 10h72v572h-72q-14 0-25 10t-10 25 10 26l143 142q11 11 25 11t25-11l143-142q11-11 11-26z" horiz-adv-x="428.6" />
|
||||
|
||||
<glyph glyph-name="cancel" unicode="" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
|
||||
|
||||
<glyph glyph-name="move" unicode="" d="M1000 350q0-14-11-25l-142-143q-11-11-26-11t-25 11-10 25v72h-215v-215h72q14 0 25-10t11-25-11-25l-143-143q-10-11-25-11t-25 11l-143 143q-11 10-11 25t11 25 25 10h72v215h-215v-72q0-14-10-25t-25-11-25 11l-143 143q-11 11-11 25t11 25l143 143q10 11 25 11t25-11 10-25v-72h215v215h-72q-14 0-25 10t-11 25 11 26l143 142q11 11 25 11t25-11l143-142q11-11 11-26t-11-25-25-10h-72v-215h215v72q0 14 10 25t25 11 26-11l142-143q11-10 11-25z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="plus" unicode="" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
|
||||
|
||||
<glyph glyph-name="link-ext" unicode="" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
|
||||
|
||||
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -345,6 +345,10 @@ h1 .version-number{
|
||||
font-size: 0.5em;
|
||||
font-weight: 300;
|
||||
}
|
||||
footer{
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
/********************
|
||||
* SETUP FORM *
|
||||
@@ -1250,6 +1254,7 @@ label .help, .label .help{
|
||||
max-width: 900px;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 2px #ddd;
|
||||
z-index: 99;
|
||||
}
|
||||
.buttonset .message.error{
|
||||
position: absolute;
|
||||
@@ -1352,11 +1357,49 @@ label .help, .label .help{
|
||||
.blox-editor{
|
||||
position: relative;
|
||||
}
|
||||
.blox-editor:hover{
|
||||
.blox:hover{
|
||||
background: #f9f8f6;
|
||||
}
|
||||
.blox-buttons{
|
||||
position: absolute;
|
||||
bottom: -15px;
|
||||
left: 15px;
|
||||
z-index: 9;
|
||||
left: 15px;
|
||||
width: 200px;
|
||||
z-index: 99;
|
||||
}
|
||||
.blox-editor button{
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
margin: 1px;
|
||||
padding: 3px 6px;
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.blox-editor button.edit{
|
||||
background: #fff;
|
||||
// background: #f9f8f6;
|
||||
color: #444;
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
.blox-editor button.edit:hover{
|
||||
background: #cc4146;
|
||||
color: #eee;
|
||||
border: 1px solid #cc4146;
|
||||
}
|
||||
.blox-editor button.cancel{
|
||||
// background: #f9f8f6;
|
||||
background: #fff;
|
||||
color: #444;
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
.blox-editor button.cancel:hover{
|
||||
background: #e0474c;
|
||||
border: 1px solid #e0474c;
|
||||
color: #eee;
|
||||
}
|
||||
.blox-editor textarea{
|
||||
font-family: arial;
|
||||
@@ -1365,33 +1408,7 @@ label .help, .label .help{
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
box-sizing: border-blox;
|
||||
}
|
||||
.blox-editor button{
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
margin: 2px 2px 10px 0;
|
||||
padding: 6px 12px;
|
||||
border-radius: 2px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.blox-editor button.edit{
|
||||
background: #e0474c;
|
||||
color: #f9f8f6;
|
||||
border: 1px solid #e0474c;
|
||||
}
|
||||
.blox-editor button.edit:hover{
|
||||
background: #cc4146;
|
||||
border: 1px solid #cc4146;
|
||||
}
|
||||
.blox-editor button.cancel{
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
color: #444;
|
||||
}
|
||||
.blox-editor button.cancel:hover{
|
||||
background: #e0474c;
|
||||
border: 1px solid #e0474c;
|
||||
color: #eee;
|
||||
min-height: 40px;
|
||||
}
|
||||
.blox-editor .sideaction{
|
||||
position: absolute;
|
||||
@@ -1432,6 +1449,14 @@ label .help, .label .help{
|
||||
.hidden{
|
||||
display: none;
|
||||
}
|
||||
.hidden .blox:hover{
|
||||
background: #fff;
|
||||
}
|
||||
.component{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
z-index:9;
|
||||
}
|
||||
.fade-editor-enter-active{
|
||||
transition: opacity .5s;
|
||||
}
|
||||
@@ -1442,6 +1467,11 @@ label .help, .label .help{
|
||||
padding: 20px;
|
||||
width:100%;
|
||||
}
|
||||
.format-bar .editactive{
|
||||
position: relative;
|
||||
margin-left: -20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.format-bar .blox-editor{
|
||||
display: inline;
|
||||
}
|
||||
@@ -1565,8 +1595,47 @@ label .help, .label .help{
|
||||
.blox blockquote p{
|
||||
margin-left: 50px;
|
||||
}
|
||||
.blox img{
|
||||
.dropbox{
|
||||
min-height: 50px;
|
||||
position: relative;
|
||||
background: #f9f8f6;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.dropbox p{
|
||||
cursor: pointer;
|
||||
border: 2px dashed grey;
|
||||
line-height: 50px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-sizing:border-box;
|
||||
padding: 0;
|
||||
}
|
||||
.dropbox input{
|
||||
background: #fff;
|
||||
width: 80%;
|
||||
margin: 2px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
.dropbox label{
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
.dropbox .imgmeta{
|
||||
margin-top: 20px;
|
||||
}
|
||||
.input-file{
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
.blox img, img.uploadPreview{
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
sup{}
|
||||
cite{}
|
||||
@@ -1603,11 +1672,14 @@ hr{
|
||||
font-weight: 400;
|
||||
padding-left: 25px;
|
||||
}
|
||||
.blox a, .blox a:link, .blox a:visited{
|
||||
.blox a, .blox a:link, .blox a:visited,
|
||||
footer a, footer a:link, footer a:visited
|
||||
{
|
||||
text-decoration: none;
|
||||
color: #e0474c;
|
||||
}
|
||||
.blox a:focus, .blox a:hover, .blox a:active{
|
||||
.blox a:focus, .blox a:hover, .blox a:active,
|
||||
footer a:focus, footer a:hover, footer a:active{
|
||||
text-decoration: underline;
|
||||
}
|
||||
.blox .TOC li:before{ color: #bbb; }
|
||||
@@ -1640,8 +1712,16 @@ hr{
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.blox-editor .loadwrapper{
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
/* load design editor button */
|
||||
.editor button.load:after,
|
||||
.editor button.load:after, .blox-editor .load:after,
|
||||
.editor button.success:after,
|
||||
.editor button.fail:after
|
||||
{
|
||||
@@ -1653,7 +1733,7 @@ hr{
|
||||
border-radius: 50%;
|
||||
content: '';
|
||||
}
|
||||
.editor button.load:after{
|
||||
.editor button.load:after, .blox-editor .load:after{
|
||||
border: 8px solid #fff;
|
||||
border-top: 8px solid #ccc;
|
||||
background: #ccc;
|
||||
|
@@ -10,24 +10,25 @@
|
||||
<div class="blox-body">
|
||||
|
||||
<content-block class="title" :body="false">
|
||||
<div class="blox title" @click="setData( $event, 'text-markdown')" data-id="0" id="blox-0">{{ title }}</div>
|
||||
<div class="blox title" @click.prevent="setData( $event )" data-id="0" id="blox-0">{{ title }}</div>
|
||||
</content-block>
|
||||
|
||||
<div id="sortblox">
|
||||
|
||||
{% for id, block in content %}
|
||||
<content-block :body="true">
|
||||
<div class="blox" @click="setData( $event, 'textarea-markdown' )" data-id="{{ id }}" id="blox-{{id}}">{{block}}</div>
|
||||
<div class="blox" @click.prevent="setData( $event )" data-id="{{ id }}" id="blox-{{id}}">{{block}}</div>
|
||||
</content-block>
|
||||
{% endfor %}
|
||||
|
||||
<content-block :body="true" v-for="newBlock in newBlocks"><div class="blox" @click="setData( $event, 'textarea-markdown' )" :data-id="newBlock.id" :id="newBlock.blockId" v-html="newBlock.content"></div></content-block>
|
||||
<content-block :body="true" v-for="newBlock in newBlocks"><div class="blox" @click.prevent="setData( $event )" :data-id="newBlock.id" :id="newBlock.blockId" v-html="newBlock.content"></div></content-block>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="format-bar">
|
||||
<content-block :body="false">
|
||||
<button class="format-item" @click="setData( $event, 'textarea-markdown' )" data-id="99999" id="blox-99999"><i class="icon-font"></i></button>
|
||||
<button class="format-item" @click.prevent="setData( $event, 'markdown-component' )" data-id="99999" id="blox-99999"><i class="icon-font"></i></button>
|
||||
<button class="format-item" @click.prevent="setData( $event, 'image-component' )" data-id="99999" id="blox-99999"><i class="icon-picture"></i></button>
|
||||
</content-block>
|
||||
</div>
|
||||
|
||||
|
@@ -107,6 +107,21 @@
|
||||
toggleElement.classList.toggle(myclass);
|
||||
}
|
||||
|
||||
if (window.Element && !Element.prototype.closest) {
|
||||
Element.prototype.closest =
|
||||
function(s) {
|
||||
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
|
||||
i,
|
||||
el = this;
|
||||
do {
|
||||
i = matches.length;
|
||||
while (--i >= 0 && matches.item(i) !== el) {};
|
||||
} while ((i < 0) && (el = el.parentElement));
|
||||
return el;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
** START VERSION CHECK **
|
||||
**********************************/
|
||||
|
@@ -1,5 +1,8 @@
|
||||
const eventBus = new Vue();
|
||||
|
||||
const contentComponent = Vue.component('content-block', {
|
||||
props: ['body'],
|
||||
template: '<div ref="bloxcomponent" class="blox-editor"><div :class="{ editactive: edit }"><div @keyup.enter="submitBlock" @click="getData"><div class="component"><transition name="fade-editor"><component :disabled="disabled" :compmarkdown="compmarkdown" @updatedMarkdown="compmarkdown = $event" :is="componentType"></component></transition><div class="blox-buttons" v-if="edit"><button class="edit" :disabled="disabled" @click.prevent="saveBlock">save</button><button class="cancel" :disabled="disabled" @click.prevent="switchToPreviewMode">cancel</button></div></div><div :class="preview"><slot></slot></div></div><div class="sideaction" v-if="body"><button class="delete" :disabled="disabled" title="delete content-block" @click.prevent="deleteBlock($event)"><i class="icon-cancel"></i></button></div></div></div>',
|
||||
data: function () {
|
||||
return {
|
||||
preview: 'visible',
|
||||
@@ -9,156 +12,168 @@ const contentComponent = Vue.component('content-block', {
|
||||
disabled: false,
|
||||
}
|
||||
},
|
||||
mounted: function()
|
||||
{
|
||||
eventBus.$on('closeComponents', this.closeComponents);
|
||||
},
|
||||
methods: {
|
||||
getData: function()
|
||||
switchToEditMode: function()
|
||||
{
|
||||
eventBus.$emit('closeComponents');
|
||||
self = this;
|
||||
|
||||
if(self.$root.$data.freeze == false && self.$root.$data.blockType != '')
|
||||
{
|
||||
self.$root.$data.freeze = true;
|
||||
this.preview = 'hidden';
|
||||
this.edit = true;
|
||||
this.compmarkdown = self.$root.$data.blockMarkdown;
|
||||
this.componentType = self.$root.$data.blockType;
|
||||
self.$root.sortable.option("disabled",true);
|
||||
}
|
||||
/*
|
||||
window.addEventListener('click', function(e)
|
||||
{
|
||||
if (!e.target.closest('.editactive'))
|
||||
{
|
||||
console.info('not found');
|
||||
publishController.errors.message = false;
|
||||
|
||||
this.preview = 'visible';
|
||||
this.edit = false;
|
||||
this.compmarkdown = '';
|
||||
self.componentType = false;
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.sortable.option("disabled",false);
|
||||
}
|
||||
});
|
||||
*/
|
||||
self.$root.$data.freeze = true; /* freeze the data */
|
||||
self.$root.sortable.option("disabled",true); /* disable sorting */
|
||||
this.preview = 'hidden'; /* hide the html-preview */
|
||||
this.edit = true; /* show the edit-mode */
|
||||
this.compmarkdown = self.$root.$data.blockMarkdown; /* get markdown data */
|
||||
this.componentType = self.$root.$data.blockType; /* get block-type of element */
|
||||
},
|
||||
cancelBlock: function()
|
||||
closeComponents: function()
|
||||
{
|
||||
publishController.errors.message = false;
|
||||
|
||||
this.preview = 'visible';
|
||||
this.edit = false;
|
||||
this.componentType = false;
|
||||
self = this;
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.sortable.option("disabled",false);
|
||||
},
|
||||
submitBlock: function(e){
|
||||
switchToPreviewMode: function()
|
||||
{
|
||||
self = this;
|
||||
self.$root.$data.freeze = false; /* activate the data again */
|
||||
self.$root.sortable.option("disabled",false); /* activate sorting again */
|
||||
this.preview = 'visible'; /* show the html-preview */
|
||||
this.edit = false; /* hide the edit mode */
|
||||
this.compmarkdown = ''; /* clear markdown content */
|
||||
this.componentType = false; /* delete the component type */
|
||||
self.$root.$data.blockType = false;
|
||||
self.$root.$data.blockMarkdown = false;
|
||||
self.$root.$data.file = false;
|
||||
publishController.errors.message = false; /* delete all error messages */
|
||||
},
|
||||
freezePage: function()
|
||||
{
|
||||
this.disabled = 'disabled';
|
||||
publishController.errors.message = false;
|
||||
publishController.publishDisabled = true;
|
||||
var self = this;
|
||||
self.$root.$data.freeze = true;
|
||||
},
|
||||
activatePage: function()
|
||||
{
|
||||
this.disabled = false;
|
||||
publishController.publishDisabled = false;
|
||||
},
|
||||
getData: function()
|
||||
{
|
||||
self = this;
|
||||
if(self.$root.$data.blockType != '')
|
||||
{
|
||||
this.switchToEditMode();
|
||||
}
|
||||
|
||||
/*
|
||||
if(self.$root.$data.freeze == false && self.$root.$data.blockType != '')
|
||||
{
|
||||
this.switchToEditMode();
|
||||
}
|
||||
*/
|
||||
},
|
||||
submitBlock: function(){
|
||||
var emptyline = /^\s*$(?:\r\n?|\n)/gm;
|
||||
if(this.compmarkdown.search(emptyline) > -1)
|
||||
{
|
||||
var checkempty = this.compmarkdown.replace(/(\r\n|\n|\r|\s)/gm,"");
|
||||
if(checkempty == '')
|
||||
{
|
||||
publishController.errors.message = false;
|
||||
|
||||
this.preview = 'visible';
|
||||
this.edit = false;
|
||||
this.componentType = false;
|
||||
self = this;
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.sortable.option("disabled",false);
|
||||
this.switchToPreviewMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.$root.sortable.option("disabled",false);
|
||||
this.saveBlock();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
saveBlock: function()
|
||||
{
|
||||
publishController.errors.message = false;
|
||||
this.disabled = 'disabled';
|
||||
|
||||
var self = this;
|
||||
|
||||
self.$root.$data.freeze = true;
|
||||
|
||||
var url = self.$root.$data.root + '/api/v1/block';
|
||||
|
||||
var params = {
|
||||
'url': document.getElementById("path").value,
|
||||
'markdown': this.compmarkdown,
|
||||
'block_id': self.$root.$data.blockId,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
};
|
||||
|
||||
var method = 'PUT';
|
||||
|
||||
sendJson(function(response, httpStatus)
|
||||
{
|
||||
if(this.compmarkdown == undefined || this.compmarkdown.replace(/(\r\n|\n|\r|\s)/gm,"") == '')
|
||||
{
|
||||
if(httpStatus == 400)
|
||||
this.switchToPreviewMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.freezePage();
|
||||
|
||||
var self = this;
|
||||
|
||||
if(this.componentType == 'image-component' && self.$root.$data.file)
|
||||
{
|
||||
self.disabled = false;
|
||||
publishController.publishDisabled = false;
|
||||
var url = self.$root.$data.root + '/api/v1/image';
|
||||
var method = 'PUT';
|
||||
}
|
||||
if(response)
|
||||
else
|
||||
{
|
||||
self.disabled = false;
|
||||
publishController.publishDisabled = false;
|
||||
|
||||
var result = JSON.parse(response);
|
||||
|
||||
if(result.errors)
|
||||
var url = self.$root.$data.root + '/api/v1/block';
|
||||
var method = 'PUT';
|
||||
}
|
||||
|
||||
var params = {
|
||||
'url': document.getElementById("path").value,
|
||||
'markdown': this.compmarkdown,
|
||||
'block_id': self.$root.$data.blockId,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
};
|
||||
|
||||
sendJson(function(response, httpStatus)
|
||||
{
|
||||
if(httpStatus == 400)
|
||||
{
|
||||
console.info(result.errors);
|
||||
publishController.errors.message = result.errors.markdown[0];
|
||||
return false;
|
||||
self.activatePage();
|
||||
}
|
||||
else
|
||||
if(response)
|
||||
{
|
||||
self.preview = 'visible';
|
||||
self.edit = false;
|
||||
self.componentType = false;
|
||||
self.$root.$data.freeze = false;
|
||||
self.activatePage();
|
||||
|
||||
if(self.$root.$data.blockId == 99999)
|
||||
var result = JSON.parse(response);
|
||||
|
||||
if(result.errors)
|
||||
{
|
||||
self.$root.$data.markdown.push(result.markdown);
|
||||
self.$root.$data.newBlocks.push(result);
|
||||
|
||||
self.$root.$data.blockMarkdown = '';
|
||||
self.$root.$data.blockType = 'textarea-markdown';
|
||||
self.getData();
|
||||
publishController.errors.message = result.errors.markdown[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
var htmlid = "blox-" + self.$root.$data.blockId;
|
||||
var html = document.getElementById(htmlid);
|
||||
html.innerHTML = result.content;
|
||||
self.switchToPreviewMode();
|
||||
|
||||
self.$root.$data.markdown[self.$root.$data.blockId] = result.markdown;
|
||||
|
||||
self.$root.$data.blockMarkdown = '';
|
||||
self.$root.$data.blockType = '';
|
||||
if(self.$root.$data.blockId == 99999)
|
||||
{
|
||||
self.$root.$data.markdown.push(result.markdown);
|
||||
self.$root.$data.newBlocks.push(result);
|
||||
|
||||
self.$root.$data.blockMarkdown = '';
|
||||
self.$root.$data.blockType = 'markdown-component';
|
||||
self.getData();
|
||||
}
|
||||
else
|
||||
{
|
||||
var htmlid = "blox-" + self.$root.$data.blockId;
|
||||
var html = document.getElementById(htmlid);
|
||||
html.innerHTML = result.content;
|
||||
|
||||
self.$root.$data.markdown[self.$root.$data.blockId] = result.markdown;
|
||||
self.$root.$data.blockMarkdown = '';
|
||||
self.$root.$data.blockType = '';
|
||||
}
|
||||
}
|
||||
|
||||
publishController.publishResult = "";
|
||||
}
|
||||
}
|
||||
}, method, url, params);
|
||||
}, method, url, params);
|
||||
}
|
||||
},
|
||||
deleteBlock: function(event)
|
||||
{
|
||||
var bloxeditor = event.target.parentElement.parentElement;
|
||||
console.info(bloxeditor);
|
||||
this.freezePage();
|
||||
|
||||
var bloxeditor = event.target.closest('.blox-editor');
|
||||
|
||||
var bloxid = bloxeditor.getElementsByClassName('blox')[0].dataset.id;
|
||||
bloxeditor.id = "delete-"+bloxid;
|
||||
|
||||
this.disabled = 'disabled';
|
||||
|
||||
publishController.errors.message = false;
|
||||
bloxeditor.firstChild.id = "delete-"+bloxid;
|
||||
|
||||
var self = this;
|
||||
|
||||
@@ -177,24 +192,21 @@ const contentComponent = Vue.component('content-block', {
|
||||
{
|
||||
if(httpStatus == 400)
|
||||
{
|
||||
self.disabled = false;
|
||||
self.activatePage();
|
||||
}
|
||||
if(response)
|
||||
{
|
||||
self.disabled = false;
|
||||
self.activatePage();
|
||||
|
||||
var result = JSON.parse(response);
|
||||
|
||||
if(result.errors)
|
||||
{
|
||||
publishController.errors.message = result.errors;
|
||||
publishController.publishDisabled = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.edit = false;
|
||||
self.componentType = false;
|
||||
{
|
||||
self.switchToPreviewMode();
|
||||
|
||||
var deleteblock = document.getElementById("delete-"+bloxid);
|
||||
deleteblock.parentElement.remove(deleteblock);
|
||||
@@ -206,46 +218,22 @@ const contentComponent = Vue.component('content-block', {
|
||||
blox[i].dataset.id = i;
|
||||
}
|
||||
|
||||
self.$root.$data.freeze = false;
|
||||
self.$root.$data.markdown = result.markdown;
|
||||
self.$root.$data.markdown = result.markdown;
|
||||
self.$root.$data.blockMarkdown = '';
|
||||
self.$root.$data.blockType = '';
|
||||
|
||||
publishController.publishDisabled = false;
|
||||
publishController.publishResult = "";
|
||||
}
|
||||
}
|
||||
}, method, url, params);
|
||||
},
|
||||
},
|
||||
/*
|
||||
mounted: function() {
|
||||
var self = this;
|
||||
|
||||
self.sortable = new Sortable(sortblox, {
|
||||
animation: 150,
|
||||
onEnd: function (evt) {
|
||||
var params = {
|
||||
'url': document.getElementById("path").value,
|
||||
'old_index': evt.oldIndex,
|
||||
'new_index': evt.newIndex,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
};
|
||||
self.moveBlock(params);
|
||||
},
|
||||
});
|
||||
},
|
||||
*/
|
||||
template: '<div class="blox-editor"><div :class="{ editactive: edit }"><div @keyup.enter="submitBlock" @click="getData"><transition name="fade-editor"><component :disabled="disabled" :compmarkdown="compmarkdown" @updatedMarkdown="compmarkdown = $event" :is="componentType"></component></transition><div :class="preview"><slot></slot></div></div><div class="blox-buttons" v-if="edit"><button class="edit" :disabled="disabled" @click.prevent="saveBlock">save</button><button class="cancel" :disabled="disabled" @click.prevent="cancelBlock">cancel</button></div><div class="sideaction" v-if="body"><button class="delete" :disabled="disabled" title="delete content-block" @click.prevent="deleteBlock($event)"><i class="icon-cancel"></i></button></div></div></div>',
|
||||
})
|
||||
|
||||
const textareaComponent = Vue.component('textarea-markdown', {
|
||||
const markdownComponent = Vue.component('markdown-component', {
|
||||
props: ['compmarkdown', 'disabled'],
|
||||
template: '<div><textarea ref="markdown" :value="compmarkdown" :disabled="disabled" @input="updatemarkdown"></textarea></div>',
|
||||
mounted: function(){
|
||||
autosize(document.querySelector('textarea'));
|
||||
this.$refs.markdown.focus();
|
||||
autosize(document.querySelectorAll('textarea'));
|
||||
},
|
||||
methods: {
|
||||
updatemarkdown: function(event)
|
||||
@@ -255,12 +243,12 @@ const textareaComponent = Vue.component('textarea-markdown', {
|
||||
},
|
||||
})
|
||||
|
||||
const textComponent = Vue.component('text-markdown', {
|
||||
const titleComponent = Vue.component('title-component', {
|
||||
props: ['compmarkdown', 'disabled'],
|
||||
template: '<div><input type="text" ref="markdown" :value="compmarkdown" :disabled="disabled" @input="updatemarkdown"></div>',
|
||||
mounted: function(){
|
||||
autosize(document.querySelector('textarea'));
|
||||
this.$refs.markdown.focus();
|
||||
autosize(document.querySelectorAll('textarea'));
|
||||
},
|
||||
methods: {
|
||||
updatemarkdown: function(event)
|
||||
@@ -270,11 +258,212 @@ const textComponent = Vue.component('text-markdown', {
|
||||
},
|
||||
})
|
||||
|
||||
const imageComponent = Vue.component('input-image', {
|
||||
template: '<div>Image component</div>',
|
||||
const imageComponent = Vue.component('image-component', {
|
||||
props: ['compmarkdown', 'disabled'],
|
||||
template: '<div class="dropbox"><input type="hidden" ref="markdown" :value="compmarkdown" :disabled="disabled" @input="updatemarkdown"><input type="file" name="image" accept="image/*" class="input-file" @change="onFileChange( $event )"><p>drag a picture or click to select</p><img class="uploadPreview" :src="imgpreview" /><div v-if="load" class="loadwrapper"><span class="load"></span></div><div class="imgmeta" v-if="imgmeta"><label for="imgalt">Alt-Text: </label><input name="imgalt" type="text" placeholder="alt" @input="createmarkdown" v-model="imgalt" max="100"/><label for="imgtitle">Title: </label><input name="imgtitle" type="text" placeholder="title" v-model="imgtitle" @input="createmarkdown" max="64" /><label for="imgcaption">Caption: </label><input title="imgcaption" type="text" placeholder="caption" v-model="imgcaption" @input="createmarkdown" max="140" /><label for="imgurl">Link: </label><input title="imgurl" type="url" placeholder="url" v-model="imglink" @input="createmarkdown" /></div></div>',
|
||||
data: function(){
|
||||
return {
|
||||
maxsize: 5, // megabyte
|
||||
imgpreview: false,
|
||||
load: false,
|
||||
imgmeta: false,
|
||||
imgalt: '',
|
||||
imgtitle: '',
|
||||
imgcaption: '',
|
||||
imglink: '',
|
||||
imgfile: 'imgplchldr',
|
||||
}
|
||||
},
|
||||
mounted: function(){
|
||||
// autosize(document.querySelector('textarea'));
|
||||
this.$refs.markdown.focus();
|
||||
|
||||
if(this.compmarkdown)
|
||||
{
|
||||
this.imgmeta = true;
|
||||
|
||||
var imgmarkdown = this.compmarkdown;
|
||||
|
||||
var imgcaption = imgmarkdown.match(/\*.*?\*/);
|
||||
if(imgcaption){
|
||||
this.imgcaption = imgcaption[0].slice(1,-1);
|
||||
imgmarkdown = imgmarkdown.replace(this.imgcaption,'');
|
||||
imgmarkdown = imgmarkdown.replace(/\r?\n|\r/g,'');
|
||||
}
|
||||
|
||||
if(this.compmarkdown[0] == '[')
|
||||
{
|
||||
var imglink = this.compmarkdown.match(/\(.*?\)/g);
|
||||
if(imglink[1])
|
||||
{
|
||||
this.imglink = imglink[1].slice(1,-1);
|
||||
imgmarkdown = imgmarkdown.replace(imglink[1],'');
|
||||
imgmarkdown = imgmarkdown.slice(1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
var imgtitle = imgmarkdown.match(/\".*?\"/);
|
||||
if(imgtitle)
|
||||
{
|
||||
this.imgtitle = imgtitle[0].slice(1,-1);
|
||||
imgmarkdown = imgmarkdown.replace(imgtitle[0], '');
|
||||
}
|
||||
|
||||
var imgalt = imgmarkdown.match(/\[.*?\]/);
|
||||
if(imgalt)
|
||||
{
|
||||
this.imgalt = imgalt[0].slice(1,-1);
|
||||
}
|
||||
var imgpreview = imgmarkdown.match(/\(.*?\)/);
|
||||
if(imgpreview)
|
||||
{
|
||||
this.imgpreview = imgpreview[0].slice(1,-1);
|
||||
this.imgfile = this.imgpreview;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updatemarkdown: function(event)
|
||||
{
|
||||
this.$emit('updatedMarkdown', event.target.value);
|
||||
},
|
||||
createmarkdown: function()
|
||||
{
|
||||
errors = false;
|
||||
|
||||
if(this.imgalt.length < 101)
|
||||
{
|
||||
imgmarkdown = '![' + this.imgalt + ']';
|
||||
}
|
||||
else
|
||||
{
|
||||
errors = 'Maximum size of image alt-text is 100 characters';
|
||||
imgmarkdown = '![]';
|
||||
}
|
||||
|
||||
if(this.imgtitle != '')
|
||||
{
|
||||
if(this.imgtitle.length < 101)
|
||||
{
|
||||
imgmarkdown = imgmarkdown + '(' + this.imgfile + ' "' + this.imgtitle + '")';
|
||||
}
|
||||
else
|
||||
{
|
||||
errors = 'Maximum size of image title is 100 characters';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
imgmarkdown = imgmarkdown + '(' + this.imgfile + ')';
|
||||
}
|
||||
|
||||
if(this.imglink != '')
|
||||
{
|
||||
if(this.imglink.length < 101)
|
||||
{
|
||||
imgmarkdown = '[' + imgmarkdown + '](' + this.imglink + ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
errors = 'Maximum size of image link is 100 characters';
|
||||
}
|
||||
}
|
||||
|
||||
if(this.imgcaption != '')
|
||||
{
|
||||
if(this.imgcaption.length < 140)
|
||||
{
|
||||
imgmarkdown = imgmarkdown + '\n*' + this.imgcaption + '*';
|
||||
}
|
||||
else
|
||||
{
|
||||
errors = 'Maximum size of image caption is 140 characters';
|
||||
}
|
||||
}
|
||||
|
||||
if(errors)
|
||||
{
|
||||
this.$parent.freezePage();
|
||||
publishController.errors.message = errors;
|
||||
}
|
||||
else
|
||||
{
|
||||
publishController.errors.message = false;
|
||||
this.$parent.activatePage();
|
||||
this.$emit('updatedMarkdown', imgmarkdown);
|
||||
}
|
||||
},
|
||||
onFileChange: function( e )
|
||||
{
|
||||
if(e.target.files.length > 0)
|
||||
{
|
||||
let imageFile = e.target.files[0];
|
||||
let size = imageFile.size / 1024 / 1024;
|
||||
|
||||
if (!imageFile.type.match('image.*'))
|
||||
{
|
||||
publishController.errors.message = "Only images are allowed.";
|
||||
}
|
||||
else if (size > this.maxsize)
|
||||
{
|
||||
publishController.errors.message = "The maximal size of images is " + this.maxsize + " MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
self = this;
|
||||
this.$parent.freezePage();
|
||||
this.$root.$data.file = true;
|
||||
this.load = true;
|
||||
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(imageFile);
|
||||
reader.onload = function(e) {
|
||||
self.imgpreview = e.target.result;
|
||||
self.$emit('updatedMarkdown', '');
|
||||
|
||||
/* load image to server */
|
||||
var url = self.$root.$data.root + '/api/v1/image';
|
||||
|
||||
var params = {
|
||||
'url': document.getElementById("path").value,
|
||||
'image': e.target.result,
|
||||
'csrf_name': document.getElementById("csrf_name").value,
|
||||
'csrf_value': document.getElementById("csrf_value").value,
|
||||
};
|
||||
|
||||
var method = 'POST';
|
||||
|
||||
sendJson(function(response, httpStatus)
|
||||
{
|
||||
if(httpStatus == 400)
|
||||
{
|
||||
self.$parent.activatePage();
|
||||
}
|
||||
if(response)
|
||||
{
|
||||
self.$parent.activatePage();
|
||||
self.load = false;
|
||||
|
||||
var result = JSON.parse(response);
|
||||
|
||||
if(result.errors)
|
||||
{
|
||||
publishController.errors.message = result.errors;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.imgmeta = true;
|
||||
}
|
||||
}
|
||||
}, method, url, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const tableComponent = Vue.component('input-table', {
|
||||
const tableComponent = Vue.component('table', {
|
||||
template: '<div>table component</div>',
|
||||
})
|
||||
|
||||
@@ -283,10 +472,9 @@ let editor = new Vue({
|
||||
el: '#blox',
|
||||
components: {
|
||||
'content-component': contentComponent,
|
||||
'textarea-component': textareaComponent,
|
||||
'text-component': textComponent,
|
||||
'image-component': imageComponent,
|
||||
'table-component': tableComponent,
|
||||
'markdown-component': markdownComponent,
|
||||
'title-component': titleComponent,
|
||||
'image-component': imageComponent,
|
||||
},
|
||||
data: {
|
||||
root: document.getElementById("main").dataset.url,
|
||||
@@ -294,6 +482,7 @@ let editor = new Vue({
|
||||
blockId: false,
|
||||
blockType: false,
|
||||
blockMarkdown: '',
|
||||
file: false,
|
||||
freeze: false,
|
||||
newBlocks: [],
|
||||
draftDisabled: true,
|
||||
@@ -346,14 +535,43 @@ let editor = new Vue({
|
||||
};
|
||||
self.moveBlock(params);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
setData: function(event, blocktype, body)
|
||||
{
|
||||
this.blockId = event.currentTarget.dataset.id;
|
||||
this.blockType = blocktype;
|
||||
/* this.blockType = blocktype; */
|
||||
this.blockMarkdown = this.markdown[this.blockId];
|
||||
if(blocktype)
|
||||
{
|
||||
this.blockType = blocktype;
|
||||
}
|
||||
else if(this.blockId == 0)
|
||||
{
|
||||
this.blockType = "title-component"
|
||||
}
|
||||
else
|
||||
{
|
||||
this.blockType = this.determineBlockType(this.blockMarkdown);
|
||||
}
|
||||
},
|
||||
determineBlockType: function(block)
|
||||
{
|
||||
var firstChar = block[0];
|
||||
var secondChar = block[1];
|
||||
var thirdChar = block[2];
|
||||
|
||||
switch(firstChar){
|
||||
case "!":
|
||||
if(secondChar == "[") { return "image-component" }
|
||||
break;
|
||||
case "[":
|
||||
if(secondChar == "!" && thirdChar == "[") { return "image-component" } else { return "markdown-component" }
|
||||
break;
|
||||
default:
|
||||
return 'markdown-component';
|
||||
}
|
||||
},
|
||||
moveBlock: function(params)
|
||||
{
|
||||
@@ -362,7 +580,7 @@ let editor = new Vue({
|
||||
var url = this.root + '/api/v1/moveblock';
|
||||
|
||||
var self = this;
|
||||
|
||||
|
||||
var method = 'PUT';
|
||||
|
||||
sendJson(function(response, httpStatus)
|
||||
@@ -379,7 +597,6 @@ let editor = new Vue({
|
||||
{
|
||||
publishController.errors.message = result.errors;
|
||||
publishController.publishDisabled = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -6,6 +6,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<meta name="description" content="Configure your TYPEMILL website"/>
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="msapplication-TileColor" content="#F9F8F6" />
|
||||
<meta name="msapplication-TileImage" content="{{ base_url }}/system/author/img/mstile-144x144.png" />
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
<meta name="description" content="Welcome to your new TYPEMILL website" />
|
||||
<meta name="robots" content="noindex" />
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="msapplication-TileColor" content="#F9F8F6" />
|
||||
<meta name="msapplication-TileImage" content="{{ base_url }}/system/author/img/mstile-144x144.png" />
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
<meta name="description" content="Configure your TYPEMILL website"/>
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="msapplication-TileColor" content="#F9F8F6" />
|
||||
<meta name="msapplication-TileImage" content="{{ base_url }}/system/author/img/mstile-144x144.png" />
|
||||
<link rel="icon" type="image/png" href="{{ base_url }}/system/author/img/favicon-32x32.png" sizes="32x32" />
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
<meta name="description" content="Edit your TYPEMILL website" />
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="msapplication-TileColor" content="#F9F8F6" />
|
||||
<meta name="msapplication-TileImage" content="{{ base_url }}/system/author/img/mstile-144x144.png" />
|
||||
<link rel="icon" type="image/png" href="{{ base_url }}/system/author/img/favicon-32x32.png" sizes="32x32" />
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
<meta name="description" content="Edit your TYPEMILL website" />
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="msapplication-TileColor" content="#F9F8F6" />
|
||||
<meta name="msapplication-TileImage" content="{{ base_url }}/system/author/img/mstile-144x144.png" />
|
||||
<link rel="icon" type="image/png" href="{{ base_url }}/system/author/img/favicon-32x32.png" sizes="32x32" />
|
||||
|
@@ -5,6 +5,8 @@
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="description" content="{{ description }}" />
|
||||
<meta name="author" content="{{ settings.author }}" />
|
||||
<meta name="generator" content="TYPEMILL" />
|
||||
|
@@ -5,6 +5,8 @@
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<base href="{{ base_url }}/">
|
||||
|
||||
<meta name="description" content="{{ description }}" />
|
||||
<meta name="author" content="{{ settings.author }}" />
|
||||
<meta name="generator" content="TYPEMILL" />
|
||||
|
@@ -1,5 +1,5 @@
|
||||
name: Typemill Theme
|
||||
version: 1.1.0
|
||||
version: 1.1.1
|
||||
description: The standard theme for Typemill. Responsive, minimal and without any dependencies. It uses the system fonts Calibri and Helvetica. No JavaScript is used.
|
||||
author: Sebastian Schürmanns
|
||||
homepage: https://typemill.net
|
||||
@@ -12,6 +12,9 @@ settings:
|
||||
modifiedText: 'Last updated'
|
||||
modifiedFormat: 'd.m.Y'
|
||||
authorIntro: 'Author'
|
||||
images:
|
||||
live:
|
||||
width: 820
|
||||
|
||||
forms:
|
||||
fields:
|
||||
|
Reference in New Issue
Block a user