prepare for next implementation in go
This commit is contained in:
parent
5570b0b568
commit
83cb61da71
9
Gemfile
9
Gemfile
|
@ -1,9 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'sequel'
|
||||
gem 'pg'
|
||||
gem 'zero', :git => 'https://github.com/libzero/zero.git'
|
||||
gem 'slim'
|
||||
gem 'sass'
|
||||
gem 'kramdown'
|
||||
gem 'puma'
|
34
Gemfile.lock
34
Gemfile.lock
|
@ -1,34 +0,0 @@
|
|||
GIT
|
||||
remote: https://github.com/libzero/zero.git
|
||||
revision: dde9fc410fb50bc44b128fb1032b15f09c53e0f7
|
||||
specs:
|
||||
zero (0.2.0)
|
||||
tilt
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
kramdown (1.3.2)
|
||||
pg (0.17.1)
|
||||
puma (2.7.1)
|
||||
rack (>= 1.1, < 2.0)
|
||||
rack (1.5.2)
|
||||
sass (3.2.14)
|
||||
sequel (4.7.0)
|
||||
slim (2.0.2)
|
||||
temple (~> 0.6.6)
|
||||
tilt (>= 1.3.3, < 2.1)
|
||||
temple (0.6.7)
|
||||
tilt (2.0.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
kramdown
|
||||
pg
|
||||
puma
|
||||
sass
|
||||
sequel
|
||||
slim
|
||||
zero!
|
|
@ -1,8 +0,0 @@
|
|||
#!/usr/bin/env rackup
|
||||
require File.expand_path('../lib/boot.rb', __FILE__)
|
||||
|
||||
Renderer.find_templates('templates')
|
||||
run Application.new(Router, {
|
||||
:renderer => Renderer,
|
||||
:query => {}
|
||||
})
|
|
@ -1 +0,0 @@
|
|||
:db: "postgres://localhost/blogdb"
|
|
@ -1,7 +0,0 @@
|
|||
module Routes
|
||||
class Atom
|
||||
def self.call(session)
|
||||
Post
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
module Routes
|
||||
class Images
|
||||
def self.call(session)
|
||||
file = "images/#{session.request.path.gsub(/images/, '')}"
|
||||
return RouteNotFound unless File.exist?(file)
|
||||
session.response.body = File.read(file)
|
||||
session.response.content_type = 'image/png'
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
module Routes
|
||||
class MethodNotAllowed
|
||||
def self.call(session)
|
||||
session.response.status = 405
|
||||
session.response.content_type = 'text/html'
|
||||
session.response.body = 'Method not supported by this resource!'
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,63 +0,0 @@
|
|||
module Routes
|
||||
class Post < Controller
|
||||
PREV_AND_NEXT_QUERY = <<SQL
|
||||
select (
|
||||
select id from posts where written < ? and released order by written desc limit 1
|
||||
) older,
|
||||
(
|
||||
select id from posts where written > ? and released order by written limit 1
|
||||
) younger
|
||||
SQL
|
||||
|
||||
def self.get(session)
|
||||
posts = define_posts_query(session)
|
||||
if session.options[:id]
|
||||
posts = posts.filter(:posts__id => session.options[:id].to_i)
|
||||
return RouteNotFound if posts.empty?
|
||||
set_previous_and_next_post(session, posts)
|
||||
else
|
||||
if session.request.params['search']
|
||||
posts = load_fulltextsearch(session, posts)
|
||||
end
|
||||
page = session.request.params['page'].to_i
|
||||
per_page = session.request.params['per_page'].to_i
|
||||
per_page = 10 if per_page && per_page < 1
|
||||
set_page_information(session, posts, page, per_page)
|
||||
posts = posts.limit(per_page).offset(page * per_page)
|
||||
end
|
||||
session.options[:posts] = posts
|
||||
session.options[:render] = 'posts/index'
|
||||
end
|
||||
|
||||
def self.define_posts_query(session)
|
||||
posts = DB[:posts].
|
||||
filter(:released => true).
|
||||
select(:posts__id___post_id, :written, :title, :content, :username).
|
||||
join(:accounts, :id___account_id => :account_id).
|
||||
reverse_order(:written, :posts__id)
|
||||
end
|
||||
|
||||
# load posts depending on the pagination
|
||||
def self.set_page_information(session, posts, page, per_page)
|
||||
# compute pages
|
||||
session.options[:page] = page if page
|
||||
session.options[:query][:per_page] = per_page if per_page
|
||||
session.options[:pages] = posts.count / per_page
|
||||
end
|
||||
|
||||
# load a single posts and the ids of the next and previous posts
|
||||
def self.set_previous_and_next_post(session, posts)
|
||||
written = posts.first[:written]
|
||||
session.options[:post_ids_pn] = DB[PREV_AND_NEXT_QUERY, written, written].first
|
||||
end
|
||||
|
||||
# adjust query to use fulltext search
|
||||
def self.load_fulltextsearch(session, posts)
|
||||
session.options[:query][:search] = session.request.params['search']
|
||||
posts.filter(
|
||||
'posts.search_field @@ to_tsquery(\'english\', ?)',
|
||||
session.request.params['search'].tr(' ', '&')
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
module Routes
|
||||
class RouteNotFound < Controller
|
||||
def self.get(session)
|
||||
session.options[:render] = 'error/route_not_found'
|
||||
session.response.status = 404
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
module Routes
|
||||
class Stylesheet
|
||||
def self.call(session)
|
||||
session.options[:render] = 'stylesheet/index'
|
||||
session.options[:renderer]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
module Routes
|
||||
class Welcome
|
||||
def self.call(session)
|
||||
Post
|
||||
end
|
||||
end
|
||||
end
|
Binary file not shown.
Before Width: | Height: | Size: 56 KiB |
|
@ -1,19 +0,0 @@
|
|||
class Application
|
||||
def initialize(start, defaults = {})
|
||||
@start = start
|
||||
@defaults = defaults
|
||||
end
|
||||
|
||||
def call(env)
|
||||
session = Session.new(
|
||||
::Zero::Request.new(env),
|
||||
::Zero::Response.new,
|
||||
Render.new(@defaults.clone)
|
||||
)
|
||||
worker = @start
|
||||
while not worker.nil?
|
||||
worker = worker.call(session)
|
||||
end
|
||||
session.response.to_a
|
||||
end
|
||||
end
|
16
lib/boot.rb
16
lib/boot.rb
|
@ -1,16 +0,0 @@
|
|||
$LOAD_PATH << File.expand_path('..', __FILE__)
|
||||
|
||||
require 'libraries'
|
||||
require 'session'
|
||||
require 'application'
|
||||
require 'controller'
|
||||
require 'renderer'
|
||||
require 'render'
|
||||
require 'router'
|
||||
|
||||
config = YAML.load_file(File.expand_path('../../config.yml', __FILE__))
|
||||
DB = Sequel.connect(config[:db])
|
||||
|
||||
Dir[File.expand_path('../../controller', __FILE__) + '/**'].each do |controller|
|
||||
require controller
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
class Controller
|
||||
def self.call(session)
|
||||
return call_method(session) if respond_to? session.request.method
|
||||
Routes::MethodNotAllowed.call(session)
|
||||
end
|
||||
|
||||
def self.call_method(session)
|
||||
result = send(session.request.method, session)
|
||||
return result if result.kind_of?(Class)
|
||||
session.options[:renderer]
|
||||
end
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
require 'bundler/setup'
|
||||
require 'yaml'
|
||||
require 'sass'
|
||||
require 'tilt'
|
||||
require 'tilt/sass'
|
||||
require 'sequel'
|
||||
require 'zero'
|
||||
require 'slim'
|
||||
require 'kramdown'
|
|
@ -1,46 +0,0 @@
|
|||
# defines a render container with some helper functions to keep the templates
|
||||
# small
|
||||
class Render
|
||||
SLASH = '/'
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
end
|
||||
|
||||
def [](key)
|
||||
fetch(key)
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
@options[key] = value
|
||||
end
|
||||
|
||||
def fetch(key)
|
||||
@options[key]
|
||||
end
|
||||
|
||||
def has_key?(key)
|
||||
@options.has_key?(key)
|
||||
end
|
||||
|
||||
def options
|
||||
@options
|
||||
end
|
||||
|
||||
def link_to(*params)
|
||||
query = []
|
||||
while params.last.kind_of? Hash
|
||||
query.push params.pop
|
||||
end
|
||||
return path(params) if query.empty?
|
||||
path(params) + '?' + query_string(query)
|
||||
end
|
||||
|
||||
def path(params)
|
||||
SLASH + params.join(SLASH)
|
||||
end
|
||||
|
||||
def query_string(query)
|
||||
URI.encode_www_form(query.inject(:merge))
|
||||
end
|
||||
end
|
|
@ -1,84 +0,0 @@
|
|||
class Renderer
|
||||
COMPONENT_MATCHER = %r{/?(?<template>[^\.]+)\.(?<type>[^\.]+)\.(?<engine>.+)}
|
||||
DEFAULT_TYPE = :default_type
|
||||
|
||||
def self.call(session)
|
||||
template = do_checks(session)
|
||||
return nil unless template
|
||||
type = get_type(session, template)
|
||||
session.response.body = render(template, type, session.options)
|
||||
session.response.content_type = type_map[type]
|
||||
nil
|
||||
end
|
||||
|
||||
def self.render(template, type, object)
|
||||
layout = templates['layout']
|
||||
if layout && layout.has_key?(type)
|
||||
return layout[type].render(object) do
|
||||
template[type].render(object)
|
||||
end
|
||||
end
|
||||
template[type].render(object)
|
||||
end
|
||||
|
||||
def self.do_checks(session)
|
||||
unless session.options.has_key? :render
|
||||
session.response.body = ':render not set!'
|
||||
return nil
|
||||
end
|
||||
to_render = session.options[:render]
|
||||
unless templates.has_key? to_render
|
||||
session.response.body = 'Template does not exist!'
|
||||
return nil
|
||||
end
|
||||
return templates[to_render]
|
||||
end
|
||||
|
||||
# initialize the template cache
|
||||
def self.find_templates(path)
|
||||
templates = {}
|
||||
Dir[path + '/**/*'].each do |file|
|
||||
parts = file.gsub(path, '').match(COMPONENT_MATCHER)
|
||||
next unless File.file?(file) && parts
|
||||
templates[parts[:template]] ||= {}
|
||||
templates[parts[:template]].merge!({parts[:type].to_sym => Tilt.new(file)})
|
||||
end
|
||||
templates
|
||||
end
|
||||
|
||||
def self.templates
|
||||
@@templates ||= find_templates 'templates'
|
||||
end
|
||||
|
||||
def self.set_types(types)
|
||||
@@type_map = types.invert
|
||||
@@types = types
|
||||
end
|
||||
|
||||
def self.types
|
||||
@@types ||= {
|
||||
'*/*' => DEFAULT_TYPE,
|
||||
'text/css' => :css,
|
||||
'text/html' => :html,
|
||||
'application/atom+xml' => :atom
|
||||
}
|
||||
end
|
||||
|
||||
def self.type_map
|
||||
@@type_map ||= types.invert
|
||||
end
|
||||
|
||||
def self.get_type(session, template)
|
||||
type = get_preferred_type(session.request, template)
|
||||
return template.first[0] if type == DEFAULT_TYPE
|
||||
type
|
||||
end
|
||||
|
||||
def self.get_preferred_type(request, template)
|
||||
request.accept.types.each do |type|
|
||||
next unless types.has_key? type
|
||||
return types[type] if template.has_key? types[type]
|
||||
return DEFAULT_TYPE if types[type] == DEFAULT_TYPE
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,38 +0,0 @@
|
|||
class Router
|
||||
ROUTE_REGEX = %r{\A(/(?<controller>[a-zA-Z]+)\.?(?<extension>[a-zA-Z]+)?(/(?<id>[^/]+)?)?)?\Z}
|
||||
# get the controller handling the request
|
||||
def self.call(session)
|
||||
variables = session.request.path.match(ROUTE_REGEX)
|
||||
return default_route unless variables && variables[:controller]
|
||||
session.options[:id] = variables[:id]
|
||||
find(variables[:controller])
|
||||
end
|
||||
|
||||
# the namespace of all routes
|
||||
def self.namespace
|
||||
@@namespace ||= ::Routes
|
||||
end
|
||||
|
||||
# set the namespace to a module or class which holds all controllers
|
||||
def self.set_namespace(namespace)
|
||||
@@namespace = namespace
|
||||
end
|
||||
|
||||
# the default route to take when no path is given
|
||||
def self.default_route
|
||||
@@default ||= namespace.const_get(:Welcome)
|
||||
end
|
||||
|
||||
# set the default route to take when no path is given
|
||||
def self.set_default_route(default)
|
||||
@@default = default
|
||||
end
|
||||
|
||||
# check for the controller name and return 404 when not found
|
||||
def self.find(ctrl)
|
||||
ctrl = ctrl.capitalize
|
||||
# make constant lookup without ancestors
|
||||
return namespace.const_get(ctrl, false) if namespace.const_defined?(ctrl, false)
|
||||
namespace::RouteNotFound
|
||||
end
|
||||
end
|
|
@ -1 +0,0 @@
|
|||
Session = Struct.new(:request, :response, :options)
|
|
@ -1,47 +0,0 @@
|
|||
Sequel.migration do
|
||||
change do
|
||||
create_table(:accounts) do
|
||||
primary_key :id
|
||||
String :username, :size=>50
|
||||
String :email, :size=>50
|
||||
String :crypted_password, :size=>70
|
||||
String :role, :size=>50
|
||||
end
|
||||
|
||||
create_table(:tags) do
|
||||
primary_key :id
|
||||
String :name, :text=>true
|
||||
end
|
||||
|
||||
create_table(:posts, :ignore_index_errors=>true) do
|
||||
primary_key :id
|
||||
String :title, :text=>true, :null=>false
|
||||
DateTime :written
|
||||
TrueClass :released, :default=>false
|
||||
String :markup, :default=>"markdown", :text=>true
|
||||
String :content, :text=>true
|
||||
foreign_key :account_id, :accounts, :null=>false, :key=>[:id]
|
||||
|
||||
index [:account_id], :name=>:index_posts_account
|
||||
index [:written, :id], :name=>:posts_written_id_idx
|
||||
end
|
||||
|
||||
create_table(:comments, :ignore_index_errors=>true) do
|
||||
primary_key :id
|
||||
String :author, :size=>50
|
||||
String :email, :size=>50
|
||||
TrueClass :acknowledged, :default=>false
|
||||
String :body, :text=>true
|
||||
foreign_key :post_id, :posts, :null=>false, :key=>[:id]
|
||||
|
||||
index [:post_id], :name=>:index_comments_post
|
||||
end
|
||||
|
||||
create_table(:post_tags) do
|
||||
foreign_key :post_id, :posts, :null=>false, :key=>[:id]
|
||||
foreign_key :tag_id, :tags, :null=>false, :key=>[:id]
|
||||
|
||||
primary_key [:post_id, :tag_id]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,52 +0,0 @@
|
|||
# this is the schema from the old platform
|
||||
Sequel.migration do
|
||||
up do
|
||||
drop_table :post_tags
|
||||
drop_table :comments
|
||||
drop_table :tags
|
||||
|
||||
alter_table :posts do
|
||||
add_column :language, String, :size => 10
|
||||
end
|
||||
|
||||
from(:posts).update(:language => 'english')
|
||||
|
||||
alter_table :posts do
|
||||
set_column_not_null :language
|
||||
end
|
||||
|
||||
run 'create function search_field(posts) returns tsvector as $$' +
|
||||
"select to_tsvector($1.language::regconfig, $1.title || ' ' || $1.content);" +
|
||||
'$$ language sql immutable;'
|
||||
end
|
||||
|
||||
down do
|
||||
alter_table :posts do
|
||||
drop_column :language
|
||||
end
|
||||
run 'drop function search_field(posts);'
|
||||
|
||||
create_table(:tags) do
|
||||
primary_key :id
|
||||
String :name, :text=>true
|
||||
end
|
||||
|
||||
create_table(:comments, :ignore_index_errors=>true) do
|
||||
primary_key :id
|
||||
String :author, :size=>50
|
||||
String :email, :size=>50
|
||||
TrueClass :acknowledged, :default=>false
|
||||
String :body, :text=>true
|
||||
foreign_key :post_id, :posts, :null=>false, :key=>[:id]
|
||||
|
||||
index [:post_id], :name=>:index_comments_post
|
||||
end
|
||||
|
||||
create_table(:post_tags) do
|
||||
foreign_key :post_id, :posts, :null=>false, :key=>[:id]
|
||||
foreign_key :tag_id, :tags, :null=>false, :key=>[:id]
|
||||
|
||||
primary_key [:post_id, :tag_id]
|
||||
end
|
||||
end
|
||||
end
|
Binary file not shown.
Before Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 104 KiB |
|
@ -1,4 +0,0 @@
|
|||
p.error
|
||||
'Sorry, this article does not exist. Maybe you want to go the
|
||||
a(href=link_to('')) homepage
|
||||
' and see, if you can find your post there?
|
|
@ -1,24 +0,0 @@
|
|||
doctype 5
|
||||
html
|
||||
head
|
||||
title zero-knowledge
|
||||
meta(
|
||||
http-equiv='Content-Type'
|
||||
content='text/html; charset=utf-8')
|
||||
link(
|
||||
href='/atom.xml'
|
||||
rel='alternate'
|
||||
title='Atom 1.0'
|
||||
type='application/atom+xml')
|
||||
link(
|
||||
href='/stylesheet.css'
|
||||
rel='stylesheet'
|
||||
type='text/css')
|
||||
body
|
||||
header#header
|
||||
a href='/'
|
||||
h1 zero-knowledge
|
||||
h2 no clue at all
|
||||
img src='/images/zero-knowledge.png' alt='zero-knowledge'
|
||||
#content
|
||||
==yield
|
|
@ -1,18 +0,0 @@
|
|||
doctype xml
|
||||
feed xmlns='http://www.w3.org/2005/Atom'
|
||||
title zero-knowledge
|
||||
link href='http://zero-knowledge.org'
|
||||
link type='application/atom+xml' rel='self' href='http://zero-knowledge.org'
|
||||
updated=fetch(:posts).first[:written].xmlschema
|
||||
id http://zero-knowledge.org/
|
||||
-for post in fetch(:posts)
|
||||
entry
|
||||
id="http://zero-knowledge.org/post/#{post[:post_id]}"
|
||||
link(type='text/html' rel='alternate'
|
||||
href="http://zero-knowledge.org/post/#{post[:post_id]}")
|
||||
title=post[:title]
|
||||
updated=post[:written].xmlschema
|
||||
author
|
||||
name=post[:username]
|
||||
summary type='html'=post[:content]
|
||||
content type='html'=Kramdown::Document.new(post[:content]).to_html
|
|
@ -1,29 +0,0 @@
|
|||
- if has_key?(:page) && 0 < fetch(:page)
|
||||
a.page.up(
|
||||
href=link_to(:post, fetch(:query), :page => fetch(:page) - 1)
|
||||
) show newer
|
||||
- if has_key?(:post_ids_pn) && fetch(:post_ids_pn)[:younger]
|
||||
a.page.up(
|
||||
href=link_to(:post, fetch(:post_ids_pn)[:younger])
|
||||
) show newer
|
||||
|
||||
- for post in fetch(:posts)
|
||||
article
|
||||
header
|
||||
h1
|
||||
//a(href=link_to(:post, post[:post_id], fetch(:query))) post[:title]
|
||||
a(href=link_to(:post, post[:post_id]))=post[:title]
|
||||
footer
|
||||
.author=post[:username]
|
||||
.date= post[:written].strftime('%Y-%m-%d')
|
||||
.time= post[:written].strftime('%H-%M')
|
||||
section==Kramdown::Document.new(post[:content]).to_html
|
||||
|
||||
- if has_key?(:page) && fetch(:page) < fetch(:pages)
|
||||
a.page.down(
|
||||
href=link_to(:post, fetch(:query), :page => fetch(:page) + 1)
|
||||
) show older
|
||||
- if has_key?(:post_ids_pn) && fetch(:post_ids_pn)[:older]
|
||||
a.page.down(
|
||||
href=link_to(:post, fetch(:post_ids_pn)[:older])
|
||||
) show older
|
|
@ -1,130 +0,0 @@
|
|||
// normal text color
|
||||
$normal_color: hsl(0,0, 90%);
|
||||
// the nice orange
|
||||
$action_color: hsl(32, 100%, 50%);
|
||||
// the blue
|
||||
$alternate_color: hsl(204, 35%, 35%);
|
||||
// box color for quotes and code
|
||||
$box_color: hsla(0, 0%, 0%, 0);
|
||||
|
||||
// standard size to size everything from that
|
||||
$standard-width: 1em;
|
||||
|
||||
// other variables
|
||||
$box_border: $standard-width solid $box_color;
|
||||
|
||||
html {
|
||||
font-size: 99%;
|
||||
font-family: sans-serif;
|
||||
/* original picture from http://subtlepatterns.com/iron-grip/ */
|
||||
background-image: url('/images/irongrip-zero.png');
|
||||
min-width: 300px;
|
||||
width: 100%;
|
||||
max-width: 1100px;
|
||||
margin: auto;
|
||||
color: $normal_color;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "PT mono", monospace;
|
||||
}
|
||||
pre {
|
||||
border: $box_border;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border: $box_border;
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
|
||||
p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#header {
|
||||
h1, h2 {
|
||||
display: none;
|
||||
margin: $standard-width / 2;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
padding-left: $standard-width;
|
||||
padding-right: $standard-width;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: $action-color;
|
||||
}
|
||||
|
||||
.page {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: $standard-width;
|
||||
font-size: $standard-width * 0.9;
|
||||
font-weight: bold;
|
||||
&.up {
|
||||
border-top: $standard-width / 4 solid $alternate-color;
|
||||
&:hover, &:focus, &:active {
|
||||
border-top: $standard-width / 4 solid $action-color;
|
||||
}
|
||||
}
|
||||
&.down {
|
||||
border-bottom: $standard-width / 4 solid $alternate-color;
|
||||
&:hover, &:focus, &:active {
|
||||
border-bottom: $standard-width / 4 solid $action-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
padding: $standard-width;
|
||||
}
|
||||
|
||||
#content, pre, blockquote {
|
||||
background-color: fade-out($alternate-color, 0.7);
|
||||
}
|
||||
|
||||
article {
|
||||
padding-top: $standard-width;
|
||||
padding-bottom: $standard-width;
|
||||
header {
|
||||
padding: $standard-width / 4;
|
||||
display: inline-block;
|
||||
h1 { margin: 0;}
|
||||
h1, h2 { display: inline-block; }
|
||||
}
|
||||
footer {
|
||||
padding: $standard-width / 4;
|
||||
display: inline-block;
|
||||
font-size: $standard-width * 0.9;
|
||||
div {
|
||||
display: inline-block;
|
||||
margin: $standard-width / 5;
|
||||
font-weight: bold;
|
||||
color: hsl(0, 0%, 60%);
|
||||
}
|
||||
.author:before { content: 'by '; }
|
||||
.date:before { content: ' on '; }
|
||||
.time { display: none; }
|
||||
}
|
||||
section {
|
||||
border-top: $standard-width/5 solid $alternate-color;
|
||||
word-wrap: break-word;
|
||||
h1 { font-size: $standard-width * 1.3 }
|
||||
h2 { font-size: $standard-width * 1.2 }
|
||||
h3 { font-size: $standard-width * 1.1; font-weight: normal; }
|
||||
h1, h2, h3 {
|
||||
border-bottom: $standard-width / 10 solid $normal-color;
|
||||
margin-right: 25%;
|
||||
}
|
||||
code, pre { word-wrap: initial; }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue