Run jekyll as part of the matrix-doc build

- this saves us having to run it manually on the web server.
pull/984/head
Richard van der Hoff 7 years ago
parent 299b60970b
commit 9d2a93ad7b

14
.gitignore vendored

@ -1,10 +1,10 @@
scripts/gen
scripts/continuserv/continuserv
scripts/speculator/speculator
/scripts/gen
/scripts/continuserv/continuserv
/scripts/speculator/speculator
/scripts/swagger
templating/out
/templating/out
*.pyc
*.swp
supporting-docs/_site
supporting-docs/.sass-cache
api/node_modules
/api/node_modules
/site.tar.gz
/_site

@ -0,0 +1,21 @@
# Site settings
title: Matrix
email: webmaster@matrix.org
description: > # this means to ignore newlines until "baseurl:"
Matrix.org documentation
baseurl: "/docs" # the subpath of your site, e.g. /blog/
url: "http://matrix.org" # the base hostname & protocol for your site
twitter_username: matrixdotorg
github_username: matrix-org
exclude:
- "*.png"
- "*.jpg"
- "*.gif"
# Build settings
markdown: kramdown
#defaults:
permalink: /:categories/:title.html # can use this when/if we use jekyll for all docs
#permalink: /:title.html

@ -0,0 +1,7 @@
<script type='text/javascript' src='//matrix.org/blog/wp-content/themes/Divi-child/js/waypoints.min.js?ver=2.2'></script>
<script type='text/javascript' src='//matrix.org/docs/css/custom.js'></script>
<div id="footer"><div id="footerContent">&copy 2014-2017 Matrix.org | Hosted by <a href="https://upcloud.com/matrix">UpCloud</a></div></div>

@ -0,0 +1,28 @@
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type='text/javascript' src='//matrix.org/blog/wp-includes/js/jquery/jquery.js?ver=1.11.3'></script>
<link rel="stylesheet" href="/site.css">
<link rel="stylesheet" href="/docs/css/main.css">
<link rel="stylesheet" href="/docs/css/site_overrides.css">
<link rel="stylesheet" href="/docs/css/basic.css">
<link rel="stylesheet" href="/docs/css/nature.css">
<link rel='stylesheet' id='divi-fonts-css' href='//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,800italic,400,300,700,800&#038;subset=latin,latin-ext' type='text/css' media='all'>
<link rel='stylesheet' id='divi-style-css' href='//matrix.org/blog/wp-content/themes/Divi-child/style.css?ver=2.2' type='text/css' media='all'>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-54779209-1', 'auto');
ga('send', 'pageview');
</script>

@ -0,0 +1,32 @@
<header id="main-header" class="et_nav_text_color_dark" style="top: 0px;">
<div class="container clearfix" >
<a href="https://matrix.org/blog/">
<img src="//matrix.org/blog/wp-content/uploads/2015/01/logo1.png" alt="Matrix.org" id="logo" />
</a>
<div id="et-top-navigation">
<nav id="top-menu-nav">
<ul id="top-menu" class="nav"><li id="menu-item-17" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-17"><a href="http://matrix.org/">Home</a></li>
<li id="menu-item-794" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-794"><a href="/docs/projects/try-matrix-now.html">Try Matrix Now!</a></li>
<li id="menu-item-348" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-348"><a href="/docs/guides/">Guides</a></li>
<li id="menu-item-349" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-349"><a href="/docs/spec">Spec</a></li>
<li id="menu-item-350" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-350"><a href="/docs/api/client-server">Client-Server APIs</a></li>
<li id="menu-item-351" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-351"><a href="/code">Code</a></li>
<li id="menu-item-347" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-347"><a href="/docs/guides/faq.html">FAQ</a></li>
<li id="menu-item-353" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-353"><a href="/blog">Blog</a></li>
</ul>
</nav>
<div id="et_top_search">
<span id="et_search_icon"></span>
<form role="search" method="get" class="et-search-form et-hidden" action="https://matrix.org/blog/">
<input type="search" class="et-search-field" placeholder="Search &hellip;" value="" name="s" title="Search for:" />
</form>
</div>
<div id="et_mobile_nav_menu">
<a href="#" class="mobile_nav closed">
<span class="select_page">Select Page</span>
<span class="mobile_menu_bar"></span>
</a>
</div>
</div> <!-- #et-top-navigation -->
</div> <!-- .container -->
</header> <!-- #main-header -->

