1
0
mirror of https://github.com/typemill/typemill.git synced 2025-08-01 11:50:28 +02:00

Version 1.2.11: Table editor

This commit is contained in:
Sebastian
2019-02-17 11:17:43 +01:00
parent 8060eba08c
commit f40622ed2c
36 changed files with 534 additions and 128 deletions

2
cache/lastCache.txt vendored
View File

@@ -1 +1 @@
1548495240
1550398193

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -92,8 +92,10 @@ abstract class ContentController
$vResult = $validate->editorInput($this->params);
if(is_array($vResult))
{
{
$message = reset($vResult);
$this->errors = ['errors' => $vResult];
if(isset($message[0])){ $this->errors['errors']['message'] = $message[0]; }
return false;
}
return true;
@@ -106,7 +108,9 @@ abstract class ContentController
if(is_array($vResult))
{
$message = reset($vResult);
$this->errors = ['errors' => $vResult];
if(isset($message[0])){ $this->errors['errors']['message'] = $message[0]; }
return false;
}
return true;
@@ -119,7 +123,9 @@ abstract class ContentController
if(is_array($vResult))
{
$message = reset($vResult);
$this->errors = ['errors' => $vResult];
if(isset($message[0])){ $this->errors['errors']['message'] = $message[0]; }
return false;
}
return true;
@@ -132,7 +138,9 @@ abstract class ContentController
if(is_array($vResult))
{
$message = reset($vResult);
$this->errors = ['errors' => $vResult];
if(isset($message[0])){ $this->errors['errors']['message'] = $message[0]; }
return false;
}
return true;

View File

@@ -114,7 +114,7 @@ class SettingsController extends Controller
if(isset($themeSettings['forms']['fields']))
{
$fields = $fieldsModel->getFields($userSettings, 'themes', $themeName, $themeSettings);
$fields = $fieldsModel->getFields($userSettings, 'themes', $themeName, $themeSettings);
/* overwrite original theme form definitions with enhanced form objects */
$themedata[$themeName]['forms']['fields'] = $fields;
@@ -193,7 +193,7 @@ class SettingsController extends Controller
$fields = $fieldsModel->getFields($userSettings, 'plugins', $pluginName, $pluginOriginalSettings);
/* overwrite original plugin form definitions with enhanced form objects */
$plugins[$pluginName]['forms']['fields'] = $fields;
$plugins[$pluginName]['forms']['fields'] = $fields;
}
}

View File

@@ -13,7 +13,7 @@ class Fields
# formtype are backend forms or public forms, only relevant for plugins for now
$formType = $formType ? $formType : 'forms';
# iterate through all fields of the objectSetting (theme or plugin)
foreach($objectSettings[$formType]['fields'] as $fieldName => $fieldConfigurations)
{

View File

@@ -285,7 +285,7 @@ class Validation
$v->rule('required', ['folder_id', 'item_name', 'type', 'url']);
$v->rule('regex', 'folder_id', '/^[0-9.]+$/i');
$v->rule('noSpecialChars', 'item_name');
$v->rule('lengthBetween', 'item_name', 1, 20);
$v->rule('lengthBetween', 'item_name', 1, 40);
$v->rule('in', 'type', ['file', 'folder']);
if($v->validate())

View File

@@ -24,7 +24,7 @@ class Write
}
else
{
throw new \Exception("The folder '{$folder}' is missing and we could not create it. Please create the folder manually on your server.");
# throw new \Exception("The folder '{$folder}' is missing and we could not create it. Please create the folder manually on your server.");
return false;
}
}
@@ -35,7 +35,7 @@ class Write
}
else
{
throw new \Exception("Please make the folder '{$folder}' writable.");
# throw new \Exception("Please make the folder '{$folder}' writable.");
return false;
}
return true;

View File

@@ -11,7 +11,7 @@
<h1>Hurra!</h1>
<p>Your account has been created and you are logged in now.</p>
<p><strong>Next step:</strong> Visit the author panel and setup your new website. You can configure the system, choose themes and add plugins.</p>
<p><strong>New:</strong> We recently added many format options like images, youtube videos, list and codeblocks to the visual content editor.</p>
<p><strong>New:</strong>Markdown is cool but editing tables is a nightmare. But not with Typemill, because we added a visual table editor recently. Try it!</p>
<p><strong>Get help:</strong> If you have any questions, please consult the <a target="_blank" href="https://typemill.net/typemill"><i class="icon-link-ext"></i> docs</a> or open a new issue on <a target="_blank" href="https://github.com/typemill/typemill"><i class="icon-link-ext"></i> github</a>.</p>
</div>
<a class="button" href="{{ path_for('settings.show') }}">Configure your website</a>

View File

