Merge remote-tracking branch 'refs/remotes/origin/master' into feature/documentation
|
@ -3,10 +3,17 @@ python: 2.7
|
||||||
install:
|
install:
|
||||||
- "pip install -U pip"
|
- "pip install -U pip"
|
||||||
- "pip install git+https://github.com/lektor/lektor#egg=Lektor"
|
- "pip install git+https://github.com/lektor/lektor#egg=Lektor"
|
||||||
script: "lektor build && lektor deploy production"
|
script:
|
||||||
|
- "lektor build"
|
||||||
|
- "test \"$TRAVIS_PULL_REQUEST\" == \"false\" && test \"$TRAVIS_BRANCH\" == \"master\" && lektor deploy production"
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.cache/pip
|
- $HOME/.cache/pip
|
||||||
- $HOME/.cache/lektor/builds
|
- $HOME/.cache/lektor/builds
|
||||||
addons:
|
addons:
|
||||||
ssh_known_hosts: flow.srv.pocoo.org
|
ssh_known_hosts: flow.srv.pocoo.org
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/f0c538cdfc9883f81e34
|
||||||
|
|
|
@ -12,3 +12,5 @@ default = yes
|
||||||
[packages]
|
[packages]
|
||||||
lektor-webpack-support = 0.1
|
lektor-webpack-support = 0.1
|
||||||
lektor-disqus-comments = 0.1
|
lektor-disqus-comments = 0.1
|
||||||
|
lektor-markdown-header-anchors = 0.1
|
||||||
|
lektor-markdown-highlighter = 0.1
|
||||||
|
|
|
@ -24,6 +24,7 @@ if 1:
|
||||||
import json
|
import json
|
||||||
import urllib
|
import urllib
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import shutil
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
|
||||||
sys.stdin = open('/dev/tty', 'r')
|
sys.stdin = open('/dev/tty', 'r')
|
||||||
|
@ -59,6 +60,32 @@ if 1:
|
||||||
os.path.dirname(path), 'lib', 'lektor')
|
os.path.dirname(path), 'lib', 'lektor')
|
||||||
None, None
|
None, None
|
||||||
|
|
||||||
|
def get_confirmation():
|
||||||
|
while 1:
|
||||||
|
input = raw_input('Continue? [Yn] ').lower().strip()
|
||||||
|
if input in ('', 'y'):
|
||||||
|
break
|
||||||
|
elif input == 'n':
|
||||||
|
print
|
||||||
|
print 'Aborted!'
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
def wipe_installation(lib_dir, symlink_path):
|
||||||
|
if os.path.lexists(symlink_path):
|
||||||
|
os.remove(symlink_path)
|
||||||
|
if os.path.exists(lib_dir):
|
||||||
|
shutil.rmtree(lib_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
def check_installation(lib_dir, bin_dir):
|
||||||
|
symlink_path = os.path.join(bin_dir, 'lektor')
|
||||||
|
if os.path.exists(lib_dir) or os.path.lexists(symlink_path):
|
||||||
|
print ' Lektor seems to be installed already.'
|
||||||
|
print ' Continuing will wipe %s and remove %s' % (lib_dir, symlink_path)
|
||||||
|
print
|
||||||
|
get_confirmation()
|
||||||
|
print
|
||||||
|
wipe_installation(lib_dir, symlink_path)
|
||||||
|
|
||||||
def fail(message):
|
def fail(message):
|
||||||
print 'Error: %s' % message
|
print 'Error: %s' % message
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -67,17 +94,19 @@ if 1:
|
||||||
t = tempfile.mkdtemp()
|
t = tempfile.mkdtemp()
|
||||||
Popen('curl -sf "%s" | tar -xzf - --strip-components=1' %
|
Popen('curl -sf "%s" | tar -xzf - --strip-components=1' %
|
||||||
virtualenv_url, shell=True, cwd=t).wait()
|
virtualenv_url, shell=True, cwd=t).wait()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(lib_dir)
|
os.makedirs(lib_dir)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
Popen(['./virtualenv.py', lib_dir], cwd=t).wait()
|
Popen(['./virtualenv.py', lib_dir], cwd=t).wait()
|
||||||
Popen([os.path.join(lib_dir, 'bin', 'pip'),
|
Popen([os.path.join(lib_dir, 'bin', 'pip'),
|
||||||
'install', '--upgrade', 'Lektor']).wait()
|
'install', '--upgrade', 'Lektor']).wait()
|
||||||
os.symlink(os.path.join(lib_dir, 'bin', 'lektor'),
|
os.symlink(os.path.join(lib_dir, 'bin', 'lektor'),
|
||||||
os.path.join(bin_dir, 'lektor'))
|
os.path.join(bin_dir, 'lektor'))
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
print
|
||||||
print 'Welcome to Lektor'
|
print 'Welcome to Lektor'
|
||||||
print
|
print
|
||||||
print 'This script will install Lektor on your computer.'
|
print 'This script will install Lektor on your computer.'
|
||||||
|
@ -92,17 +121,14 @@ if 1:
|
||||||
if bin_dir is None or lib_dir is None:
|
if bin_dir is None or lib_dir is None:
|
||||||
fail('Could not determine installation location for Lektor.')
|
fail('Could not determine installation location for Lektor.')
|
||||||
|
|
||||||
|
check_installation(lib_dir, bin_dir)
|
||||||
|
|
||||||
|
print 'Installing at:'
|
||||||
print ' bin: %s' % bin_dir
|
print ' bin: %s' % bin_dir
|
||||||
print ' app: %s' % lib_dir
|
print ' app: %s' % lib_dir
|
||||||
print
|
print
|
||||||
|
|
||||||
while 1:
|
get_confirmation()
|
||||||
input = raw_input('Continue? [Yn] ').lower().strip()
|
|
||||||
if input in ('', 'y'):
|
|
||||||
break
|
|
||||||
elif input == 'n':
|
|
||||||
print 'Aborted!'
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
for url in json.load(urllib.urlopen(VENV_URL))['urls']:
|
for url in json.load(urllib.urlopen(VENV_URL))['urls']:
|
||||||
if url['python_version'] == 'source':
|
if url['python_version'] == 'source':
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
!function(t){function e(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return t[i].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){(function(t){"use strict";function e(t){if(document.body.createTextRange){var e=document.body.createTextRange();e.moveToElementText(t),e.select()}else if(window.getSelection){var n=window.getSelection(),e=document.createRange();e.selectNodeContents(t),n.removeAllRanges(),n.addRange(e)}}function i(){var e=t(".download-btn");e.length<=0||(e.hide(),t.ajax({method:"GET",url:"https://api.github.com/repos/lektor/lektor/releases",crossDomain:!0}).then(function(t){r(e.toArray(),t)},function(){e.show()}))}function o(t){var e=null,n=null;if(navigator.platform.match(/^mac/i)&&(e=/\.dmg$/,n="For OSX 10.9 and later."),null!=e)for(var i=0;i<t.length;i++)if(t[i].name.match(e))return{url:t[i].browser_download_url,note:n};return null}function r(e,n){var i=n[0].tag_name,r="/downloads/",s=o(n[0].assets);e.forEach(function(e){var n=t('<div class="note"></div>').appendTo(e),o=t("a",e);s?(o.attr("href",s.url),n.append(t("<span></span>").text(s.note+" ")),n.append(t("<a>Other platforms</a>").attr("href",r))):o.attr("href",r),o.append(t('<span class="version"></span>').text(i)),t(e).fadeIn("slow")})}function s(){var n=t(".install-row pre");n.length>0&&n.on("dblclick",function(){e(this)})}function a(){var e=t(".google-custom-search");if(0!=e.length){var n="012722186170730423054:utwznhnrrmi",i=document.createElement("script");i.type="text/javascript",i.async=!0,i.src=("https:"==document.location.protocol?"https:":"http:")+"//cse.google.com/cse.js?cx="+n;var o=document.getElementsByTagName("script")[0];o.parentNode.insertBefore(i,o),t('\n <gcse:searchresults-only linktarget="_parent"></gcse:searchresults-only>\n ').appendTo(e),t('\n <div style="display: none">\n <div id="base_webResult">\n <div class="gs-webResult gs-result"\n data-vars="{\n longUrl: function() {\n var i = unescapedUrl.indexOf(visibleUrl);\n return i < 1 ? visibleUrl : unescapedUrl.substring(i);\n },\n processSearchTitle: function(title) {\n return title.split(\' | \').slice(0, -2).join(\' | \') || \'Documentation\';\n }\n }">\n <div class="gs-title">\n <a class="gs-title" data-attr="{href:unescapedUrl, target:target}"\n data-body="html(processSearchTitle(title))"></a>\n </div>\n <div class="gs-visibleUrl gs-visibleUrl-long" data-body="longUrl()"></div>\n <div class="gs-snippet" data-body="html(content)"></div>\n </div>\n </div>\n </div>\n ').appendTo(e);var r=c.parse(location.search);r.q&&t('input[name="q"]',e).val(r.q)}}function l(){navigator.appVersion.indexOf("Win")>=0&&t(".hide-for-windows").hide()}n(2);var c=n(15);t(function(){i(),s(),a(),l()})}).call(e,n(1))},function(t,e,n){var i,o;/*!
|
!function(t){function e(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return t[i].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){(function(t){"use strict";function e(t){if(document.body.createTextRange){var e=document.body.createTextRange();e.moveToElementText(t),e.select()}else if(window.getSelection){var n=window.getSelection(),e=document.createRange();e.selectNodeContents(t),n.removeAllRanges(),n.addRange(e)}}function i(){function e(){var o=n[i++];o&&(window.setTimeout(e,200),t(o).fadeIn())}var n=t(".badges li").hide();if(!(n.length<=0)){var i=0;window.setTimeout(function(){e()},1e3)}}function o(){var e=t(".download-btn");e.length<=0||(e.hide(),t.ajax({method:"GET",url:"https://api.github.com/repos/lektor/lektor/releases",crossDomain:!0}).then(function(t){s(e.toArray(),t)},function(){e.show()}))}function r(t){var e=null,n=null;if(navigator.platform.match(/^mac/i)&&(e=/\.dmg$/,n="For OSX 10.9 and later."),null!=e)for(var i=0;i<t.length;i++)if(t[i].name.match(e))return{url:t[i].browser_download_url,note:n};return null}function s(e,n){var i=n[0].tag_name,o="/downloads/",s=r(n[0].assets);e.forEach(function(e){var n=t('<div class="note"></div>').appendTo(e),r=t("a",e);s?(r.attr("href",s.url),n.append(t("<span></span>").text(s.note+" ")),n.append(t("<a>Other platforms</a>").attr("href",o))):r.attr("href",o),r.append(t('<span class="version"></span>').text(i)),t(e).fadeIn("slow")})}function a(){var n=t(".install-row pre");n.length>0&&n.on("dblclick",function(){e(this)})}function l(){var e=t(".google-custom-search");if(0!=e.length){var n="012722186170730423054:utwznhnrrmi",i=document.createElement("script");i.type="text/javascript",i.async=!0,i.src=("https:"==document.location.protocol?"https:":"http:")+"//cse.google.com/cse.js?cx="+n;var o=document.getElementsByTagName("script")[0];o.parentNode.insertBefore(i,o),t('\n <gcse:searchresults-only linktarget="_parent"></gcse:searchresults-only>\n ').appendTo(e),t('\n <div style="display: none">\n <div id="base_webResult">\n <div class="gs-webResult gs-result"\n data-vars="{\n longUrl: function() {\n var i = unescapedUrl.indexOf(visibleUrl);\n return i < 1 ? visibleUrl : unescapedUrl.substring(i);\n },\n processSearchTitle: function(title) {\n return title.split(\' | \').slice(0, -2).join(\' | \') || \'Documentation\';\n }\n }">\n <div class="gs-title">\n <a class="gs-title" data-attr="{href:unescapedUrl, target:target}"\n data-body="html(processSearchTitle(title))"></a>\n </div>\n <div class="gs-visibleUrl gs-visibleUrl-long" data-body="longUrl()"></div>\n <div class="gs-snippet" data-body="html(content)"></div>\n </div>\n </div>\n </div>\n ').appendTo(e);var r=u.parse(location.search);r.q&&t('input[name="q"]',e).val(r.q)}}function c(){navigator.appVersion.indexOf("Win")>=0&&t(".hide-for-windows").hide()}n(2);var u=n(15);t(function(){i(),o(),a(),l(),c()})}).call(e,n(1))},function(t,e,n){var i,o;/*!
|
||||||
* jQuery JavaScript Library v2.1.4
|
* jQuery JavaScript Library v2.1.4
|
||||||
* http://jquery.com/
|
* http://jquery.com/
|
||||||
*
|
*
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"app.js","sources":["webpack:///app.js","webpack:///"],"mappings":"AAAA;;;;;;;;;;;;;AC+LA;;;;;;;;;;AAqiBA;AAqpHA;AAkgIA;AAg3EA","sourceRoot":""}
|
{"version":3,"file":"app.js","sources":["webpack:///app.js","webpack:///"],"mappings":"AAAA;;;;;;;;;;;;;ACuNA;;;;;;;;;;AAqiBA;AAqpHA;AAkgIA;AAg3EA","sourceRoot":""}
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 211 KiB |
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 415 KiB After Width: | Height: | Size: 368 KiB |
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 158 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
title: Lektor Loves Travis-CI and GitHub Pages
|
||||||
|
---
|
||||||
|
summary:
|
||||||
|
|
||||||
|
Read about how to use Lektor with Travis-CI and GitHub Pages.
|
||||||
|
---
|
||||||
|
pub_date: 2015-12-23
|
||||||
|
---
|
||||||
|
author: Armin Ronacher
|
||||||
|
---
|
||||||
|
twitter_handle: mitsuhiko
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
#### banner ####
|
||||||
|
image: header.jpg
|
||||||
|
----
|
||||||
|
height: 500
|
||||||
|
#### text-block ####
|
||||||
|
text:
|
||||||
|
|
||||||
|
Open Source projects need websites, that's a given, and one of the most popular
|
||||||
|
ways to host them these days is [GitHub Pages :ext](https://pages.github.com/).
|
||||||
|
It's a free service provided by [GitHub :ext](https://github.com/) which allows
|
||||||
|
hosts a git repository as a website on a subdomain of `github.io`.
|
||||||
|
|
||||||
|
Wouldn't it be nice if you could easily host Lektor projects on there? Turns
|
||||||
|
out you can with the help of [Travis-CI :ext](https://travis-ci.org/). Because
|
||||||
|
Lektor has built-in support for deploying to GitHub Pages pairing up the three
|
||||||
|
is a breeze.
|
||||||
|
|
||||||
|
We [created a guide :ref](../../../../docs/deployment/travisci/) and also recorded
|
||||||
|
a screencast that goes with it:
|
||||||
|
|
||||||
|
<iframe width="100%" height=410 frameborder="0" allowfullscreen="allowfullscreen"
|
||||||
|
src="https://www.youtube.com/embed/3pj_EyZIL5A?autoplay=0&fs=1">
|
||||||
|
</iframe>
|
After Width: | Height: | Size: 272 KiB |
Before Width: | Height: | Size: 337 KiB After Width: | Height: | Size: 314 KiB |
|
@ -9,8 +9,6 @@ image: header.jpg
|
||||||
----
|
----
|
||||||
height: 500
|
height: 500
|
||||||
----
|
----
|
||||||
class: dark
|
|
||||||
----
|
|
||||||
contents:
|
contents:
|
||||||
|
|
||||||
<div class="container lektor-intro">
|
<div class="container lektor-intro">
|
||||||
|
@ -37,6 +35,9 @@ contents:
|
||||||
data-count-api="/repos/lektor/lektor#stargazers_count"
|
data-count-api="/repos/lektor/lektor#stargazers_count"
|
||||||
data-count-aria-label="# stargazers on GitHub"
|
data-count-aria-label="# stargazers on GitHub"
|
||||||
aria-label="Star lektor/lektor on GitHub">Star</a>
|
aria-label="Star lektor/lektor on GitHub">Star</a>
|
||||||
|
<li><a href="https://gitter.im/lektor/lektor"><img
|
||||||
|
src="https://badges.gitter.im/lektor/lektor.svg"
|
||||||
|
alt="Join the chat at https://gitter.im/lektor/lektor"></a>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,7 +75,7 @@ text:
|
||||||
system is written in Python and provides a documented API to extend it and
|
system is written in Python and provides a documented API to extend it and
|
||||||
integrate into other apps.
|
integrate into other apps.
|
||||||
* <i class="feature-circle fa fa-language"></i> **Multilingual** We can
|
* <i class="feature-circle fa fa-language"></i> **Multilingual** We can
|
||||||
speak multiple languages and allows you to easily create localized websites.
|
speak multiple languages and allow you to easily create localized websites.
|
||||||
----
|
----
|
||||||
class: two-column-list
|
class: two-column-list
|
||||||
#### slideshow ####
|
#### slideshow ####
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
title: is_discoverable
|
||||||
|
---
|
||||||
|
summary: Indicates that a record can be discovered via .children
|
||||||
|
---
|
||||||
|
type: property
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
Records can be discoverable or non discoverable. This is controlled by the
|
||||||
|
`_discoverable` system field which defaults to `yes. This property can quickly
|
||||||
|
check if a record is considered non-discoverable by Lektor or not. In
|
||||||
|
particular a hidden record is also considered undiscoverable.
|
||||||
|
|
||||||
|
Undiscoverable records can be queried and final pages will be built but they
|
||||||
|
are excempt from queries of the record. This is useful for pages that should
|
||||||
|
be built but not show up yet on overview pages. For instance this can be used
|
||||||
|
to implement drafts of blog posts or similar things.
|
||||||
|
|
||||||
|
This property is implemented on the level of source objects to make it
|
||||||
|
possible to use this API in all cases. The default implementation of
|
||||||
|
source objects will always return `true` for discoverability checks.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
{% set downloads = site.get('/downloads') %}
|
||||||
|
{% if downloads.is_discoverable %}
|
||||||
|
<p><a href="{{ downloads|url }}">Go to downloads</a>
|
||||||
|
{% endif %}
|
||||||
|
```
|
|
@ -0,0 +1,13 @@
|
||||||
|
title: is_undiscoverable
|
||||||
|
---
|
||||||
|
summary: The inverse of is_discoverable.
|
||||||
|
---
|
||||||
|
type: property
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This works like [is_discoverable :ref](../is-discoverable/) but the other
|
||||||
|
way around. It just exists for consistency and to make checks look a little
|
||||||
|
bit nicer in some places.
|
|
@ -10,8 +10,9 @@ body:
|
||||||
|
|
||||||
This controls how the query should behave with regards to hidden records.
|
This controls how the query should behave with regards to hidden records.
|
||||||
A query created from the [children :ref](../../record/children/) attribute of
|
A query created from the [children :ref](../../record/children/) attribute of
|
||||||
a record will not include hidden records by default. The opposite is true
|
a record will not include hidden records (or undiscoverable) by default. The
|
||||||
for queries created from the [query :ref](../../pad/query/) method of the pad.
|
opposite is true for queries created from the [query :ref](../../pad/query/)
|
||||||
|
method of the pad.
|
||||||
|
|
||||||
The parameter can be set to `True` to include hidden or `False` to exclude
|
The parameter can be set to `True` to include hidden or `False` to exclude
|
||||||
hidden records.
|
hidden records.
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
title: include_undiscoverable
|
||||||
|
---
|
||||||
|
signature: value
|
||||||
|
---
|
||||||
|
summary: Controls what happens to records that are not discoverable.
|
||||||
|
---
|
||||||
|
type: method
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This controls how the query should behave with regards to undiscoverable
|
||||||
|
records. A query (either created from the [children :ref](../../record/children/)
|
||||||
|
attribute or the [query :ref](../../pad/query/) method of the pad) will not
|
||||||
|
include undiscoverable records by default.
|
||||||
|
|
||||||
|
If undiscoverable records should included this method needs to be used.
|
||||||
|
Set it to `True` to include hidden or `False` to exclude them (default).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Here a basic example of how to filter something in a template:
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<ul>
|
||||||
|
{% for item in this.children.include_undiscoverable(true) %}
|
||||||
|
<li>{{ item.title }}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
```
|
|
@ -0,0 +1,22 @@
|
||||||
|
title: []
|
||||||
|
---
|
||||||
|
summary: Looks up a field from the type.
|
||||||
|
---
|
||||||
|
type: operator
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
The “get-item” operator is used to look up a field from a record. Within
|
||||||
|
templates attribute access automatically falls back to this operator which
|
||||||
|
is why you can typically access `foo.bar` instead of `foo['bar']` unless a
|
||||||
|
conflict with a record property exists.
|
||||||
|
|
||||||
|
All available fields can be accessed this way (model defined fields as well
|
||||||
|
as system fields which are prefixed by an underscore).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```python
|
||||||
|
for child in this.children:
|
||||||
|
print 'ID: %s' % child['_id']
|
||||||
|
```
|
|
@ -15,17 +15,23 @@ overview page.
|
||||||
|
|
||||||
The following attributes exist on the pagination object:
|
The following attributes exist on the pagination object:
|
||||||
|
|
||||||
| Attribute | Description
|
| Attribute | Description
|
||||||
| ----------- | ------------
|
| ------------ | ------------
|
||||||
| `current` | The current record
|
| `current` | The current record
|
||||||
| `prev` | The record for the last page (might be `None`)
|
| `prev` | The record for the last page (might be `None`)
|
||||||
| `next` | The record for the net page (might be `None`)
|
| `next` | The record for the net page (might be `None`)
|
||||||
| `total` | The total number of items across all pages
|
| `total` | The total number of items across all pages
|
||||||
| `pages` | The total number of pages
|
| `pages` | The total number of pages
|
||||||
| `page` | The number of current page
|
| `page` | The number of current page
|
||||||
| `has_prev` | `True` if a previous page exists
|
| `has_prev` | `True` if a previous page exists
|
||||||
| `has_next` | `True` if a next page exists
|
| `has_next` | `True` if a next page exists
|
||||||
| `items` | The query that resolves to the children of the current page.
|
| `items` | The query that resolves to the children of the current page.
|
||||||
|
| `for_page()` | Returns the record for a different page.
|
||||||
|
|
||||||
|
The `for_page()` function accepts a page number and returns the record for
|
||||||
|
the other page.
|
||||||
|
|
||||||
|
!! *Changed in Lektor 2.0:* The `for_page()` method was added.
|
||||||
|
|
||||||
## Item Query Example
|
## Item Query Example
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
title: _alt
|
||||||
|
---
|
||||||
|
summary: The alt for this record.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This field points to the [Alternative :ref](../../../../content/alts/) of
|
||||||
|
the page. This should be considered as an internal field that is exposed
|
||||||
|
through the [alt :ref](../../obj/alt/) source object property instead.
|
|
@ -0,0 +1,14 @@
|
||||||
|
title: _attachment_type
|
||||||
|
---
|
||||||
|
summary: An indication of the attachment type.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This indicates the type of the attachment. Currently only a small set of
|
||||||
|
attachments is detected. The most useful attachment type is `image` which
|
||||||
|
identifies images. The attachments are detected by the file extension.
|
||||||
|
|
||||||
|
!!!! This feature in many ways does not entirely work as you would expect
|
||||||
|
and should be taken is something that will improve in future versions.
|
|
@ -0,0 +1,13 @@
|
||||||
|
title: System Fields
|
||||||
|
---
|
||||||
|
summary: The complete list of system fields in Lektor
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
All records have a few system fields available in addition to the fields
|
||||||
|
defined by the data model. These fields are always there and control internal
|
||||||
|
behavior in Lektor. They are prefixed by an underscore to separate them
|
||||||
|
from the fields a model defines.
|
||||||
|
|
||||||
|
Many system fields are hidden from the admin panel but some can be changed
|
||||||
|
there (`_template`, `_hidden`, and a few others).
|
|
@ -0,0 +1,20 @@
|
||||||
|
title: _discoverable
|
||||||
|
---
|
||||||
|
summary: Controls if this page is picked up by collection queries by default.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
By default any non hidden page is returned from `.children` on iteration. This
|
||||||
|
field can be set to `no` to hide a page from such default queries. This
|
||||||
|
implicitly hides a page for most template operations but Lektor will still
|
||||||
|
build it. This for instance is very useful for draft blog posts. If a post is
|
||||||
|
set to not being discoverable it will be hidden from the blog index without
|
||||||
|
further custom template code, but someone who knows the URL can still find it.
|
||||||
|
|
||||||
|
This is also particularly useful to hide special pages such as `sitemap.xml`
|
||||||
|
which would otherwise cause problems because generic code might not expect
|
||||||
|
it.
|
|
@ -0,0 +1,20 @@
|
||||||
|
title: _gid
|
||||||
|
---
|
||||||
|
summary: A globally unique ID of the page.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
The `_gid` is the MD5 hashed version of the page's [`_path`](../path/). This
|
||||||
|
is useful in situations where a stable ID is needed that follows a certain
|
||||||
|
format. For instance it can come in useful when a ID is needed for a DOM
|
||||||
|
element.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<body class="page-{{ this._gid }}">
|
||||||
|
...
|
||||||
|
</body>
|
||||||
|
```
|
|
@ -0,0 +1,20 @@
|
||||||
|
title: _hidden
|
||||||
|
---
|
||||||
|
summary: Controls if the page should be built or not.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This field controls if Lektor should process the page into a build artifact.
|
||||||
|
By default each page is built into a build artifact (HTML page) and each
|
||||||
|
attachment is processed. This can be prevented by setting `_hidden` to `yes`.
|
||||||
|
|
||||||
|
This also automatically applies to all children of a page unless they
|
||||||
|
forcefully override this setting.
|
||||||
|
|
||||||
|
This is useful for more advanced setups like [Single Page Applications
|
||||||
|
:ref](../../../../guides/single-page/).
|
||||||
|
|
||||||
|
Hidden pages are automatically also removed from the `.children` property
|
||||||
|
of records but stay available for querying via the pad.
|
|
@ -0,0 +1,32 @@
|
||||||
|
title: _id
|
||||||
|
---
|
||||||
|
summary: The local identifier of a record.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
Each record has an `_id`. This ID is basically a form of the filename.
|
||||||
|
Depending on if you are looking at an attachment or a page the rules are
|
||||||
|
slightly different.
|
||||||
|
|
||||||
|
For pages the ID is the name of the folder. So if you have a page called
|
||||||
|
`docs/overview/contents.lr` then `_id` is `overview`. If you have however
|
||||||
|
an attachment named `docs/overview/screenshot.jpg` the `_id` will be the
|
||||||
|
filename of the attachment: `screenshot.jpg`.
|
||||||
|
|
||||||
|
Note that IDs are not globally unique! There is also the `_path` which is
|
||||||
|
the entire path if the record.
|
||||||
|
|
||||||
|
The `_id` is automatically set and cannot be overridden.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<ul class="nav">
|
||||||
|
{% for item in site.query('/projects') %}
|
||||||
|
<li{% if item._id == this._id %} class="active"{%
|
||||||
|
endif %}>{{ item.name }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
```
|
|
@ -0,0 +1,23 @@
|
||||||
|
title: _model
|
||||||
|
---
|
||||||
|
summary: The model the record uses for its fields.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This field selects the model that should be used for non-system fields. In
|
||||||
|
many situations the model is picked automatically but for equally many
|
||||||
|
situations it needs to be selected manually.
|
||||||
|
|
||||||
|
This field is most useful for filtering when operating on mixed collections.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<ul class="projects">
|
||||||
|
{% for child in this.children.filter(F._model == 'project') %}
|
||||||
|
<li>{{ child.name }}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
```
|
|
@ -0,0 +1,22 @@
|
||||||
|
title: _path
|
||||||
|
---
|
||||||
|
summary: The full path of the record.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
The `_path` is the more complete version of the [`_id`](../id/). It contains
|
||||||
|
the entire path of records that are the parents of a record. So if you have a
|
||||||
|
record named `docs/api/db/contents.lr` the `_id` would be `db` but the `_path`
|
||||||
|
would be `docs/api/db`.
|
||||||
|
|
||||||
|
The path can be used to uniquely identify a page but for that purpose the
|
||||||
|
[`_gid`](../gid/) can also be used which is a hashed hexadecimal version of
|
||||||
|
the page.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<!-- generated from {{ this._path }} -->
|
||||||
|
```
|
|
@ -0,0 +1,13 @@
|
||||||
|
title: _slug
|
||||||
|
---
|
||||||
|
summary: The URL slug of the record.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This field defines the URL slug of the record. If not set it defaults to
|
||||||
|
either the `_id` or an expansion of what the parent defines for all children.
|
||||||
|
|
||||||
|
For more information about this refer to [URLs and Slugs
|
||||||
|
:ref](../../../../content/urls/).
|
|
@ -0,0 +1,20 @@
|
||||||
|
title: _source_alt
|
||||||
|
---
|
||||||
|
summary: The alt from the source of the record.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This field points to the true source [Alternative
|
||||||
|
:ref](../../../../content/alts/) of the page. This primarily exists internally
|
||||||
|
to support the builder. In particular the difference to the `_alt` field is
|
||||||
|
that this one will indicate if an alt falls back to a different alternative.
|
||||||
|
At present pages can only fall back to the `_primary` alternative which will
|
||||||
|
be reflected by this field.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<!-- generated from language {{ this._source_alt }} -->
|
||||||
|
```
|
|
@ -0,0 +1,13 @@
|
||||||
|
title: _template
|
||||||
|
---
|
||||||
|
signature:
|
||||||
|
---
|
||||||
|
summary: Selects the template for the page.
|
||||||
|
---
|
||||||
|
type: sysfield
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This field sets the template that Lektor uses for rendering. It defaults to
|
||||||
|
model name + `.html`. If the `_model` is `page` the name of the template
|
||||||
|
will be `page.html`. In some situations it makes sense to override this.
|
|
@ -0,0 +1,26 @@
|
||||||
|
title: add_publisher
|
||||||
|
---
|
||||||
|
type: method
|
||||||
|
---
|
||||||
|
signature: scheme, publisher
|
||||||
|
---
|
||||||
|
summary: Registers a publisher class with the environment.
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This method can be used to register a new publisher for a given URL scheme
|
||||||
|
with Lektor. This allows plugins to provide custom deployment methods. For
|
||||||
|
more information on implementing these see [Publisher :ref](../../publisher/).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```python
|
||||||
|
from lektor.publisher import Publisher
|
||||||
|
|
||||||
|
class MyPublisher(Publisher):
|
||||||
|
pass
|
||||||
|
|
||||||
|
env.add_publisher('my', MyPublisher)
|
||||||
|
```
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
|
@ -0,0 +1,23 @@
|
||||||
|
title: Publisher
|
||||||
|
---
|
||||||
|
module: lektor.publisher
|
||||||
|
---
|
||||||
|
summary: The interface for extending the deployment process
|
||||||
|
---
|
||||||
|
type: class
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This class can be subclassed to implement custom deployment methods.
|
||||||
|
Internally these are called “publishers” and to register them with the
|
||||||
|
environment the [add_publisher :ref](../environment/add-publisher/) method can
|
||||||
|
be used.
|
||||||
|
|
||||||
|
Publishers have one method called [publish :ref](publish/) which is used to
|
||||||
|
trigger the actual deployment process. It also has a reference back to the
|
||||||
|
environment it belongs to as well as the output path of the build process.
|
||||||
|
|
||||||
|
For a minimal example of a publisher refer to the documentation of the
|
||||||
|
[publish :ref](publish/) method.
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
|
@ -0,0 +1,12 @@
|
||||||
|
title: env
|
||||||
|
---
|
||||||
|
summary: Reference to the creating environment
|
||||||
|
---
|
||||||
|
type: property
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
As each publisher is bound to an [Environment :ref](../../environment/) that
|
||||||
|
created it. This is useful to discover related information.
|
|
@ -0,0 +1,31 @@
|
||||||
|
title: fail
|
||||||
|
---
|
||||||
|
summary: Notifies a failure during publishing
|
||||||
|
---
|
||||||
|
signature: message
|
||||||
|
---
|
||||||
|
type: method
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This method takes a message and raises an appropriate failure that aborts
|
||||||
|
the publishing process. This is invoked from within the [publish
|
||||||
|
:ref](../publish/) method to indicate a failure:
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```python
|
||||||
|
from lektor.publisher import Publisher
|
||||||
|
|
||||||
|
|
||||||
|
class MyPublisher(Publisher):
|
||||||
|
def publish(self, target_url, credentials=None, **extra):
|
||||||
|
self.fail('This publisher cannot publish :(')
|
||||||
|
|
||||||
|
|
||||||
|
class MyPlugin(Plugin):
|
||||||
|
def on_setup_env(self, **extra):
|
||||||
|
self.env.add_publisher('my', MyPublisher)
|
||||||
|
```
|
|
@ -0,0 +1,15 @@
|
||||||
|
title: output_path
|
||||||
|
---
|
||||||
|
type: property
|
||||||
|
---
|
||||||
|
summary: The path to the folder with the build artifacts
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This attribute holds the path to the folder where the build process put the
|
||||||
|
final artifacts. Usually a publisher walks that folder and does something
|
||||||
|
with all contents of it. The publishers however are heavily encourated to
|
||||||
|
ignore the special `.lektor` folder which contains lektor specific information
|
||||||
|
that should not end up on the resulting server.
|
|
@ -0,0 +1,82 @@
|
||||||
|
title: publish
|
||||||
|
---
|
||||||
|
signature: target_url, credentials=None, **extra
|
||||||
|
---
|
||||||
|
summary: The method that triggers the deployment
|
||||||
|
---
|
||||||
|
type: method
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This method implements the actual publishing process. It's supposed to
|
||||||
|
implement a generator that reports the progress of the publishing. If at any
|
||||||
|
point something happens that would cause an error for the deployment this can
|
||||||
|
be signalled with the [fail :ref](../fail/) method which aborts the execution
|
||||||
|
and reports an error.
|
||||||
|
|
||||||
|
The parameters to the function are as follows:
|
||||||
|
|
||||||
|
* `target_url`: a URL object with the parsed URL. This object comes from the
|
||||||
|
Werkzeug library and gives access to the individual parts of a URL by the
|
||||||
|
exposed attributes ([Read about the URL object :ext](http://werkzeug.pocoo.org/docs/0.11/urls/)).
|
||||||
|
* `credentials`: an optional dictionary with command line supplied credentials.
|
||||||
|
Note that these credentials might be completely absent and the keys which are
|
||||||
|
provided might change with future versions of Lektor.
|
||||||
|
* `**extra`: for forwards compatibility publishers are required to ignore extra
|
||||||
|
keyword arguments.
|
||||||
|
|
||||||
|
Each line in the generator must be a string which is then either logged to
|
||||||
|
the output in the console or in the deploy/publish window in the admin UI.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
This example implements a simple publisher that just copies all built files
|
||||||
|
into a new location.
|
||||||
|
|
||||||
|
```python
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from lektor.publisher import Publisher
|
||||||
|
|
||||||
|
|
||||||
|
class CopyPublisher(Publisher):
|
||||||
|
|
||||||
|
def publish(self, target_url, credentials=None, **extra):
|
||||||
|
src_path = self.output_path
|
||||||
|
dst_path = target_url.path
|
||||||
|
strip = len(src_path) + 1
|
||||||
|
|
||||||
|
for path, folders, filenames in os.walk(src_path):
|
||||||
|
# Ignore the .lektor folder.
|
||||||
|
folders[:] = [x for x in folders if x != '.lektor']
|
||||||
|
|
||||||
|
# Copy all files over
|
||||||
|
for filename in filenames:
|
||||||
|
full_path = os.path.join(src_path, path, filename)
|
||||||
|
dst = os.path.join(path, full_path[strip:])
|
||||||
|
|
||||||
|
# Make sure the destination folder exists.
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(dst))
|
||||||
|
except (OSError, IOError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Copy the file
|
||||||
|
yield 'Copy %s' % filename
|
||||||
|
shutil.copy(full_path, dst)
|
||||||
|
|
||||||
|
yield 'Done'
|
||||||
|
|
||||||
|
|
||||||
|
class MyPlugin(Plugin):
|
||||||
|
def on_setup_env(self, **extra):
|
||||||
|
self.env.add_publisher('copy', CopyPublisher)
|
||||||
|
```
|
||||||
|
|
||||||
|
This publisher registers with the `copy` scheme and could be used like this:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
target_url = copy:///path/to/destination/folder
|
||||||
|
```
|
|
@ -0,0 +1,22 @@
|
||||||
|
title: markdown
|
||||||
|
---
|
||||||
|
signature: source
|
||||||
|
---
|
||||||
|
summary: Converts markdown to HTML
|
||||||
|
---
|
||||||
|
type: filter
|
||||||
|
---
|
||||||
|
version_added: 2.0
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
|
||||||
|
This filter converts a markdown string into HTML. This behaves the same as
|
||||||
|
the [Markdown Type :ref](../../../db/types/markdown/).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```html+jinja
|
||||||
|
<div class="example">
|
||||||
|
{{ "Hello **World**"|markdown }}
|
||||||
|
</div>
|
||||||
|
```
|
|
@ -49,7 +49,7 @@ Each page is associated with a model and a template. Each page needs to have
|
||||||
a model that defines which fields exist. The template by default matches the
|
a model that defines which fields exist. The template by default matches the
|
||||||
model name but it can be overridden on a per-page basis.
|
model name but it can be overridden on a per-page basis.
|
||||||
|
|
||||||
So how is the model selected? Either expicitly in the `contents.lr` file
|
So how is the model selected? Either explicitly in the `contents.lr` file
|
||||||
with the `_model` key or by configuration and convention. Lektor will
|
with the `_model` key or by configuration and convention. Lektor will
|
||||||
select the default model based on trying things in this order:
|
select the default model based on trying things in this order:
|
||||||
|
|
||||||
|
@ -80,11 +80,15 @@ The page body goes here
|
||||||
|
|
||||||
Fields are separated by three dashes `---` and follow the format `key: value`.
|
Fields are separated by three dashes `---` and follow the format `key: value`.
|
||||||
For values with multiple lines it's recommended to insert two newlines after
|
For values with multiple lines it's recommended to insert two newlines after
|
||||||
the key. To format of each field is specific to how the model is configured.
|
the key. The format of each field is specific to how the model is configured.
|
||||||
|
|
||||||
Some fields are plain text, others can be markdown syntax and more. These
|
Some fields are plain text, others can be markdown syntax and more. These
|
||||||
fields become available for rendering in the template automatically.
|
fields become available for rendering in the template automatically.
|
||||||
|
|
||||||
**Tip:** If you want to use `---` itself in the document text, just add another
|
!!! If you want to use `---` itself in the document text, just add another
|
||||||
dash. This means `----` will render as `---` and `-----` will render as
|
dash. This means `----` will render as `---` and `-----` will render as
|
||||||
`----` etc.
|
`----` etc.
|
||||||
|
|
||||||
|
Fields prefixed with an underscore are so-called system fields. They are
|
||||||
|
provided by Lektor and customize behavior within Lektor. For a list of
|
||||||
|
available fields see [System Fields :ref](../api/db/system-fields/).
|
||||||
|
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 22 KiB |
|
@ -101,6 +101,10 @@ The following targets are supported for the `target` folder:
|
||||||
* [FTP](ftp/)
|
* [FTP](ftp/)
|
||||||
* [GitHub Pages](ghpages/)
|
* [GitHub Pages](ghpages/)
|
||||||
|
|
||||||
|
In addition, third-party plugins are available for these targets:
|
||||||
|
|
||||||
|
* [S3 :ext](https://github.com/spenczar/lektor-s3)
|
||||||
|
|
||||||
## Manual Deployments
|
## Manual Deployments
|
||||||
|
|
||||||
If you want to manually deploy something through the favorite tool of yours
|
If you want to manually deploy something through the favorite tool of yours
|
||||||
|
|
|
@ -8,7 +8,7 @@ body:
|
||||||
* `ghpages+https://username/repository`
|
* `ghpages+https://username/repository`
|
||||||
|
|
||||||
A popular way to host websites for Open Source projects is the GitHub pages.
|
A popular way to host websites for Open Source projects is the GitHub pages.
|
||||||
It's a free services provided by [GitHub :ext](http://github.com/) which allows
|
It's a free service provided by [GitHub :ext](http://github.com/) which allows
|
||||||
to host completely static websites through GitHub.
|
to host completely static websites through GitHub.
|
||||||
|
|
||||||
The way this is implemented in Lektor currently is that Lektor will force-push
|
The way this is implemented in Lektor currently is that Lektor will force-push
|
||||||
|
|
|
@ -123,7 +123,7 @@ For the detail page we show all information we know about:
|
||||||
{% block title %}{{ this.name }} ({{ this.date.year }}){% endblock %}
|
{% block title %}{{ this.name }} ({{ this.date.year }}){% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h1>{{ this.name }}</h1>
|
<h1>{{ this.name }}</h1>
|
||||||
<dt>
|
<dl>
|
||||||
<dt>Date
|
<dt>Date
|
||||||
<dd>{{ this.date|dateformat }}
|
<dd>{{ this.date|dateformat }}
|
||||||
{% if this.website %}
|
{% if this.website %}
|
||||||
|
|
|
@ -23,6 +23,10 @@ _model: none
|
||||||
This instructs Lektor to use the template `sitemap.xml` for this page. We
|
This instructs Lektor to use the template `sitemap.xml` for this page. We
|
||||||
also give it the empty `none` model for good measure.
|
also give it the empty `none` model for good measure.
|
||||||
|
|
||||||
|
!!! Starting with Lektor 2.0 you can also add `_discoverable: no` as field
|
||||||
|
into the file to hide it from `.children`. This is useful for such special
|
||||||
|
pages which should be excluded from navigation or automatic link generation.
|
||||||
|
|
||||||
## Template File
|
## Template File
|
||||||
|
|
||||||
The template loaded will be `templates/sitemap.xml`. In this file we just
|
The template loaded will be `templates/sitemap.xml`. In this file we just
|
||||||
|
|
|
@ -6,10 +6,10 @@ sort_key: 50
|
||||||
---
|
---
|
||||||
body:
|
body:
|
||||||
|
|
||||||
Lektor comes in two flavors: the command line executable as well as as a
|
Lektor comes in two flavors: as a command line executable and as a
|
||||||
desktop application. The desktop version also contains the command line
|
desktop application. The desktop version also contains the command
|
||||||
executable however it bundles together all dependencies of Lektor in an
|
line executable, but it also bundles together all dependencies of Lektor
|
||||||
easy to use package which heavily simplifies installation.
|
in an easy to use package which heavily simplifies installation.
|
||||||
|
|
||||||
## Desktop Application
|
## Desktop Application
|
||||||
|
|
||||||
|
@ -20,23 +20,23 @@ disk image that you can mount which contains one application by the name of
|
||||||
go.
|
go.
|
||||||
|
|
||||||
If you also want access to the command line tools just launch `Lektor.app`
|
If you also want access to the command line tools just launch `Lektor.app`
|
||||||
and then click on *Lektor ➤ Install Shell Command*.
|
and then click in the menu bar on *Lektor ➤ Install Shell Command*.
|
||||||
|
|
||||||
## Command Line Application
|
## Command Line Application
|
||||||
|
|
||||||
If you do not want to install the desktop app you can just install the command
|
If you do not want to install the desktop app then you can just install the command
|
||||||
line executable. This one runs on more operating systems (OSX, Linux and
|
line executable. This runs on more operating systems (OSX, Linux and Windows) but
|
||||||
Windows) but the installation is a bit more involved.
|
the installation is a bit more involved.
|
||||||
|
|
||||||
You need to make sure you have the following software installed on your computer:
|
You need to make sure you have the following software installed on your computer:
|
||||||
|
|
||||||
* Python 2.7 (**not** Python 3.x)
|
* Python 2.7 (**not** Python 3.x, also `python-dev` is required on Ubuntu)
|
||||||
* ImageMagick (`brew install imagemagick` or `apt-get install imagemagick`
|
* ImageMagick (`brew install imagemagick` or `apt-get install imagemagick`
|
||||||
can get you this on OS X and Ubuntu respectively, on Windows do `choco
|
can get you this on OS X and Ubuntu respectively, on Windows do `choco
|
||||||
install imagemagick`, which requires [chocolatey :ext](https://chocolatey.org/),
|
install imagemagick`, which requires [chocolatey :ext](https://chocolatey.org/),
|
||||||
or [download from here :ext](http://www.imagemagick.org)).
|
or [download from here :ext](http://www.imagemagick.org)).
|
||||||
|
|
||||||
Once you have that installed and made sure that they are on your `PATH` you can
|
Once you have those installed and have made sure that they are on your `PATH`, you can
|
||||||
get Lektor installed with our installation script:
|
get Lektor installed with our installation script:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -53,8 +53,11 @@ but you can also do it directly in `Powershell`:
|
||||||
PS C:\> iex ((new-object net.webclient).DownloadString('https://getlektor.com/install.ps1'))
|
PS C:\> iex ((new-object net.webclient).DownloadString('https://getlektor.com/install.ps1'))
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively you can manually install it with `virtualenv` if you know
|
## pip
|
||||||
how that works:
|
|
||||||
|
Alternatively you can manually install the command line version with
|
||||||
|
`virtualenv` if you know how that works. Note that this method is *heavily
|
||||||
|
discouraged* for anything other than advanced use cases such as build servers.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ virtualenv venv
|
$ virtualenv venv
|
||||||
|
@ -62,6 +65,12 @@ $ . venv/bin/activate
|
||||||
$ pip install Lektor
|
$ pip install Lektor
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!!! When we say this installation type is discouraged we mean it. The reason
|
||||||
|
is that it encourages uses of Lektor which are entirely unsupported by us.
|
||||||
|
Lektor actively manages virtualenvs for plugin installations in very specific
|
||||||
|
ways and this might or might not work in your setup. We support pip
|
||||||
|
installations for deployment environments and local development only.
|
||||||
|
|
||||||
## Development Version
|
## Development Version
|
||||||
|
|
||||||
If you want to install the development version of Lektor you can do so. It's
|
If you want to install the development version of Lektor you can do so. It's
|
||||||
|
|
|
@ -108,10 +108,10 @@ class HelloWorldPlugin(Plugin):
|
||||||
|
|
||||||
If you now start your lektor server with `lektor server` you should
|
If you now start your lektor server with `lektor server` you should
|
||||||
see some output that indicates that the plugin was loaded. You can also
|
see some output that indicates that the plugin was loaded. You can also
|
||||||
get a list with `lektor plugins`:
|
get a list with `lektor plugins list`:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ lektor plugins
|
$ lektor plugins list
|
||||||
hello-world: Hello World
|
hello-world: Hello World
|
||||||
This is a demo plugin for testing purposes.
|
This is a demo plugin for testing purposes.
|
||||||
path: /Users/john/demo/packages/hello-world
|
path: /Users/john/demo/packages/hello-world
|
||||||
|
|
|
@ -17,10 +17,16 @@ project:
|
||||||
this plugin embeds disqus comments into your website.
|
this plugin embeds disqus comments into your website.
|
||||||
* [webpack-support :ext](https://github.com/lektor/lektor-webpack-support):
|
* [webpack-support :ext](https://github.com/lektor/lektor-webpack-support):
|
||||||
adds support for building websites with webpack.
|
adds support for building websites with webpack.
|
||||||
|
* [markdown-highlighter :ext](https://github.com/lektor/lektor-markdown-highlighter):
|
||||||
|
adds support for syntax highlighting to markdown code snippets.
|
||||||
|
* [markdown-header-anchors :ext](https://github.com/lektor/lektor-markdown-header-anchors):
|
||||||
|
adds support for header anchors and table of contents to markdown.
|
||||||
|
|
||||||
## Inofficial
|
## Unofficial
|
||||||
|
|
||||||
There are currently no inofficial plugins listed here, but if you have some
|
These are unofficial plugins. This list is moderated and updated
|
||||||
you can [edit this page on github
|
regularly, but they still aren't developed by the authors of Lektor,
|
||||||
:ext](https://github.com/lektor/lektor-website/edit/master/content/docs/plugins/list/contents.lr)
|
so they might not keep pace with development on Lektor.
|
||||||
and send a pull request.
|
|
||||||
|
* [s3 :ext](https://github.com/spenczar/lektor-s3):
|
||||||
|
allows deployment of websites to S3 buckets
|
||||||
|
|
|
@ -87,7 +87,7 @@ but are contained within a field of a model.
|
||||||
### `packages/`
|
### `packages/`
|
||||||
|
|
||||||
For local plugin development the `packages/` folder can be used. Any plugin
|
For local plugin development the `packages/` folder can be used. Any plugin
|
||||||
stored in there is automatically actviated in the system.
|
stored in there is automatically activated in the system.
|
||||||
|
|
||||||
### `configs/`
|
### `configs/`
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 118 KiB |
|
@ -50,7 +50,7 @@ $ lektor server
|
||||||
```
|
```
|
||||||
|
|
||||||
This will automatically start the server and you can navigate to
|
This will automatically start the server and you can navigate to
|
||||||
[localhost:5000](http://localhost:5000/) go open the project.
|
[localhost:5000](http://localhost:5000/) open the project.
|
||||||
|
|
||||||
You can keep the server running, it will automatically rebuild your files as
|
You can keep the server running, it will automatically rebuild your files as
|
||||||
they change.
|
they change.
|
||||||
|
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 157 KiB |
|
@ -6,8 +6,8 @@ sort_key: 20
|
||||||
---
|
---
|
||||||
body:
|
body:
|
||||||
|
|
||||||
When it comes to creating websites, there is a ludicrous amount of tools available.
|
When it comes to creating websites, there is a ludicrous number of tools available.
|
||||||
They range from full blown content management solutions like Drupal over
|
They range from full-blown content management solutions like Drupal to
|
||||||
desktop solutions like Google Web Designer to Cloud Hosted Website solutions
|
desktop solutions like Google Web Designer to Cloud Hosted Website solutions
|
||||||
like WIX to more programmer focused approaches like Jekyll which generate
|
like WIX to more programmer focused approaches like Jekyll which generate
|
||||||
websites out of templates and markdown files.
|
websites out of templates and markdown files.
|
||||||
|
@ -17,31 +17,31 @@ websites out of templates and markdown files.
|
||||||
## Lektor is Static
|
## Lektor is Static
|
||||||
|
|
||||||
Lektor learned from the huge range of static file generators like Jekyll,
|
Lektor learned from the huge range of static file generators like Jekyll,
|
||||||
Pelican, Hugo, Middleman and many more about the values of generating a
|
Pelican, Hugo, Middleman and many more about the value of generating a
|
||||||
completely static website. This means that unlike WordPress or similar
|
completely static website. This means that unlike WordPress or similar
|
||||||
solutions it does not run on a server, but your local computer (or a build
|
solutions it does not run on a server, but your local computer (or a build
|
||||||
server) and generates out static HTML that can be uploaded to any web server
|
server), and generates static HTML that can be uploaded to any web server or
|
||||||
or content distribution platform like S3 with CloudFront.
|
content distribution platform like S3 with CloudFront.
|
||||||
|
|
||||||
Why go static? Because the vast, vast majority of websites will be read many
|
Why go static? Because the vast, vast majority of websites will be read many
|
||||||
more times than they will update. This is crucial because dynamic does not
|
more times than they will be updated. This is crucial because dynamic content
|
||||||
come for free. It needs server resources and because program code is running
|
does not come for free. It needs server resources and because program code is
|
||||||
there it needs to be kept up to date for to ensure there are no security
|
running there it needs to be kept up to date for to ensure there are no security
|
||||||
problems that are left unpatched. Also when a website gets a sudden spike
|
problems that are left unpatched. Also when a website gets a sudden spike of
|
||||||
of traffic a static website will stay up for longer on the same server than
|
traffic a static website will stay up for longer on the same server than a
|
||||||
a dynamic one that needs to execute code.
|
dynamic one that needs to execute code.
|
||||||
|
|
||||||
Sure, there are some things you cannot do on a static website, but those
|
Sure, there are some things you cannot do on a static website, but those are not
|
||||||
things you would not use Lektor for. For small dynamic sections, JavaScript
|
things you would not use Lektor for. For small dynamic sections, JavaScript
|
||||||
and pairing up with other services is a good solution.
|
paired up with other services is a good solution.
|
||||||
|
|
||||||
<img src="static.png" alt="" class="screenshot">
|
<img src="static.png" alt="" class="screenshot">
|
||||||
|
|
||||||
## Lektor is a CMS
|
## Lektor is a CMS
|
||||||
|
|
||||||
However Lektor also takes from content management systems like WordPress
|
However, Lektor also takes from content management systems like WordPress
|
||||||
and provides a flexible browser based admin interface from which you can
|
and provides a flexible browser-based admin interface from which you can
|
||||||
edit your website's contents. Unlike traditional CMS solutions however it
|
edit your website's contents. Unlike traditional CMS solutions, however, it
|
||||||
runs entirely on your own computer.
|
runs entirely on your own computer.
|
||||||
|
|
||||||
This means you can give a Lektor website to people that have no understanding
|
This means you can give a Lektor website to people that have no understanding
|
||||||
|
@ -51,7 +51,7 @@ of programming and they can still modify the content and update the website.
|
||||||
|
|
||||||
## Lektor is a Framework
|
## Lektor is a Framework
|
||||||
|
|
||||||
Lastly however Lektor learns from experience in writing web frameworks. Lektor
|
Lastly, Lektor learns from experience in writing web frameworks. Lektor
|
||||||
is much more than a website generator because it is based on a very flexible
|
is much more than a website generator because it is based on a very flexible
|
||||||
internal flat file database which can be used to model any website content.
|
internal flat file database which can be used to model any website content.
|
||||||
Unlike static blog generators which are based on some markdown content and
|
Unlike static blog generators which are based on some markdown content and
|
||||||
|
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 460 KiB After Width: | Height: | Size: 433 KiB |
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 331 KiB After Width: | Height: | Size: 219 KiB |
Before Width: | Height: | Size: 299 KiB After Width: | Height: | Size: 261 KiB |
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 240 KiB |
BIN
content/logo.png
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 175 KiB |
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 170 KiB |
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 152 KiB |
|
@ -6,23 +6,16 @@ button_label = [[flag]]
|
||||||
label = Image
|
label = Image
|
||||||
type = select
|
type = select
|
||||||
source = record.attachments.images
|
source = record.attachments.images
|
||||||
width = 2/4
|
width = 3/4
|
||||||
|
|
||||||
[fields.height]
|
[fields.height]
|
||||||
label = Height
|
label = Height
|
||||||
type = select
|
type = select
|
||||||
choices = half, full, 500, 300
|
choices = 500, 300
|
||||||
choice_labels = Half, Full, 500px, 300px
|
choice_labels = 500px, 300px
|
||||||
default = 300
|
default = 300
|
||||||
width = 1/4
|
width = 1/4
|
||||||
|
|
||||||
[fields.class]
|
|
||||||
label = Class
|
|
||||||
type = select
|
|
||||||
choices = dark
|
|
||||||
choice_labels = Dark
|
|
||||||
width = 1/4
|
|
||||||
|
|
||||||
[fields.contents]
|
[fields.contents]
|
||||||
label = Contents
|
label = Contents
|
||||||
type = html
|
type = html
|
||||||
|
|
|
@ -28,16 +28,12 @@ default = yes
|
||||||
checkbox_label = Show comment box
|
checkbox_label = Show comment box
|
||||||
width = 1/4
|
width = 1/4
|
||||||
|
|
||||||
[fields.body]
|
|
||||||
label = Body
|
|
||||||
type = markdown
|
|
||||||
|
|
||||||
[fields.type]
|
[fields.type]
|
||||||
label = Technical Type
|
label = Technical Type
|
||||||
type = select
|
type = select
|
||||||
description = Of what general type this doc page is. If not set, it's a normal doc page.
|
description = Of what general type this doc page is. If not set, it's a normal doc page.
|
||||||
choices = class, function, method, property, operator, filter, cmdlet, event, type
|
choices = class, function, method, property, operator, filter, cmdlet, event, type, sysfield
|
||||||
choice_labels = Class, Function, Method, Property, Operator, Filter, Commandlet, Event, Field Type
|
choice_labels = Class, Function, Method, Property, Operator, Filter, Commandlet, Event, Field Type, System Field
|
||||||
width = 1/2
|
width = 1/2
|
||||||
|
|
||||||
[fields.module]
|
[fields.module]
|
||||||
|
@ -57,3 +53,11 @@ description = An optional signature for a type.
|
||||||
label = Template Variable
|
label = Template Variable
|
||||||
type = string
|
type = string
|
||||||
description = An optional template variable if it exists there as such.
|
description = An optional template variable if it exists there as such.
|
||||||
|
|
||||||
|
[fields.version_added]
|
||||||
|
label = Added in version
|
||||||
|
type = string
|
||||||
|
|
||||||
|
[fields.body]
|
||||||
|
label = Body
|
||||||
|
type = markdown
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.egg-info
|
|
@ -0,0 +1,34 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
from lektor.pluginsystem import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
_prefix_re = re.compile(r'^\s*(!{1,4})\s+')
|
||||||
|
|
||||||
|
CLASSES = {
|
||||||
|
1: 'note',
|
||||||
|
2: 'info',
|
||||||
|
3: 'tip',
|
||||||
|
4: 'warning',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AdmonitionMixin(object):
|
||||||
|
|
||||||
|
def paragraph(self, text):
|
||||||
|
match = _prefix_re.match(text)
|
||||||
|
if match is None:
|
||||||
|
return super(AdmonitionMixin, self).paragraph(text)
|
||||||
|
level = len(match.group(1))
|
||||||
|
return '<div class="admonition admonition-%s"><p>%s</p></div>' % (
|
||||||
|
CLASSES[level],
|
||||||
|
text[match.end():]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownAdmonitionPlugin(Plugin):
|
||||||
|
name = u'Markdown Admonition'
|
||||||
|
description = u'Adds admonitions to markdown.'
|
||||||
|
|
||||||
|
def on_markdown_config(self, config, **extra):
|
||||||
|
config.renderer_mixins.append(AdmonitionMixin)
|
|
@ -0,0 +1,15 @@
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='lektor-markdown-admonition',
|
||||||
|
version='0.1',
|
||||||
|
author=u'Armin Ronacher',
|
||||||
|
author_email='armin.ronacher@active-4.com',
|
||||||
|
license='MIT',
|
||||||
|
py_modules=['lektor_markdown_admonition'],
|
||||||
|
entry_points={
|
||||||
|
'lektor.plugins': [
|
||||||
|
'markdown-admonition = lektor_markdown_admonition:MarkdownAdmonitionPlugin',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
|
@ -1,42 +0,0 @@
|
||||||
from lektor.pluginsystem import Plugin
|
|
||||||
from lektor.utils import slugify
|
|
||||||
from markupsafe import Markup
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
TocEntry = namedtuple('TocEntry', ['anchor', 'title', 'children'])
|
|
||||||
|
|
||||||
|
|
||||||
class MarkdownHeaderAnchorsPlugin(Plugin):
|
|
||||||
name = 'Markdown Header Anchors'
|
|
||||||
description = 'Adds anchors to markdown headers.'
|
|
||||||
|
|
||||||
def on_markdown_config(self, config, **extra):
|
|
||||||
class HeaderAnchorMixin(object):
|
|
||||||
def header(renderer, text, level, raw):
|
|
||||||
anchor = slugify(raw)
|
|
||||||
renderer.meta['toc'].append((level, anchor, Markup(text)))
|
|
||||||
return '<h%d id="%s">%s</h%d>' % (level, anchor, text, level)
|
|
||||||
config.renderer_mixins.append(HeaderAnchorMixin)
|
|
||||||
|
|
||||||
def on_markdown_meta_init(self, meta, **extra):
|
|
||||||
meta['toc'] = []
|
|
||||||
|
|
||||||
def on_markdown_meta_postprocess(self, meta, **extra):
|
|
||||||
prev_level = None
|
|
||||||
toc = []
|
|
||||||
stack = [toc]
|
|
||||||
|
|
||||||
for level, anchor, title in meta['toc']:
|
|
||||||
if prev_level is None:
|
|
||||||
prev_level = level
|
|
||||||
elif prev_level == level - 1:
|
|
||||||
stack.append(stack[-1][-1][2])
|
|
||||||
prev_level = level
|
|
||||||
elif prev_level > level:
|
|
||||||
while prev_level > level:
|
|
||||||
stack.pop()
|
|
||||||
prev_level -= 1
|
|
||||||
stack[-1].append(TocEntry(anchor, title, []))
|
|
||||||
|
|
||||||
meta['toc'] = toc
|
|
|
@ -1,12 +0,0 @@
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name='lektor-markdown-header-anchors',
|
|
||||||
version='0.1',
|
|
||||||
py_modules=['lektor_markdown_header-anchors'],
|
|
||||||
entry_points={
|
|
||||||
'lektor.plugins': [
|
|
||||||
'markdown-header-anchors = lektor_markdown_header_anchors:MarkdownHeaderAnchorsPlugin',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,49 +0,0 @@
|
||||||
from lektor.pluginsystem import Plugin
|
|
||||||
from lektor.context import get_ctx
|
|
||||||
|
|
||||||
from pygments import highlight
|
|
||||||
from pygments.formatters import HtmlFormatter
|
|
||||||
from pygments.lexers import get_lexer_by_name
|
|
||||||
|
|
||||||
from markupsafe import Markup
|
|
||||||
|
|
||||||
|
|
||||||
class MarkdownHighlighterPlugin(Plugin):
|
|
||||||
name = 'Markdown Highlighter'
|
|
||||||
description = 'Adds syntax highlighting for markdown blocks.'
|
|
||||||
|
|
||||||
def get_formatter(self):
|
|
||||||
return HtmlFormatter(style=self.get_style())
|
|
||||||
|
|
||||||
def get_style(self):
|
|
||||||
return self.get_config().get('pygments.style', 'default')
|
|
||||||
|
|
||||||
def highlight_code(self, text, lang):
|
|
||||||
get_ctx().record_dependency(self.config_filename)
|
|
||||||
lexer = get_lexer_by_name(lang)
|
|
||||||
return highlight(text, lexer, self.get_formatter())
|
|
||||||
|
|
||||||
def on_markdown_config(self, config, **extra):
|
|
||||||
class HighlightMixin(object):
|
|
||||||
def block_code(ren, text, lang):
|
|
||||||
if not lang:
|
|
||||||
return super(HighlightMixin, ren).block_code(text, lang)
|
|
||||||
return self.highlight_code(text, lang)
|
|
||||||
config.renderer_mixins.append(HighlightMixin)
|
|
||||||
|
|
||||||
def on_setup_env(self, **extra):
|
|
||||||
def get_pygments_stylesheet(artifact_name='/static/pygments.css'):
|
|
||||||
ctx = get_ctx()
|
|
||||||
@ctx.sub_artifact(artifact_name=artifact_name, sources=[
|
|
||||||
self.config_filename])
|
|
||||||
def build_stylesheet(artifact):
|
|
||||||
with artifact.open('w') as f:
|
|
||||||
f.write(self.get_formatter().get_style_defs())
|
|
||||||
return artifact_name
|
|
||||||
|
|
||||||
def pygmentize(text, lang):
|
|
||||||
return Markup(self.highlight_code(text, lang))
|
|
||||||
|
|
||||||
self.env.jinja_env.globals['get_pygments_stylesheet'] = \
|
|
||||||
get_pygments_stylesheet
|
|
||||||
self.env.jinja_env.filters['pygmentize'] = pygmentize
|
|
|
@ -1,15 +0,0 @@
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name='lektor-markdown-highlighter',
|
|
||||||
version='0.1',
|
|
||||||
py_modules=['lektor_markdown_highlighter'],
|
|
||||||
entry_points={
|
|
||||||
'lektor.plugins': [
|
|
||||||
'markdown-highlighter = lektor_markdown_highlighter:MarkdownHighlighterPlugin',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
install_requires=[
|
|
||||||
'Pygments',
|
|
||||||
]
|
|
||||||
)
|
|
|
@ -1,8 +1,5 @@
|
||||||
{% set image = record.attachments.get(this.image) %}
|
{% set image = record.attachments.get(this.image) %}
|
||||||
<div class="banner{% if this.class %} banner-{{ this.class }}{% endif %}" style="background-image: url({{ image|url
|
<div class="banner banner-{{ this.height }}" style="background-image: url({{ image|url
|
||||||
}}); height: {{ {
|
}})">{% if this.contents %}
|
||||||
'full': image.height,
|
|
||||||
'half': image.height / 2,
|
|
||||||
}.get(this.height, this.height) }}px">{% if this.contents %}
|
|
||||||
{{ this.contents }}
|
{{ this.contents }}
|
||||||
{% endif %}</div>
|
{% endif %}</div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="slideshow-wrapper">
|
<div class="slideshow-wrapper">
|
||||||
<div class="slideshow">
|
<div class="slideshow">
|
||||||
<div class="slideshow-inner">
|
<div class="slideshow-inner">
|
||||||
<div class="carousel slide" data-ride="carousel" id="{{ carousel_id }}">
|
<div class="carousel slide" data-ride="carousel" data-interval="8500" id="{{ carousel_id }}">
|
||||||
{#
|
{#
|
||||||
<ol class="carousel-indicators">
|
<ol class="carousel-indicators">
|
||||||
{% for slide in this.slides.blocks %}
|
{% for slide in this.slides.blocks %}
|
||||||
|
|
|
@ -33,21 +33,35 @@
|
||||||
<div class="col-sm-9 doc-styling">
|
<div class="col-sm-9 doc-styling">
|
||||||
{{ get_doc_header(this) }}
|
{{ get_doc_header(this) }}
|
||||||
|
|
||||||
|
<ul class=page-meta>
|
||||||
{% if this.type == 'method' %}
|
{% if this.type == 'method' %}
|
||||||
<p class="type-info">Method of {{ get_doc_link(this.parent) }}
|
<li>Method of {{ get_doc_link(this.parent) }}
|
||||||
{% elif this.type == 'property' %}
|
{% elif this.type == 'property' %}
|
||||||
<p class="type-info">Property of {{ get_doc_link(this.parent) }}
|
<li>Property of {{ get_doc_link(this.parent) }}
|
||||||
{% elif this.type == 'operator' %}
|
{% elif this.type == 'operator' %}
|
||||||
<p class="type-info">Operator of {{ get_doc_link(this.parent) }}
|
<li>Operator of {{ get_doc_link(this.parent) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if this.template_var %}
|
{% if this.template_var %}
|
||||||
<p class="type-info">Template variable: <a href="{{ (
|
<li>Template variable: <a href="{{ (
|
||||||
'/docs/api/templates/globals/' ~ this.template_var|lower ~ '/')|url
|
'/docs/api/templates/globals/' ~ this.template_var|lower ~ '/')|url
|
||||||
}}"><code>{{ this.template_var }}</code></a>
|
}}"><code>{{ this.template_var }}</code></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if this.version_added %}
|
||||||
|
<li>New in Lektor Version <em>{{ this.version_added }}</em>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
{{ this.body }}
|
{{ this.body }}
|
||||||
|
|
||||||
|
{% if this.version_history %}
|
||||||
|
<div class="version-info version-info-collapsed">
|
||||||
|
<h2>Version Info</h2>
|
||||||
|
<div class="contents">
|
||||||
|
{{ this.version_history }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if this.children %}
|
{% if this.children %}
|
||||||
<div class="child-pages">
|
<div class="child-pages">
|
||||||
{% for cols in this.children|batch(2) %}
|
{% for cols in this.children|batch(2) %}
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
><i class="fa fa-bug"></i></a>
|
><i class="fa fa-bug"></i></a>
|
||||||
<a href="https://twitter.com/getlektor" title="Find Lektor on Twitter"
|
<a href="https://twitter.com/getlektor" title="Find Lektor on Twitter"
|
||||||
><i class="fa fa-twitter"></i></a>
|
><i class="fa fa-twitter"></i></a>
|
||||||
|
<a href="https://gitter.im/lektor/lektor" title="Chat on Gitter"
|
||||||
|
><i class="fa fa-comment"></i></a>
|
||||||
{%- if this.path %}
|
{%- if this.path %}
|
||||||
<a href="https://github.com/lektor/lektor-website/tree/master/content{{ this.path
|
<a href="https://github.com/lektor/lektor-website/tree/master/content{{ this.path
|
||||||
}}/contents.lr" title="View source for this page"><i class="fa fa-code"></i></a>
|
}}/contents.lr" title="View source for this page"><i class="fa fa-code"></i></a>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<i class="glyphicon glyphicon-console"></i>
|
<i class="glyphicon glyphicon-console"></i>
|
||||||
{%- elif page.type == 'event' -%}
|
{%- elif page.type == 'event' -%}
|
||||||
<i class="glyphicon glyphicon-flash"></i>
|
<i class="glyphicon glyphicon-flash"></i>
|
||||||
{%- elif page.type == 'type' -%}
|
{%- elif page.type == 'type' or page.type == 'sysfield' -%}
|
||||||
<i class="glyphicon glyphicon-pencil"></i>
|
<i class="glyphicon glyphicon-pencil"></i>
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
<i class="glyphicon glyphicon-list-alt"></i>
|
<i class="glyphicon glyphicon-list-alt"></i>
|
||||||
|
|
|
@ -15,6 +15,29 @@ function selectText(text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initBadges() {
|
||||||
|
let badges = $('.badges li').hide();
|
||||||
|
|
||||||
|
if (badges.length <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nextBadge = 0;
|
||||||
|
|
||||||
|
function fadeInNext() {
|
||||||
|
let el = badges[nextBadge++];
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.setTimeout(fadeInNext, 200);
|
||||||
|
$(el).fadeIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(function() {
|
||||||
|
fadeInNext();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
function initDownloadButton() {
|
function initDownloadButton() {
|
||||||
let buttons = $('.download-btn');
|
let buttons = $('.download-btn');
|
||||||
if (buttons.length <= 0) {
|
if (buttons.length <= 0) {
|
||||||
|
@ -143,6 +166,7 @@ function hideThingsForWindows() {
|
||||||
}
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
initBadges();
|
||||||
initDownloadButton();
|
initDownloadButton();
|
||||||
initInstallRow();
|
initInstallRow();
|
||||||
initGoogleSearch();
|
initGoogleSearch();
|
||||||
|
|
|
@ -103,7 +103,7 @@ div.slideshow {
|
||||||
height: auto;
|
height: auto;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: lighten($gray, 55) url(../images/dark-curls.png);
|
background: lighten($gray, 55) url(../images/dark-curls.png);
|
||||||
box-shadow: inset 0 0 10px darken($lektor-header-bg, 5);
|
box-shadow: inset 0 0 10px fade-out(darken($lektor-header-bg, 5), 0.8);
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
div.slideshow-inner {
|
div.slideshow-inner {
|
||||||
|
@ -259,14 +259,24 @@ div.banner {
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
|
background-color: $lektor-header-bg;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
box-shadow: 0 4px 10px fade-out($gray, 0.8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.banner-dark {
|
&.banner-500 {
|
||||||
background-color: $lektor-header-bg;
|
height: 500px;
|
||||||
|
|
||||||
|
@media (max-width: $screen-md-max) { height: 300px; }
|
||||||
|
@media (max-width: $screen-sm-max) { height: 200px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
&.banner-300 {
|
||||||
|
height: 300px;
|
||||||
|
|
||||||
|
@media (max-width: $screen-md-max) { height: 200px; }
|
||||||
|
@media (max-width: $screen-sm-max) { height: 120px; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,11 +301,24 @@ div.doc-styling {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.type-info {
|
ul.page-meta {
|
||||||
|
list-style: none;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
margin: 0;
|
||||||
p.type-info + p.type-info {
|
padding: 0 0 0 30px;
|
||||||
margin-top: 0;
|
line-height: 1.4;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
@ -314,6 +337,10 @@ div.doc-styling {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
tr:nth-child(odd) {
|
tr:nth-child(odd) {
|
||||||
background: #f8f8f8;
|
background: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
@ -600,6 +627,56 @@ div.sourceviewer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
margin: 15px 0;
|
||||||
|
background: white;
|
||||||
|
padding: 10px 15px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
margin: -10px -15px 10px -15px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
line-height: 1;
|
||||||
|
background: #ccc;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.admonition-note {
|
||||||
|
&:before {
|
||||||
|
content: "Note";
|
||||||
|
background: #8FC4E0;
|
||||||
|
}
|
||||||
|
border: 1px solid #8FC4E0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.admonition-info {
|
||||||
|
&:before {
|
||||||
|
content: "Info";
|
||||||
|
background: #E0C18F;
|
||||||
|
}
|
||||||
|
border: 1px solid #E0C18F;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.admonition-tip {
|
||||||
|
&:before {
|
||||||
|
content: "Tip";
|
||||||
|
background: #9EB675;
|
||||||
|
}
|
||||||
|
border: 1px solid #9EB675;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.admonition-warning {
|
||||||
|
&:before {
|
||||||
|
content: "Warning";
|
||||||
|
background: #E0AA8F;
|
||||||
|
}
|
||||||
|
border: 1px solid #E0AA8F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* search */
|
/* search */
|
||||||
div.doc-styling div.gsc-control-cse {
|
div.doc-styling div.gsc-control-cse {
|
||||||
font-family: $font-family-base!important;
|
font-family: $font-family-base!important;
|
||||||
|
|