@ -0,0 +1,4 @@
<title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %} | Matrix.org</title>
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en-US" class="js">
<head>
{% include title.html %}
{% include head.html %}
</head>
<body class="blog et_fixed_nav et_cover_background et_right_sidebar">
<div id="page-wrapper">
<div class="page-content" id="page-container">
{% include nav.html %}
<div id="main-content">
<div class="wrapper" id="wrapper">
<div class="document_foo" id="document">
{{ content }}
</div>
</div>
<div class="push"></div>
</div>
</div>
{% include footer.html %}
</div>
</div>
</body>
</html>

@ -0,0 +1,14 @@
---
layout: default
---
<div class="post">
<header class="post-header">
<h1 class="post-title">{{ page.title }}</h1>
</header>
<article class="post-content">
{{ content }}
</article>
</div>

@ -0,0 +1,6 @@
---
layout: default
---
{{ content }}

@ -0,0 +1,64 @@
---
layout: default
---
<style>
img[alt="screenshot"] {
max-width: 800px;
display: block;
}
.font18 {
font-size: 18px;
}
.bold {
font-weight: bold;
}
.thumbnail {
max-width: 150px;
}
.project {
vertical-align: text-top;
width: 170px;
padding-right: 5px;
padding-left: 5px;
padding-bottom: 20px;
}
.bigproject {
vertical-align: text-top;
width: 300px;
padding-right: 15px;
padding-left: 15px;
padding-bottom: 20px;
}
.featured_screenshot {
max-height: 200px;
width: auto;
display: block;
margin-left: auto;
margin-right: auto;
}
.toc {
display: table;
padding-top: 16px;
padding-right: 16px;
padding-bottom: 16px;
list-style: disc inside;
list-style-type: disc inside;
color: #2EA3F2;
padding-left: 16px;
width: 400px;
}
</style>
{{ content }}

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2011 Greg Thornton, http://xdissent.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

@ -0,0 +1,97 @@
Overview
========
This plugin adds `ReStructuredText`_ support to `Jekyll`_ and `Octopress`_.
It renders ReST in posts and pages, and provides a custom directive to
support Octopress-compatible syntax highlighting.
Requirements
============
* Jekyll *or* Octopress >= 2.0
* Docutils
* Pygments
* `RbST`_
Installation
============
1. Install Docutils and Pygments.
The most convenient way is to use virtualenv_burrito:
::
$ curl -s https://raw.github.com/brainsik/virtualenv-burrito/master/virtualenv-burrito.sh | bash
$ source /Users/xdissent/.venvburrito/startup.sh
$ mkvirtualenv jekyll-rst
$ pip install docutils pygments
2. Install RbST.
If you use `bundler`_ with Octopress, add ``gem 'RbST'`` to
your ``Gemfile`` in the ``development`` group, then run
``bundle install``. Otherwise, ``gem install RbST``.
3. Install the plugin.
For Jekyll:
::
$ cd <jekyll-project-path>
$ git submodule add https://github.com/xdissent/jekyll-rst.git _plugins/jekyll-rst
For Octopress:
::
$ cd <octopress-project-path>
$ git submodule add https://github.com/xdissent/jekyll-rst.git plugins/jekyll-rst
4. Start blogging in ReStructuredText. Any file with the ``.rst`` extension
will be parsed as ReST and rendered into HTML.
.. note:: Be sure to activate the ``jekyll-rst`` virtualenv before generating
the site by issuing a ``workon jekyll-rst``. I suggest you follow `Harry
Marr's advice`_ and create a ``.venv`` file that will automatically
activate the ``jekyll-rst`` virtualenv when you ``cd`` into your project.
Source Code Highlighting
========================
A ``code-block`` ReST directive is registered and aliased as ``sourcecode``.
It adds syntax highlighting to code blocks in your documents::
.. code-block:: ruby
# Output "I love ReST"
say = "I love ReST"
puts say
Optional arguments exist to supply a caption, link, and link title::
.. code-block:: console
:caption: Read Hacker News on a budget
:url: http://news.ycombinator.com
:title: Hacker News
$ curl http://news.ycombinator.com | less
Octopress already includes style sheets for syntax highlighting, but you'll
need to generate one yourself if using Jekyll::
$ pygmentize -S default -f html > css/pygments.css
Octopress Tips
==============
* Use ``.. more`` in your ReST documents to indicate where Octopress's
``excerpt`` tag should split your content for summary views.
.. _ReStructuredText: http://docutils.sourceforge.net/rst.html
.. _Jekyll: http://jekyllrb.com/
.. _Octopress: http://octopress.com/
.. _RbST: http://rubygems.org/gems/RbST
.. _bundler: http://gembundler.com/
.. _Harry Marr's advice: http://hmarr.com/2010/jan/19/making-virtualenv-play-nice-with-git/