@@ -1567,11 +1567,54 @@ button.format-item:hover{
font-weight: 700;
}
.blox tbody{}
.blox tr{}
.blox tr:nth-child(odd){ }
.blox th{ padding: 10px 0;}
.blox tr,.blox-editor tr{}
.blox tr:nth-child{ }
.blox tr:nth-child(even){ background-color:#f9f8f6; }
.blox td{ padding: 5px;}
.blox th{ padding: 10px 0;}
.blox-editor table{
display: inline-table;
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.blox-editor thead{}
.blox-editor tbody{}
.blox-editor tr{}
.blox-editor th{ border: 1px solid #ccc; padding: 5px; }
.blox-editor td{ border: 1px solid #ccc; padding: 5px; }
.blox-editor td.noteditable, .blox-editor th.noteditable{
border: 1px solid #ccc;
text-align:center;
color: #ccc;
background: #f9f8f6;
font-weight: 300;
padding: 0;
}
.blox-editor .columnaction, .blox-editor .rowaction{
position: absolute;
background: #fff;
width: 150px;
font-size: 0.9em;
color: #000;
text-align: left;
box-shadow: 0 0 2px #000;
margin: 5px;
z-index:999999;
}
.blox-editor .rowaction{
margin-left: 53px;
margin-top: -3px;
}
.blox-editor .actionline{
padding: 5px 10px;
cursor: pointer;
}
.blox-editor .actionline:hover{
background: #70c1b3;
color: #fff;
}
.blox dl{
border-top: 1px solid #e0474c;
border-bottom: 1px solid #e0474c;

View File

@@ -33,10 +33,10 @@
<button class="format-item" @click.prevent="setData( $event, 'olist-component' )" data-id="99999" id="blox-99999"><i class="icon-list-numbered"></i></button>
<button class="format-item" @click.prevent="setData( $event, 'image-component' )" data-id="99999" id="blox-99999"><i class="icon-picture"></i></button>
<button class="format-item" @click.prevent="setData( $event, 'video-component' )" data-id="99999" id="blox-99999"><i class="icon-youtube-play"></i></button>
<button class="format-item" @click.prevent="setData( $event, 'table-component' )" data-id="99999" id="blox-99999"><i class="icon-table"></i></button>
<button class="format-item" @click.prevent="setData( $event, 'quote-component' )" data-id="99999" id="blox-99999"><i class="icon-quote-left"></i></button>
<button class="format-item" @click.prevent="setData( $event, 'code-component' )" data-id="99999" id="blox-99999"><i class="icon-code"></i></button>
<!-- <button class="format-item" @click.prevent="setData( $event, 'code-component' )" data-id="99999" id="blox-99999"><i class="icon-table"></i></button>
<button class="format-item" @click.prevent="setData( $event, 'code-component' )" data-id="99999" id="blox-99999"><i class="icon-math"></i></button> -->
<!-- <button class="format-item" @click.prevent="setData( $event, 'code-component' )" data-id="99999" id="blox-99999"><i class="icon-math"></i></button> -->
</content-block>
</div>

View File

@@ -162,7 +162,7 @@ const contentComponent = Vue.component('content-block', {
}
},
saveBlock: function()
{
{
if(this.compmarkdown == undefined || this.compmarkdown.replace(/(\r\n|\n|\r|\s)/gm,"") == '')
{
this.switchToPreviewMode();
@@ -203,17 +203,17 @@ const contentComponent = Vue.component('content-block', {
if(httpStatus == 400)
{
self.activatePage();
publishController.errors.message = "Sorry, something went wrong. Maybe you are logged out? Please login and try again.";
publishController.errors.message = "Looks like you are logged out. Please login and try again.";
}
if(response)
else if(response)
{
self.activatePage();
var result = JSON.parse(response);
if(result.errors)
{
publishController.errors.message = result.errors.markdown[0];
publishController.errors.message = result.errors.message;
}
else
{
@@ -227,7 +227,8 @@ const contentComponent = Vue.component('content-block', {
self.$root.$data.blockMarkdown = '';
self.$root.$data.blockType = 'markdown-component';
self.getData();
document.querySelectorAll('textarea')[0].style.height = "70px";
var textbox = document.querySelectorAll('textarea')[0];
if(textbox){ textbox.style.height = "70px"; }
}
else
{
@@ -241,6 +242,11 @@ const contentComponent = Vue.component('content-block', {
}
}
}
else if(httpStatus != 200)
{
self.activatePage();
publishController.errors.message = "Sorry, something went wrong. Please refresh the page and try again.";
}
}, method, url, params);
}
},
@@ -430,6 +436,28 @@ const ulistComponent = Vue.component('ulist-component', {
{
this.compmarkdown = '* ';
}
else
{
var lines = this.compmarkdown.split("\n");
var length = lines.length
var md = '';
for(i = 0; i < length; i++)
{
var clean = lines[i];
clean = clean.replace(/^- /, '* ');
clean = clean.replace(/^\+ /, '* ');
if(i == length-1)
{
md += clean;
}
else
{
md += clean + '\n';
}
}
this.compmarkdown = md;
}
this.$nextTick(function () {
autosize(document.querySelectorAll('textarea'));
});
@@ -487,6 +515,219 @@ const headlineComponent = Vue.component('headline-component', {
},
})
const tableComponent = Vue.component('table-component', {
props: ['compmarkdown', 'disabled'],
data: function(){
return {
table: [
['0', '1', '2'],
['1', 'Head', 'Head'],
['2', 'cell', 'cell'],
['3', 'cell', 'cell'],
],
editable: 'editable',
noteditable: 'noteditable',
cellcontent: '',
columnbar: false,
rowbar: false,
tablekey: 1,
}
},
template: '<div ref="table" :key="tablekey">' +
'<div class="contenttype"><i class="icon-table"></i></div>' +
'<table ref="markdown">' +
'<colgroup>' +
'<col v-for="col in table[0]">' +
'</colgroup>' +
'<tbody>' +
'<tr v-for="(row, rowindex) in table">' +
'<td v-if="rowindex === 0" v-for="(value,colindex) in row" contenteditable="false" class="noteditable" @click="switchcolumnbar(value)">{{value}} ' +
'<div v-if="columnbar === value" class="columnaction">' +
'<div class="actionline" @click="addrightcolumn(value)">add right column</div>' +
'<div class="actionline" @click="addleftcolumn(value)">add left column</div>' +
'<div class="actionline" @click="deletecolumn(value)">delete column</div>' +
'</div>' +
'</td>' +
'<th v-if="rowindex === 1" v-for="(value,colindex) in row" :contenteditable="colindex !== 0 ? true : false" @click="switchrowbar(value)" @blur="updatedata($event,colindex,rowindex)" :class="colindex !== 0 ? editable : noteditable">' +
'<div v-if="colindex === 0 && rowbar === value" class="rowaction">' +
'<div class="actionline" @click="addaboverow(value)">add row above</div>' +
'<div class="actionline" @click="addbelowrow(value)">add row below</div>' +
'<div class="actionline" @click="deleterow(value)">delete row</div>' +
'</div>' +
'{{value}}</th>' +
'<td v-if="rowindex > 1" v-for="(value,colindex) in row" :contenteditable="colindex !== 0 ? true : false" @click="switchrowbar(value)" @blur="updatedata($event,colindex,rowindex)" :class="colindex !== 0 ? editable : noteditable">' +
'<div v-if="colindex === 0 && rowbar === value" class="rowaction">' +
'<div class="actionline" @click="addaboverow(value)">add row above</div>' +
'<div class="actionline" @click="addbelowrow(value)">add row below</div>' +
'<div class="actionline" @click="deleterow(value)">delete row</div>' +
'</div>' +
'{{ value }}</td>' +
'</tr>' +
'</tbody>' +
'</table>' +
'</div>',
mounted: function(){
this.$refs.markdown.focus();
if(this.compmarkdown)
{
var table = [];
var lines = this.compmarkdown.split("\n");
var length = lines.length
var c = 1;
for(i = 0; i < length; i++)
{
if(i == 1){ continue }
var line = lines[i].trim();
var row = line.split("|").map(function(cell){
return cell.trim();
});
if(row[0] == ''){ row.shift() }
if(row[row.length-1] == ''){ row.pop() }
if(i == 0)
{
var rlength = row.length;
var row0 = [];
for(y = 0; y <= rlength; y++) { row0.push(y) }
table.push(row0);
}
row.splice(0,0,c);
c++;
table.push(row);
}
this.table = table;
}
},
methods: {
updatedata: function(event,col,row)
{
this.table[row][col] = event.target.innerText;
this.markdowntable();
},
switchcolumnbar(value)
{
this.rowbar = false;
(this.columnbar == value || value == 0) ? this.columnbar = false : this.columnbar = value;
},
switchrowbar(value)
{
this.columnbar = false;
(this.rowbar == value || value == 0 || value == 1 )? this.rowbar = false : this.rowbar = value;
},
addaboverow: function(index)
{
var row = [];
var cols = this.table[0].length;
for(var i = 0; i < cols; i++){ row.push("new"); }
this.table.splice(index,0,row);
this.reindexrows();
},
addbelowrow: function(index)
{
var row = [];
var cols = this.table[0].length;
for(var i = 0; i < cols; i++){ row.push("new"); }
this.table.splice(index+1,0,row);
this.reindexrows();
},
deleterow: function(index)
{
this.table.splice(index,1);
this.reindexrows();
},
addrightcolumn: function(index)
{
var tableLength = this.table.length;
for (var i = 0; i < tableLength; i++)
{
this.table[i].splice(index+1,0,"new");
}
this.reindexcolumns();
},
addleftcolumn: function(index)
{
var tableLength = this.table.length;
for (var i = 0; i < tableLength; i++)
{
this.table[i].splice(index,0,"new");
}
this.reindexcolumns();
},
deletecolumn: function(index)
{
var tableLength = this.table.length;
for (var i = 0; i < tableLength; i++)
{
this.table[i].splice(index,1);
}
this.reindexcolumns();
},
reindexrows: function()
{
var tableRows = this.table.length;
for (var i = 0; i < tableRows; i++)
{
Vue.set(this.table[i], 0, i);
}
this.tablekey +=1;
this.markdowntable();
},
reindexcolumns: function()
{
var tableColumns = this.table[0].length;
for (var i = 0; i < tableColumns; i++)
{
Vue.set(this.table[0], i, i);
}
this.tablekey +=1;
this.markdowntable();
},
markdowntable: function()
{
var markdown = '';
var separator = '\n|';
var rows = this.table.length;
var cols = this.table[0].length;
for(var i = 0; i < cols; i++)
{
if(i == 0){ continue; }
separator += '---|';
}
for(var i = 0; i < rows; i++)
{
var row = this.table[i];
if(i == 0){ continue; }
for(var y = 0; y < cols; y++)
{
if(y == 0){ continue; }
var value = row[y].trim();
if(y == 1)
{
markdown += '\n| ' + value + ' | ';
}
else
{
markdown += value + ' | ';
}
}
if(i == 1) { markdown = markdown + separator; }
}
this.$emit('updatedMarkdown', markdown);
},
updatemarkdown: function(event)
{
/* generate markdown here ??? */
this.$emit('updatedMarkdown', event.target.value);
},
},
})
const videoComponent = Vue.component('video-component', {
props: ['compmarkdown', 'disabled', 'load'],
@@ -792,6 +1033,7 @@ let editor = new Vue({
'quote-component': quoteComponent,
'ulist-component': ulistComponent,
'olist-component': olistComponent,
'table-component': tableComponent,
},
data: {
root: document.getElementById("main").dataset.url,
@@ -877,6 +1119,12 @@ let editor = new Vue({
{
if(block.match(/^\d+\./)){ return "olist-component" }
var lines = block.split("\n");
if(lines.length > 2 && lines[0].indexOf('|') != -1 && /[\-\|: ]{3,}$/.test(lines[1]))
{
return "table-component";
}
var firstChar = block[0];
var secondChar = block[1];
var thirdChar = block[2];
@@ -898,10 +1146,10 @@ let editor = new Vue({
if(secondChar == "`" && thirdChar == "`") { return "code-component" } else { return "markdown-component" }
break;
case "*":
case "-":
case "+":
if(secondChar == " "){ return "ulist-component" } else { return "markdown-component" }
break;
case Number.isInteger(firstChar):
if(secondChar == "." ){ return "olist-component" } else { return "markdown-component" }
default:
return 'markdown-component';
}

View File

@@ -2,7 +2,10 @@ let editor = new Vue({
delimiters: ['${', '}'],
el: '#editor',
data: {
errors: false,
errors: {
title: false,
content: false,
},
form: {
title: document.getElementById("title").value,
content: document.getElementById("content").value,

View File

@@ -114,9 +114,9 @@ const navcomponent = Vue.component('navigation', {
{
publishController.errors.message = false;
if(this.$root.$data.format.test(this.newItem) || !this.newItem || this.newItem.length > 20)
{
publishController.errors.message = 'Special Characters are not allowed. Length between 1 and 20.';
if(this.$root.$data.format.test(this.newItem) || !this.newItem || this.newItem.length > 40)
{
publishController.errors.message = 'Special Characters are not allowed. Length between 1 and 40.';
return;
}

View File

@@ -11,8 +11,6 @@ let publishController = new Vue({
csrf_value: document.getElementById("csrf_value").value,
},
errors:{
title: false,
content: false,
message: false,
},
modalWindow: false,
@@ -30,7 +28,8 @@ let publishController = new Vue({
methods: {
publishDraft: function(e){
var self = this;
self.errors = {title: false, content: false, message: false};
self.errors.message = false;
editor.errors = {title: false, content: false};
self.publishResult = "load";
self.publishDisabled = "disabled";
@@ -52,7 +51,7 @@ let publishController = new Vue({
self.publishResult = "fail";
self.errors.message = "You are probably logged out. Please backup your changes, login and then try again."
}
if(response)
else if(response)
{
var result = JSON.parse(response);
@@ -60,13 +59,10 @@ let publishController = new Vue({
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = result.errors.content[0];
/*
if(result.errors.title){ self.errors.title = result.errors.title[0] };
if(result.errors.content){ self.errors.content = result.errors.content[0] };
if(result.errors.title){ editor.errors.title = result.errors.title[0] };
if(result.errors.content){ editor.errors.content = result.errors.content[0] };
if(result.errors.message){ self.errors.message = result.errors.message };
*/
}
else
{
@@ -76,12 +72,19 @@ let publishController = new Vue({
self.publishLabel = "online";
}
}
}, method, url, this.form );
else if(httpStatus != 200)
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = "Something went wrong, please refresh the page and try again."
}
}, method, url, this.form );
},
saveDraft: function(e){
var self = this;
self.errors = {title: false, content: false, message: false};
self.errors.message = false;
editor.errors = {title: false, content: false};
self.draftDisabled = "disabled";
self.draftResult = "load";
@@ -100,7 +103,7 @@ let publishController = new Vue({
self.publishResult = "fail";
self.errors.message = "You are probably logged out. Please backup your changes, login and then try again."
}
if(response)
else if(response)
{
var result = JSON.parse(response);
@@ -108,18 +111,22 @@ let publishController = new Vue({
{
self.draftDisabled = false;
self.draftResult = 'fail';
self.errors.message = result.errors.content[0];
/*
if(result.errors.title){ self.errors.title = result.errors.title[0] };
if(result.errors.content){ self.errors.message = result.errors.content[0] };
if(result.errors.message){ self.errors.message = result.errors.message };
*/
if(result.errors.title){ editor.errors.title = result.errors.title[0]; };
if(result.errors.content){ editor.errors.content = result.errors.content[0] };
if(result.errors.message){ self.errors.message = result.errors.message; };
}
else
{
self.draftResult = 'success';
}
}
else if(httpStatus != 200)
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = "Something went wrong, please refresh the page and try again."
}
}, method, url, this.form );
},
depublishArticle: function(e){
@@ -131,7 +138,8 @@ let publishController = new Vue({
}
var self = this;
self.errors = {title: false, content: false, message: false};
self.errors.message = false;
editor.errors = {title: false, content: false};
self.publishStatus = "disabled";
@@ -140,7 +148,19 @@ let publishController = new Vue({
sendJson(function(response, httpStatus)
{
if(response)
if(httpStatus == 400)
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = "You are probably logged out. Please backup your changes, login and then try again."
}
else if(httpStatus != 200)
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = "Something went wrong, please refresh the page and try again."
}
else if(response)
{
var result = JSON.parse(response);
@@ -160,7 +180,8 @@ let publishController = new Vue({
},
deleteArticle: function(e){
var self = this;
self.errors = {title: false, content: false, message: false};
self.errors.message = false;
editor.errors = {title: false, content: false};
self.deleteDisabled = "disabled";
self.deleteResult = "load";
@@ -170,7 +191,19 @@ let publishController = new Vue({
sendJson(function(response, httpStatus)
{
if(response)
if(httpStatus == 400)
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = "You are probably logged out. Please backup your changes, login and then try again."
}
else if(httpStatus != 200)
{
self.publishDisabled = false;
self.publishResult = "fail";
self.errors.message = "Something went wrong, please refresh the page and try again."
}
else if(response)
{
var result = JSON.parse(response);

View File

@@ -43,7 +43,20 @@
{% for field in plugin.forms.fields %}
{% include '/partials/fields.twig' with {'itemName' : pluginName, 'object' : 'plugins' } %}
{% if field.type == 'fieldset' %}
<fieldset class="subfield">
<legend>{{ field.legend }}</legend>
{% for field in field.fields %}
{% include '/partials/fields.twig' with {'itemName' : pluginName, 'object' : 'plugins' } %}
{% endfor %}
</fieldset>
{% else %}
{% include '/partials/fields.twig' with {'itemName' : pluginName, 'object' : 'plugins' } %}
{% endif %}
{% endfor %}

View File

@@ -13,16 +13,22 @@
"src": "fontawesome"
},
{
"uid": "e9107949dd6c9e8ab2b29ae07156e38c",
"css": "linkedin",
"code": 61665,
"src": "fontawesome"
"uid": "91426c82d94428a33353e495418435e3",
"css": "share",
"code": 59393,
"src": "entypo"
},
{
"uid": "11ebb30e17efcd988a228ade5d3e8c74",
"css": "xing",
"code": 61800,
"src": "fontawesome"
"uid": "884cfc3e6e2d456dd2a2ca0dbb9e6337",
"css": "left-open-big",
"code": 59394,
"src": "entypo"
},
{
"uid": "004882ab2d5c418c5b2060e80596279b",
"css": "right-open-big",
"code": 59395,
"src": "entypo"
},
{
"uid": "627abcdb627cb1789e009c08e2678ef9",
@@ -30,12 +36,6 @@
"code": 61593,
"src": "fontawesome"
},
{
"uid": "9d3e9faf68fd4e12def853f0d4e1173b",
"css": "whatsapp",
"code": 62002,
"src": "fontawesome"
},
{
"uid": "8e04c98c8f5ca0a035776e3001ad2638",
"css": "facebook",
@@ -43,22 +43,34 @@
"src": "fontawesome"
},
{
"uid": "884cfc3e6e2d456dd2a2ca0dbb9e6337",
"css": "left-open-big",
"code": 59393,
"src": "entypo"
"uid": "11ebb30e17efcd988a228ade5d3e8c74",
"css": "xing",
"code": 61800,
"src": "fontawesome"
},
{
"uid": "004882ab2d5c418c5b2060e80596279b",
"css": "right-open-big",
"code": 59394,
"src": "entypo"
"uid": "e9107949dd6c9e8ab2b29ae07156e38c",
"css": "linkedin",
"code": 61665,
"src": "fontawesome"
},
{
"uid": "91426c82d94428a33353e495418435e3",
"css": "share-1",
"code": 59395,
"src": "entypo"
"uid": "9d3e9faf68fd4e12def853f0d4e1173b",
"css": "whatsapp",
"code": 62002,
"src": "fontawesome"
},
{
"uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
"css": "download",
"code": 59396,
"src": "fontawesome"
},
{
"uid": "0f6a2573a7b6df911ed199bb63717e27",
"css": "github-circled",
"code": 61595,
"src": "fontawesome"
}
]
}

View File

@@ -1,10 +1,12 @@
.icon-mail:before { content: '\e800'; } /* '' */
.icon-left-open-big:before { content: '\e801'; } /* '' */
.icon-right-open-big:before { content: '\e802'; } /* '' */
.icon-share-1:before { content: '\e803'; } /* '' */
.icon-share:before { content: '\e801'; } /* '' */
.icon-left-open-big:before { content: '\e802'; } /* '' */
.icon-right-open-big:before { content: '\e803'; } /* '' */
.icon-download:before { content: '\e804'; } /* '' */
.icon-twitter:before { content: '\f099'; } /* '' */
.icon-facebook:before { content: '\f09a'; } /* '' */
.icon-github-circled:before { content: '\f09b'; } /* '' */
.icon-linkedin:before { content: '\f0e1'; } /* '' */
.icon-xing:before { content: '\f168'; } /* '' */
.icon-whatsapp:before { content: '\f232'; } /* '' */

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,12 @@
.icon-mail { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.icon-left-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-right-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-share-1 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-left-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-right-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe804;&nbsp;'); }
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;&nbsp;'); }
.icon-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;&nbsp;'); }
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09b;&nbsp;'); }
.icon-linkedin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e1;&nbsp;'); }
.icon-xing { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf168;&nbsp;'); }
.icon-whatsapp { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf232;&nbsp;'); }

View File

@@ -11,11 +11,13 @@
}
.icon-mail { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.icon-left-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-right-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-share-1 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-left-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-right-open-big { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe804;&nbsp;'); }
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;&nbsp;'); }
.icon-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;&nbsp;'); }
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09b;&nbsp;'); }
.icon-linkedin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e1;&nbsp;'); }
.icon-xing { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf168;&nbsp;'); }
.icon-whatsapp { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf232;&nbsp;'); }

View File

@@ -1,11 +1,11 @@
@font-face {
font-family: 'fontello';
src: url('../font/fontello.eot?45966989');
src: url('../font/fontello.eot?45966989#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?45966989') format('woff2'),
url('../font/fontello.woff?45966989') format('woff'),
url('../font/fontello.ttf?45966989') format('truetype'),
url('../font/fontello.svg?45966989#fontello') format('svg');
src: url('../font/fontello.eot?8743082');
src: url('../font/fontello.eot?8743082#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?8743082') format('woff2'),
url('../font/fontello.woff?8743082') format('woff'),
url('../font/fontello.ttf?8743082') format('truetype'),
url('../font/fontello.svg?8743082#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?45966989#fontello') format('svg');
src: url('../font/fontello.svg?8743082#fontello') format('svg');
}
}
*/
@@ -56,11 +56,13 @@
}
.icon-mail:before { content: '\e800'; } /* '' */
.icon-left-open-big:before { content: '\e801'; } /* '' */
.icon-right-open-big:before { content: '\e802'; } /* '' */
.icon-share-1:before { content: '\e803'; } /* '' */
.icon-share:before { content: '\e801'; } /* '' */
.icon-left-open-big:before { content: '\e802'; } /* '' */
.icon-right-open-big:before { content: '\e803'; } /* '' */
.icon-download:before { content: '\e804'; } /* '' */
.icon-twitter:before { content: '\f099'; } /* '' */
.icon-facebook:before { content: '\f09a'; } /* '' */
.icon-github-circled:before { content: '\f09b'; } /* '' */
.icon-linkedin:before { content: '\f0e1'; } /* '' */
.icon-xing:before { content: '\f168'; } /* '' */
.icon-whatsapp:before { content: '\f232'; } /* '' */

View File

@@ -229,11 +229,11 @@ body {
}
@font-face {
font-family: 'fontello';
src: url('./font/fontello.eot?98470540');
src: url('./font/fontello.eot?98470540#iefix') format('embedded-opentype'),
url('./font/fontello.woff?98470540') format('woff'),
url('./font/fontello.ttf?98470540') format('truetype'),
url('./font/fontello.svg?98470540#fontello') format('svg');
src: url('./font/fontello.eot?27459207');
src: url('./font/fontello.eot?27459207#iefix') format('embedded-opentype'),
url('./font/fontello.woff?27459207') format('woff'),
url('./font/fontello.ttf?27459207') format('truetype'),
url('./font/fontello.svg?27459207#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -299,17 +299,19 @@ body {
<div class="container" id="icons">
<div class="row">
<div class="the-icons span3" title="Code: 0xe800"><i class="demo-icon icon-mail">&#xe800;</i> <span class="i-name">icon-mail</span><span class="i-code">0xe800</span></div>
<div class="the-icons span3" title="Code: 0xe801"><i class="demo-icon icon-left-open-big">&#xe801;</i> <span class="i-name">icon-left-open-big</span><span class="i-code">0xe801</span></div>
<div class="the-icons span3" title="Code: 0xe802"><i class="demo-icon icon-right-open-big">&#xe802;</i> <span class="i-name">icon-right-open-big</span><span class="i-code">0xe802</span></div>
<div class="the-icons span3" title="Code: 0xe803"><i class="demo-icon icon-share-1">&#xe803;</i> <span class="i-name">icon-share-1</span><span class="i-code">0xe803</span></div>
<div class="the-icons span3" title="Code: 0xe801"><i class="demo-icon icon-share">&#xe801;</i> <span class="i-name">icon-share</span><span class="i-code">0xe801</span></div>
<div class="the-icons span3" title="Code: 0xe802"><i class="demo-icon icon-left-open-big">&#xe802;</i> <span class="i-name">icon-left-open-big</span><span class="i-code">0xe802</span></div>
<div class="the-icons span3" title="Code: 0xe803"><i class="demo-icon icon-right-open-big">&#xe803;</i> <span class="i-name">icon-right-open-big</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-download">&#xe804;</i> <span class="i-name">icon-download</span><span class="i-code">0xe804</span></div>
<div class="the-icons span3" title="Code: 0xf099"><i class="demo-icon icon-twitter">&#xf099;</i> <span class="i-name">icon-twitter</span><span class="i-code">0xf099</span></div>
<div class="the-icons span3" title="Code: 0xf09a"><i class="demo-icon icon-facebook">&#xf09a;</i> <span class="i-name">icon-facebook</span><span class="i-code">0xf09a</span></div>
<div class="the-icons span3" title="Code: 0xf0e1"><i class="demo-icon icon-linkedin">&#xf0e1;</i> <span class="i-name">icon-linkedin</span><span class="i-code">0xf0e1</span></div>
<div class="the-icons span3" title="Code: 0xf168"><i class="demo-icon icon-xing">&#xf168;</i> <span class="i-name">icon-xing</span><span class="i-code">0xf168</span></div>
<div class="the-icons span3" title="Code: 0xf09b"><i class="demo-icon icon-github-circled">&#xf09b;</i> <span class="i-name">icon-github-circled</span><span class="i-code">0xf09b</span></div>
</div>
<div class="row">
<div class="the-icons span3" title="Code: 0xf0e1"><i class="demo-icon icon-linkedin">&#xf0e1;</i> <span class="i-name">icon-linkedin</span><span class="i-code">0xf0e1</span></div>
<div class="the-icons span3" title="Code: 0xf168"><i class="demo-icon icon-xing">&#xf168;</i> <span class="i-name">icon-xing</span><span class="i-code">0xf168</span></div>
<div class="the-icons span3" title="Code: 0xf232"><i class="demo-icon icon-whatsapp">&#xf232;</i> <span class="i-name">icon-whatsapp</span><span class="i-code">0xf232</span></div>
</div>
</div>

View File

@@ -1,23 +1,27 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2018 by original authors @ fontello.com</metadata>
<metadata>Copyright (C) 2019 by original authors @ fontello.com</metadata>
<defs>
<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="mail" unicode="&#xe800;" d="M929 11v428q-18-20-39-36-149-115-238-189-28-24-46-37t-48-28-57-13h-2q-26 0-57 13t-48 28-46 37q-88 74-238 189-21 16-39 36v-428q0-7 6-13t12-5h822q7 0 12 5t6 13z m0 586v14t-1 7-1 7-3 5-5 4-8 2h-822q-7 0-12-6t-6-12q0-94 83-159 107-84 223-176 4-3 20-17t25-21 25-17 28-16 24-5h2q11 0 24 5t28 16 25 17 25 21 20 17q116 92 224 176 30 24 56 65t26 73z m71 21v-607q0-37-26-63t-63-27h-822q-36 0-63 27t-26 63v607q0 37 26 63t63 26h822q37 0 63-26t26-63z" horiz-adv-x="1000" />
<glyph glyph-name="left-open-big" unicode="&#xe801;" d="M452-20q26-26 0-48-26-26-48 0l-392 394q-24 24 0 50l392 394q22 26 48 0 26-22 0-48l-358-372z" horiz-adv-x="465" />
<glyph glyph-name="share" unicode="&#xe801;" d="M650 200q62 0 106-43t44-107q0-62-44-106t-106-44-106 44-44 106q0 6 1 14t1 12l-260 156q-42-32-92-32-62 0-106 44t-44 106 44 106 106 44q54 0 92-30l260 156q0 4-1 12t-1 12q0 62 44 106t106 44 106-43 44-107q0-62-44-106t-106-44q-52 0-90 32l-262-156q2-8 2-26 0-16-2-24l262-156q36 30 90 30z" horiz-adv-x="800" />
<glyph glyph-name="right-open-big" unicode="&#xe802;" d="M13-20l358 370-358 372q-26 26 0 48 26 26 48 0l392-394q24-26 0-50l-392-394q-22-26-48 0-26 22 0 48z" horiz-adv-x="465" />
<glyph glyph-name="left-open-big" unicode="&#xe802;" d="M452-20q26-26 0-48-26-26-48 0l-392 394q-24 24 0 50l392 394q22 26 48 0 26-22 0-48l-358-372z" horiz-adv-x="465" />
<glyph glyph-name="share-1" unicode="&#xe803;" d="M650 200q62 0 106-43t44-107q0-62-44-106t-106-44-106 44-44 106q0 6 1 14t1 12l-260 156q-42-32-92-32-62 0-106 44t-44 106 44 106 106 44q54 0 92-30l260 156q0 4-1 12t-1 12q0 62 44 106t106 44 106-43 44-107q0-62-44-106t-106-44q-52 0-90 32l-262-156q2-8 2-26 0-16-2-24l262-156q36 30 90 30z" horiz-adv-x="800" />
<glyph glyph-name="right-open-big" unicode="&#xe803;" d="M13-20l358 370-358 372q-26 26 0 48 26 26 48 0l392-394q24-26 0-50l-392-394q-22-26-48 0-26 22 0 48z" horiz-adv-x="465" />
<glyph glyph-name="download" unicode="&#xe804;" d="M714 100q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
<glyph glyph-name="twitter" unicode="&#xf099;" d="M904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 115 44-21-64-80-100 52 6 104 28z" horiz-adv-x="928.6" />
<glyph glyph-name="facebook" unicode="&#xf09a;" d="M535 843v-147h-87q-48 0-65-20t-17-60v-106h164l-22-165h-142v-424h-171v424h-142v165h142v122q0 104 58 161t155 57q82 0 127-7z" horiz-adv-x="571.4" />
<glyph glyph-name="github-circled" unicode="&#xf09b;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
<glyph glyph-name="linkedin" unicode="&#xf0e1;" d="M195 501v-553h-184v553h184z m12 171q0-41-29-68t-75-27h-1q-46 0-74 27t-28 68q0 41 29 68t75 27 74-27 29-68z m650-407v-317h-183v296q0 59-23 92t-71 33q-35 0-58-19t-36-48q-6-17-6-45v-309h-184q1 223 1 361t0 165l-1 27h184v-80h-1q11 18 23 31t31 29 49 24 64 9q95 0 153-63t58-186z" horiz-adv-x="857.1" />
<glyph glyph-name="xing" unicode="&#xf168;" d="M333 478q-5-10-143-255-15-25-36-25h-134q-12 0-17 9t0 20l141 250q1 0 0 1l-90 156q-7 12 0 20 5 9 17 9h134q22 0 37-26z m450 358q6-9 0-21l-295-521v0l188-344q6-11 0-20-5-9-17-9h-134q-23 0-37 25l-189 348q10 18 296 525 14 25 36 25h135q12 0 17-8z" horiz-adv-x="785.7" />

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -377,6 +377,9 @@ article button.play-video::after {
border-color: transparent transparent transparent rgba(255, 255, 255, 0.75);
content: ' ';
}
article .gitlink{
float: right;
}
/************************
* PAGING / BREADCRUMB *

View File

@@ -6,7 +6,7 @@
<h1>{{ title }}</h1>
{% if (settings.themes.typemill.socialPosition.top or settings.themes.typemill.modifiedPosition.top or settings.themes.typemill.authorPosition.top) %}
{% if (settings.themes.typemill.socialPosition.top or settings.themes.typemill.modifiedPosition.top or settings.themes.typemill.authorPosition.top or settings.themes.typemill.gitPosition.top) %}
<div class="meta-info">
{% if settings.themes.typemill.authorPosition.top %}
<small>{{ settings.themes.typemill.authorIntro }}: {{ settings.author }}</small>
@@ -22,13 +22,16 @@
</div>
</div>
{% endif %}
{% if settings.themes.typemill.gitPosition.top %}
<div class="gitlink"><a title="edit on git" href="{{ settings.themes.typemill.gitlink }}/{{ item.urlRel }}">edit <i class="icon-github-circled"></i></a></div>
{% endif %}
</div>
{% endif %}
{{ content }}
{% if (settings.themes.typemill.socialPosition.bottom or settings.themes.typemill.modifiedPosition.bottom or settings.themes.typemill.authorPosition.bottom) %}
{% if (settings.themes.typemill.socialPosition.bottom or settings.themes.typemill.modifiedPosition.bottom or settings.themes.typemill.authorPosition.bottom or settings.themes.typemill.gitPosition.bottom) %}
<div class="meta-info">
{% if settings.themes.typemill.authorPosition.bottom %}
<small>{{ settings.themes.typemill.authorIntro }}: {{ settings.author }}</small>
@@ -44,11 +47,13 @@
</div>
</div>
{% endif %}
{% if settings.themes.typemill.gitPosition.bottom %}
<div class="gitlink"><a title="edit on git" href="{{ settings.themes.typemill.gitlink }}/{{ item.urlRel }}">edit <i class="icon-github-circled"></i></a></div>
{% endif %}
</div>
{% endif %}
{% if item.prevItem or item.nextItem %}
<div class="paging">

View File

@@ -1,4 +1,4 @@
{% macro loop_over(navigation) %}
{% macro loop_over(navigation,chapnum) %}
{% import _self as macros %}
@@ -14,12 +14,12 @@
<li class="{{ element.elementType }} level-{{ depth }}">
{% endif %}
{% if (element.elementType == 'folder') %}
<a href="{{ element.urlAbs }}">{{ element.name }}</a>
<a href="{{ element.urlAbs }}">{% if chapnum %}{{ element.chapter }}. {% endif %}{{ element.name }}</a>
<ul>
{{ macros.loop_over(element.folderContent) }}
{{ macros.loop_over(element.folderContent,chapnum) }}
</ul>
{% else %}
<a href="{{ element.urlAbs }}">{{ element.name }}</a>
<a href="{{ element.urlAbs }}">{% if chapnum %}{{ element.chapter }} {% endif %}{{ element.name }}</a>
{% endif %}
</li>
{% endfor %}
@@ -28,5 +28,5 @@
{% import _self as macros %}
<ul>
{{ macros.loop_over(navigation) }}
{{ macros.loop_over(navigation,settings.themes.typemill.chapnum) }}
</ul>

View File

@@ -1,5 +1,5 @@
name: Typemill Theme
version: 1.1.3
version: 1.1.4
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
@@ -30,6 +30,11 @@ forms:
placeholder: Add Label for Start-Button
required: true
chapnum:
type: checkbox
label: Chapter Numbers
checkboxlabel: Count chapters in navigation?
fieldset0:
type: fieldset
legend: Author
@@ -90,4 +95,21 @@ forms:
xing: Xing
linkedin: Linkedin
whatsapp: WhatsApp
mail: Mail
mail: Mail
fieldset3:
type: fieldset
legend: GitHub
fields:
gitPosition:
type: checkboxlist
label: Position of Git Edit Link
options:
top: Top
bottom: Bottom
gitlink:
type: text
label: Link to git repository
placeholder: https://github.com/typemill/documentation
help: Please add the base url to the text repository e.g. on github.