@ -0,0 +1,30 @@
require 'rbst'
module Jekyll
class RestConverter < Converter
safe true
priority :low
def matches(ext)
ext =~ /rst/i
end
def output_ext(ext)
".html"
end
def convert(content)
RbST.executables = {:html => "#{File.expand_path(File.dirname(__FILE__))}/rst2html.py"}
RbST.new(content).to_html(:part => :fragment, :initial_header_level => 2)
end
end
module Filters
def restify(input)
site = @context.registers[:site]
converter = site.getConverterImpl(Jekyll::RestConverter)
converter.convert(input)
end
end
end

@ -0,0 +1,97 @@
# Define a new directive `code-block` (aliased as `sourcecode`) that uses the
# `pygments` source highlighter to render code in color.
#
# Incorporates code from the `Pygments`_ documentation for `Using Pygments in
# ReST documents`_ and `Octopress`_.
#
# .. _Pygments: http://pygments.org/
# .. _Using Pygments in ReST documents: http://pygments.org/docs/rstdirective/
# .. _Octopress: http://octopress.org/
import re
import os
import md5
import __main__
# Absolute path to pygments cache dir
PYGMENTS_CACHE_DIR = os.path.abspath(os.path.join(os.path.dirname(__main__.__file__), '../../.pygments-cache'))
# Ensure cache dir exists
if not os.path.exists(PYGMENTS_CACHE_DIR):
os.makedirs(PYGMENTS_CACHE_DIR)
from pygments.formatters import HtmlFormatter
from docutils import nodes
from docutils.parsers.rst import directives, Directive
from pygments import highlight
from pygments.lexers import get_lexer_by_name, TextLexer
class Pygments(Directive):
""" Source code syntax hightlighting.
"""
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
string_opts = ['title', 'url', 'caption']
option_spec = dict([(key, directives.unchanged) for key in string_opts])
has_content = True
def run(self):
self.assert_has_content()
try:
lexer_name = self.arguments[0]
lexer = get_lexer_by_name(lexer_name)
except ValueError:
# no lexer found - use the text one instead of an exception
lexer_name = 'text'
lexer = TextLexer()
formatter = HtmlFormatter()
# Construct cache filename
cache_file = None
content_text = u'\n'.join(self.content)
cache_file_name = '%s-%s.html' % (lexer_name, md5.new(content_text).hexdigest())
cached_path = os.path.join(PYGMENTS_CACHE_DIR, cache_file_name)
# Look for cached version, otherwise parse
if os.path.exists(cached_path):
cache_file = open(cached_path, 'r')
parsed = cache_file.read()
else:
parsed = highlight(content_text, lexer, formatter)
# Strip pre tag and everything outside it
pres = re.compile("<pre>(.+)<\/pre>", re.S)
stripped = pres.search(parsed).group(1)
# Create tabular code with line numbers
table = '<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers">'
lined = ''
for idx, line in enumerate(stripped.splitlines(True)):
table += '<span class="line-number">%d</span>\n' % (idx + 1)
lined += '<span class="line">%s</span>' % line
table += '</pre></td><td class="code"><pre><code class="%s">%s</code></pre></td></tr></table></div>' % (lexer_name, lined)
# Add wrapper with optional caption and link
code = '<figure class="code">'
if self.options:
caption = ('<span>%s</span>' % self.options['caption']) if 'caption' in self.options else ''
title = self.options['title'] if 'title' in self.options else 'link'
link = ('<a href="%s">%s</a>' % (self.options['url'], title)) if 'url' in self.options else ''
if caption or link:
code += '<figcaption>%s %s</figcaption>' % (caption, link)
code += '%s</figure>' % table
# Write cache
if cache_file is None:
cache_file = open(cached_path, 'w')
cache_file.write(parsed)
cache_file.close()
return [nodes.raw('', code, format='html')]
directives.register_directive('code-block', Pygments)
directives.register_directive('sourcecode', Pygments)

@ -0,0 +1,42 @@
#!/usr/bin/env python
# :Author: David Goodger, the Pygments team, Guenter Milde
# :Date: $Date: $
# :Copyright: This module has been placed in the public domain.
# This is a merge of the `Docutils`_ `rst2html` front end with an extension
# suggestion taken from the `Pygments`_ documentation, reworked specifically
# for `Octopress`_.
#
# .. _Pygments: http://pygments.org/
# .. _Docutils: http://docutils.sourceforge.net/
# .. _Octopress: http://octopress.org/
"""
A front end to docutils, producing HTML with syntax colouring using pygments
"""
try:
import locale
locale.setlocale(locale.LC_ALL, '')
except:
pass
from transform import transform
from docutils.writers.html4css1 import Writer
from docutils.core import default_description
from directives import Pygments
description = ('Generates (X)HTML documents from standalone reStructuredText '
'sources. Uses `pygments` to colorize the content of'
'"code-block" directives. Needs an adapted stylesheet'
+ default_description)
def main():
return transform(writer=Writer(), part='html_body')
if __name__ == '__main__':
# rav 2016/10/18: encode the output as UTF-8, otherwise python will grumble
# when writing to a pipe, because it doesn't know how to encode unicode
# strings.
print(main().encode('utf-8'))

@ -0,0 +1,42 @@
import sys
from docutils.core import publish_parts
from optparse import OptionParser
from docutils.frontend import OptionParser as DocutilsOptionParser
from docutils.parsers.rst import Parser
def transform(writer=None, part=None):
p = OptionParser(add_help_option=False)
# Collect all the command line options
docutils_parser = DocutilsOptionParser(components=(writer, Parser()))
for group in docutils_parser.option_groups:
p.add_option_group(group.title, None).add_options(group.option_list)
p.add_option('--part', default=part)
opts, args = p.parse_args()
settings = dict({
'file_insertion_enabled': False,
'raw_enabled': False,
'doctitle_xform': False,
})
if len(args) == 1:
try:
content = open(args[0], 'r').read()
except IOError:
content = args[0]
else:
content = sys.stdin.read()
parts = publish_parts(
source=content,
writer=writer,
settings_overrides=settings
)
if 'html_body' in parts:
return parts['html_body']
if opts.part in parts:
return parts[opts.part]
return ''

@ -0,0 +1,40 @@
# _plugins/post_images.rb
module Jekyll
POST_IMAGES_DIR = '_posts/projects/images'
DEST_IMAGES_DIR = 'projects/images'
class PostImageFile < StaticFile
def destination(dest)
name_bits = @name.split('-', 4)
date_dir = ''
date_dir += "#{name_bits.shift}/" if name_bits.first.to_i > 0
date_dir += "#{name_bits.shift}/" if name_bits.first.to_i > 0
date_dir += "#{name_bits.shift}/" if name_bits.first.to_i > 0
File.join(dest, date_dir + DEST_IMAGES_DIR, name_bits.join('-'))
end
end
class PostImagesGenerator < Generator
def generate(site)
# Check for the images directory inside the posts directory.
return unless File.exists?(POST_IMAGES_DIR)
post_images = []
# Process each image.
Dir.foreach(POST_IMAGES_DIR) do |entry|
if entry != '.' && entry != '..'
site.static_files << PostImageFile.new(site, site.source, POST_IMAGES_DIR, entry)
post_images << entry.gsub(File.extname(entry), '')
end
end
# Remove images considered to be "actual" posts from the posts array.
site.posts.each do |post|
if post_images.include?(post.id[1..-1].gsub('/', '-'))
site.posts.delete(post)
end
end
end
end
end

@ -0,0 +1,51 @@
module Jekyll
class ProjectVersionTag < Liquid::Tag
NO_GIT_MESSAGE = 'Oops, are you sure this is a git project?'
UNABLE_TO_PARSE_MESSAGE = 'Sorry, could not read project version at the moment'
def render(context)
if git_repo?
current_version.chomp
else
NO_GIT_MESSAGE
end
end
private
def current_version
@_current_version ||= begin
# attempt to find the latest tag, falling back to last commit
version = git_describe || parse_head
version || UNABLE_TO_PARSE_MESSAGE
end
end
def git_describe
tagged_version = %x{ git describe --tags --always }
if command_succeeded?
tagged_version
end
end
def parse_head
head_commitish = %x{ git rev-parse --short HEAD }
if command_succeeded?
head_commitish
end
end
def command_succeeded?
!$?.nil? && $?.success?
end
def git_repo?
system('git rev-parse')
end
end
end
Liquid::Template.register_tag('project_version', Jekyll::ProjectVersionTag)

@ -0,0 +1 @@
../supporting-docs

@ -0,0 +1,204 @@
/**
* Reset some basic elements
*/
body, h1, h2, h3, h4, h5, h6,
p, blockquote, pre, hr,
dl, dd, ol, ul, figure {
margin: 0;
padding: 0;
}
/**
* Basic styling
*/
body {
font-family: $base-font-family;
font-size: $base-font-size;
line-height: $base-line-height;
font-weight: 300;
color: $text-color;
background-color: $background-color;
-webkit-text-size-adjust: 100%;
}
/**
* Set `margin-bottom` to maintain vertical rhythm
*/
h1, h2, h3, h4, h5, h6,
p, blockquote, pre,
ul, ol, dl, figure,
%vertical-rhythm {
margin-bottom: $spacing-unit / 2;
}
/**
* Images
*/
img {
max-width: 100%;
vertical-align: middle;
}
/**
* Figures
*/
figure > img {
display: block;
}
figcaption {
font-size: $small-font-size;
}
/**
* Lists
*/
ul, ol {
margin-left: $spacing-unit;
}
li {
> ul,
> ol {
margin-bottom: 0;
}
}
/**
* Headings
*/
h1, h2, h3, h4, h5, h6 {
font-weight: 300;
}
/**
* Links
*/
a {
color: $brand-color;
text-decoration: none;
&:visited {
color: darken($brand-color, 15%);
}
&:hover {
color: $text-color;
text-decoration: underline;
}
}
/**
* Blockquotes
*/
blockquote {
color: $grey-color;
border-left: 4px solid $grey-color-light;
padding-left: $spacing-unit / 2;
font-size: 18px;
letter-spacing: -1px;
font-style: italic;
> :last-child {
margin-bottom: 0;
}
}
/**
* Code formatting
*/
pre,
code {
font-size: 15px;
border: 1px solid $grey-color-light;
border-radius: 3px;
background-color: #eef;
}
code {
padding: 1px 5px;
}
pre {
padding: 8px 12px;
overflow-x: scroll;
> code {
border: 0;
padding-right: 0;
padding-left: 0;
}
}
/**
* Wrapper
*/
.wrapper {
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
margin-right: auto;
margin-left: auto;
padding-right: $spacing-unit;
padding-left: $spacing-unit;
@extend %clearfix;
@include media-query($on-laptop) {
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
max-width: calc(#{$content-width} - (#{$spacing-unit}));
padding-right: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
}
/**
* Clearfix
*/
%clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
/**
* Icons
*/
.icon {
> svg {
display: inline-block;
width: 16px;
height: 16px;
vertical-align: middle;
path {
fill: $grey-color;
}
}
}

@ -0,0 +1,236 @@
/**
* Site header
*/
.site-header {
border-top: 5px solid $grey-color-dark;
border-bottom: 1px solid $grey-color-light;
min-height: 56px;
// Positioning context for the mobile navigation icon
position: relative;
}
.site-title {
font-size: 26px;
line-height: 56px;
letter-spacing: -1px;
margin-bottom: 0;
float: left;
&,
&:visited {
color: $grey-color-dark;
}
}
.site-nav {
float: right;
line-height: 56px;
.menu-icon {
display: none;
}
.page-link {
color: $text-color;
line-height: $base-line-height;
// Gaps between nav items, but not on the first one
&:not(:first-child) {
margin-left: 20px;
}
}
@include media-query($on-palm) {
position: absolute;
top: 9px;
right: 30px;
background-color: $background-color;
border: 1px solid $grey-color-light;
border-radius: 5px;
text-align: right;
.menu-icon {
display: block;
float: right;
width: 36px;
height: 26px;
line-height: 0;
padding-top: 10px;
text-align: center;
> svg {
width: 18px;
height: 15px;
path {
fill: $grey-color-dark;
}
}
}
.trigger {
clear: both;
display: none;
}
&:hover .trigger {
display: block;
padding-bottom: 5px;
}
.page-link {
display: block;
padding: 5px 10px;
}
}
}
/**
* Site footer
*/
.site-footer {
border-top: 1px solid $grey-color-light;
padding: $spacing-unit 0;
}
.footer-heading {
font-size: 18px;
margin-bottom: $spacing-unit / 2;
}
.contact-list,
.social-media-list {
list-style: none;
margin-left: 0;
}
.footer-col-wrapper {
font-size: 15px;
color: $grey-color;
margin-left: -$spacing-unit / 2;
@extend %clearfix;
}
.footer-col {
float: left;
margin-bottom: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
.footer-col-1 {
width: -webkit-calc(35% - (#{$spacing-unit} / 2));
width: calc(35% - (#{$spacing-unit} / 2));
}
.footer-col-2 {
width: -webkit-calc(20% - (#{$spacing-unit} / 2));
width: calc(20% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(45% - (#{$spacing-unit} / 2));
width: calc(45% - (#{$spacing-unit} / 2));
}
@include media-query($on-laptop) {
.footer-col-1,
.footer-col-2 {
width: -webkit-calc(50% - (#{$spacing-unit} / 2));
width: calc(50% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
@include media-query($on-palm) {
.footer-col {
float: none;
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
/**
* Page content
*/
.page-content {
padding: $spacing-unit 0;
}
.page-heading {
font-size: 20px;
}
.post-list {
margin-left: 0;
list-style: none;
> li {
margin-bottom: $spacing-unit;
}
}
.post-meta {
font-size: $small-font-size;
color: $grey-color;
}
.post-link {
display: block;
font-size: 24px;
}
/**
* Posts
*/
.post-header {
margin-bottom: $spacing-unit;
}
.post-title {
font-size: 42px;
letter-spacing: -1px;
line-height: 1;
@include media-query($on-laptop) {
font-size: 36px;
}
}
.post-content {
margin-bottom: $spacing-unit;
h2 {
font-size: 32px;
@include media-query($on-laptop) {
font-size: 28px;
}
}
h3 {
font-size: 26px;
@include media-query($on-laptop) {
font-size: 22px;
}
}
h4 {
font-size: 20px;
@include media-query($on-laptop) {
font-size: 18px;
}
}
}

@ -0,0 +1,67 @@
/**
* Syntax highlighting styles
*/
.highlight {
background: #fff;
@extend %vertical-rhythm;
.c { color: #998; font-style: italic } // Comment
.err { color: #a61717; background-color: #e3d2d2 } // Error
.k { font-weight: bold } // Keyword
.o { font-weight: bold } // Operator
.cm { color: #998; font-style: italic } // Comment.Multiline
.cp { color: #999; font-weight: bold } // Comment.Preproc
.c1 { color: #998; font-style: italic } // Comment.Single
.cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
.gd { color: #000; background-color: #fdd } // Generic.Deleted
.gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
.ge { font-style: italic } // Generic.Emph
.gr { color: #a00 } // Generic.Error
.gh { color: #999 } // Generic.Heading
.gi { color: #000; background-color: #dfd } // Generic.Inserted
.gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
.go { color: #888 } // Generic.Output
.gp { color: #555 } // Generic.Prompt
.gs { font-weight: bold } // Generic.Strong
.gu { color: #aaa } // Generic.Subheading
.gt { color: #a00 } // Generic.Traceback
.kc { font-weight: bold } // Keyword.Constant
.kd { font-weight: bold } // Keyword.Declaration
.kp { font-weight: bold } // Keyword.Pseudo
.kr { font-weight: bold } // Keyword.Reserved
.kt { color: #458; font-weight: bold } // Keyword.Type
.m { color: #099 } // Literal.Number
.s { color: #d14 } // Literal.String
.na { color: #008080 } // Name.Attribute
.nb { color: #0086B3 } // Name.Builtin
.nc { color: #458; font-weight: bold } // Name.Class
.no { color: #008080 } // Name.Constant
.ni { color: #800080 } // Name.Entity
.ne { color: #900; font-weight: bold } // Name.Exception
.nf { color: #900; font-weight: bold } // Name.Function
.nn { color: #555 } // Name.Namespace
.nt { color: #000080 } // Name.Tag
.nv { color: #008080 } // Name.Variable
.ow { font-weight: bold } // Operator.Word
.w { color: #bbb } // Text.Whitespace
.mf { color: #099 } // Literal.Number.Float
.mh { color: #099 } // Literal.Number.Hex
.mi { color: #099 } // Literal.Number.Integer
.mo { color: #099 } // Literal.Number.Oct
.sb { color: #d14 } // Literal.String.Backtick
.sc { color: #d14 } // Literal.String.Char
.sd { color: #d14 } // Literal.String.Doc
.s2 { color: #d14 } // Literal.String.Double
.se { color: #d14 } // Literal.String.Escape
.sh { color: #d14 } // Literal.String.Heredoc
.si { color: #d14 } // Literal.String.Interpol
.sx { color: #d14 } // Literal.String.Other
.sr { color: #009926 } // Literal.String.Regex
.s1 { color: #d14 } // Literal.String.Single
.ss { color: #990073 } // Literal.String.Symbol
.bp { color: #999 } // Name.Builtin.Pseudo
.vc { color: #008080 } // Name.Variable.Class
.vg { color: #008080 } // Name.Variable.Global
.vi { color: #008080 } // Name.Variable.Instance
.il { color: #099 } // Literal.Number.Integer.Long
}

@ -0,0 +1,11 @@
---
layout: page
title: About
permalink: /about/
---
This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](http://jekyllrb.com/)
You can find the source code for the Jekyll new theme at: [github.com/jglovier/jekyll-new](https://github.com/jglovier/jekyll-new)
You can find the source code for Jekyll at [github.com/jekyll/jekyll](https://github.com/jekyll/jekyll)

@ -0,0 +1,129 @@
Application Services
====================
This file contains examples of some application service
IRC Bridge
----------
Pre-conditions:
- Server admin stores the AS token "T_a" on the home server.
- Home server has a token "T_h".
- Home server has the domain "hsdomain.com"
1. Application service registration
::
AS -> HS: Registers itself with the home server
POST /register
{
url: "https://someapp.com/matrix",
as_token: "T_a",
namespaces: {
users: [
{
"exclusive": true,
"regex": "@irc\.freenode\.net/.*"
}
],
aliases: [
{
"exclusive": true,
"regex": "#irc\.freenode\.net/.*"
}
]
}
}
Returns 200 OK:
{
hs_token: "T_h"
}
2. IRC user "Bob" says "hello?" on "#matrix" at timestamp 1421416883133:
::
- AS stores message as potential scrollback.
- Nothing happens as no Matrix users are in the room.
3. Matrix user "@alice:hsdomain.com" wants to join "#matrix":
::
User -> HS: Request to join "#irc.freenode.net/#matrix:hsdomain.com"
HS -> AS: Room Query "#irc.freenode.net/#matrix:hsdomain.com"
GET /rooms/%23irc.freenode.net%2F%23matrix%3Ahsdomain.com?access_token=T_h
[Starts blocking]
AS -> HS: Creates room. Gets room ID "!aasaasasa:hsdomain.com".
AS -> HS: Sets room name to "#matrix".
AS -> HS: Sends message as ""@irc.freenode.net/Bob:hsdomain.com"
PUT /rooms/%21aasaasasa%3Ahsdomain.com/send/m.room.message
?access_token=T_a
&user_id=%40irc.freenode.net%2FBob%3Ahsdomain.com
&ts=1421416883133
{
body: "hello?"
msgtype: "m.text"
}
HS -> AS: User Query "@irc.freenode.net/Bob:hsdomain.com"
GET /users/%40irc.freenode.net%2FBob%3Ahsdomain.com?access_token=T_h
[Starts blocking]
AS -> HS: Creates user using CS API extension.
POST /register?access_token=T_a
{
type: "m.login.application_service",
user: "irc.freenode.net/Bob"
}
AS -> HS: Set user display name to "Bob".
[Finishes blocking]
[Finished blocking]
- HS sends room information back to client.
4. @alice:hsdomain.com says "hi!" in this room:
::
User -> HS: Send message "hi!" in room !aasaasasa:hsdomain.com
- HS sends message.
- HS sees the room ID is in the AS namespace and pushes it to the AS.
HS -> AS: Push event
PUT /transactions/1?access_token=T_h
{
events: [
{
content: {
body: "hi!",
msgtype: "m.text"
},
origin_server_ts: <generated by hs>,
user_id: "@alice:hsdomain.com",
room_id: "!aasaasasa:hsdomain.com",
type: "m.room.message"
}
]
}
- AS passes this through to IRC.
5. IRC user "Bob" says "what's up?" on "#matrix" at timestamp 1421418084816:
::
IRC -> AS: "what's up?"
AS -> HS: Send message via CS API extension
PUT /rooms/%21aasaasasa%3Ahsdomain.com/send/m.room.message
?access_token=T_a
&user_id=%40irc.freenode.net%2FBob%3Ahsdomain.com
&ts=1421418084816
{
body: "what's up?"
msgtype: "m.text"
}
- HS modifies the user_id and origin_server_ts on the event and sends it.

@ -0,0 +1,30 @@
---
layout: null
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ site.title | xml_escape }}</title>
<description>{{ site.description | xml_escape }}</description>
<link>{{ site.url }}{{ site.baseurl }}/</link>
<atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml"/>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<generator>Jekyll v{{ jekyll.version }}</generator>
{% for post in site.posts limit:10 %}
<item>
<title>{{ post.title | xml_escape }}</title>
<description>{{ post.content | xml_escape }}</description>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
<link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
<guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
{% for tag in post.tags %}
<category>{{ tag | xml_escape }}</category>
{% endfor %}
{% for cat in post.categories %}
<category>{{ cat | xml_escape }}</category>
{% endfor %}
</item>
{% endfor %}
</channel>
</rss>

@ -0,0 +1,15 @@
---
layout: default
categories: guides
---
<div class="home">
<h1>Guides</h1>
<p>Here is a collection of guides that might help you get involved with Matrix.</p>
<p>First, there is the <a href="./getting_involved.html" title="Getting Involved">Getting Involved</a> guide, which explains various ways of getting started with Matrix.</p>
<p>The <a href="/docs/howtos/client-server.html" title="Client-Server API">Client-Server API</a> guide explains in detail how to use the CS API, which is useful if you want to write a client (or modify an existing one) - or if you're just interested in how it works "under the hood".</p>
<p>The <a href="./application_services.html" title="Application services">Application services</a> guide introduces and explains Application services, and what they can be used for.
<p>Finally there is the <a href="./faq.html" title="FAQ">FAQ</a>, which tries to answer all your questions relating to Matrix!</p>
</div>

@ -13,6 +13,12 @@ export GOPATH
go get github.com/hashicorp/golang-lru
go get gopkg.in/fsnotify.v1
# make sure that the scripts build
(cd scripts/continuserv && go build)
(cd scripts/speculator && go build)
# update the jekyll site
./scripts/generate-jekyll.sh
# create a tarball of the generated site
tar -czf site.tar.gz _site

@ -0,0 +1,23 @@
#!/usr/bin/env python
#
# adds anchors before any <h1/h2/h3/h4/h5> tags with an id="..." - this is used
# for things like the FAQ where we want to have anchored links to every
# question (and this way you don't have to manually maintain it in the source
# doc).
from sys import argv
import re
script, filename = argv
textfile = open(filename, "r")
regex = r'(<h\d id="(.*?)">)'
regex2 = r'(<div class="section" id="(.*?)">)'
replacement = r'<p><a class="anchor" id="\2"></a></p>\n\1'
# check for <hX id="..." (used in the FAQ) and add anchors - and then check
# for <div class="section" id="..." and add anchors (used in the spec)
for line in textfile:
line = re.sub(regex, replacement, line.rstrip())
print(re.sub(regex2, replacement, line.rstrip()))

@ -0,0 +1,20 @@
#!/bin/sh
#
# this script runs 'jekyll' to turn the 'supporting-docs' into HTML.
#
# jekyll requires the `docutils` and `pygments` python packages, so install
# them or run from a virtualenv which includes them.
set -e
# tell jekyll to parse things as utf-8
export LANG="en_GB.UTF-8"
cd `dirname $0`/..
mkdir -p _site
jekyll build -s jekyll
./scripts/add_anchors.py _site/guides/faq.html >tmp && mv tmp _site/guides/faq.html
./scripts/add_anchors.py _site/projects/try-matrix-now.html >tmp && mv tmp _site/projects/try-matrix-now.html
Loading…
Cancel
Save