Merge branch 'jekyll-3'

Conflicts:
	.gitignore
	Gemfile.lock
	source/_components/media_player.plex.markdown
	source/_includes/site/head.html
This commit is contained in:
Paulus Schoutsen 2015-10-29 00:08:22 -07:00
commit a08459ec8f
296 changed files with 1518 additions and 2884 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ source/_stash
source/stylesheets/screen.css
vendor
node_modules
source/.jekyll-metadata

17
Gemfile
View File

@ -2,10 +2,8 @@ source "https://rubygems.org"
group :development do
gem 'rake', '~> 10.0'
gem 'jekyll', '~> 2.0'
gem 'octopress-hooks', '~> 2.2'
gem 'octopress-date-format', '~> 2.0'
gem 'jekyll-sitemap'
gem 'jekyll', '~> 3.0'
gem 'pygments.rb', '~> 0.6.3'
gem 'rdiscount', '~> 2.0'
gem 'RedCloth', '~> 4.2.9'
gem 'haml', '~> 4.0'
@ -14,9 +12,18 @@ group :development do
gem 'rubypants', '~> 0.2.0'
gem 'rb-fsevent', '~> 0.9'
gem 'stringex', '~> 1.4.0'
gem 'jekyll-time-to-read'
gem 'execjs'
gem 'therubyracer', :platforms => :ruby
gem 'coderay'
end
group :jekyll_plugins do
gem 'jekyll-paginate'
gem 'jekyll-sitemap'
gem 'jekyll-time-to-read'
gem 'octopress', '~> 3.0'
gem 'octopress-filters'
gem 'octopress-include-tag'
end
gem 'sinatra', '~> 1.4.2'

View File

@ -2,43 +2,27 @@ GEM
remote: https://rubygems.org/
specs:
RedCloth (4.2.9)
blankslate (2.1.2.4)
chunky_png (1.3.4)
classifier-reborn (2.0.3)
fast-stemmer (~> 1.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.9.1.1)
chunky_png (1.3.5)
coderay (1.1.0)
colorator (0.1)
compass (0.12.7)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.2.19)
execjs (2.6.0)
fast-stemmer (1.0.2)
ffi (1.9.10)
fssm (0.2.10)
haml (4.0.7)
tilt
jekyll (2.5.3)
classifier-reborn (~> 2.0)
jekyll (3.0.0)
colorator (~> 0.1)
jekyll-coffeescript (~> 1.0)
jekyll-gist (~> 1.0)
jekyll-paginate (~> 1.0)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
liquid (~> 2.6.1)
liquid (~> 3.0)
mercenary (~> 0.3.3)
pygments.rb (~> 0.6.0)
redcarpet (~> 3.1)
rouge (~> 1.7)
safe_yaml (~> 1.0)
toml (~> 0.1.0)
jekyll-coffeescript (1.0.1)
coffee-script (~> 2.2)
jekyll-gist (1.3.5)
jekyll-paginate (1.1.0)
jekyll-sass-converter (1.3.0)
sass (~> 3.2)
@ -49,18 +33,35 @@ GEM
listen (~> 3.0)
kramdown (1.9.0)
libv8 (3.16.14.13)
liquid (2.6.3)
liquid (3.0.6)
listen (3.0.3)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
mercenary (0.3.5)
octopress-date-format (2.0.2)
jekyll (~> 2.0)
octopress (3.0.11)
jekyll (>= 2.0)
mercenary (~> 0.3.2)
octopress-deploy
octopress-escape-code (~> 2.0)
octopress-hooks (~> 2.0)
redcarpet (~> 3.0)
titlecase
octopress-deploy (1.3.0)
colorator
octopress-escape-code (2.0.6)
octopress-hooks (~> 2.0)
octopress-filters (1.4.0)
jekyll
octopress-hooks (~> 2.0)
rubypants-unicode
titlecase
octopress-hooks (2.6.1)
jekyll (>= 2.0)
parslet (1.5.0)
blankslate (~> 2.0)
octopress-include-tag (1.1.3)
jekyll (>= 2.0)
octopress-tag-helpers (~> 1.0)
octopress-tag-helpers (1.0.8)
jekyll (>= 2.0)
posix-spawn (0.3.11)
pygments.rb (0.6.3)
posix-spawn (~> 0.3.6)
@ -75,7 +76,9 @@ GEM
rdiscount (2.1.8)
redcarpet (3.3.3)
ref (2.0.0)
rouge (1.10.1)
rubypants (0.2.0)
rubypants-unicode (0.2.5)
safe_yaml (1.0.4)
sass (3.2.19)
sass-globbing (1.0.0)
@ -89,8 +92,7 @@ GEM
libv8 (~> 3.16.14.0)
ref
tilt (2.0.1)
toml (0.1.2)
parslet (~> 1.5.0)
titlecase (0.1.1)
yajl-ruby (1.2.1)
PLATFORMS
@ -98,14 +100,18 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.2.9)
coderay
compass (~> 0.12.2)
execjs
haml (~> 4.0)
jekyll (~> 2.0)
jekyll (~> 3.0)
jekyll-paginate
jekyll-sitemap
jekyll-time-to-read
octopress-date-format (~> 2.0)
octopress-hooks (~> 2.2)
octopress (~> 3.0)
octopress-filters
octopress-include-tag
pygments.rb (~> 0.6.3)
rake (~> 10.0)
rb-fsevent (~> 0.9)
rdiscount (~> 2.0)

View File

@ -65,7 +65,7 @@ task :watch do
raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir)
puts "Starting to watch source with Jekyll and Compass."
system "compass compile --css-dir #{source_dir}/stylesheets" unless File.exist?("#{source_dir}/stylesheets/screen.css")
jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch")
jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch --incremental")
compassPid = Process.spawn("compass watch")
trap("INT") {
@ -81,7 +81,7 @@ task :preview do
raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir)
puts "Starting to watch source with Jekyll and Compass. Starting Rack on port #{server_port}"
system "compass compile --css-dir #{source_dir}/stylesheets" unless File.exist?("#{source_dir}/stylesheets/screen.css")
jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch")
jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch --incremental")
compassPid = Process.spawn("compass watch")
rackupPid = Process.spawn("rackup --port #{server_port}")

View File

@ -26,24 +26,38 @@ email:
# Jekyll & Plugins #
# ----------------------- #
# If publishing to a subdirectory as in http://site.com/project set 'root: /project'
root: /
permalink: /blog/:year/:month/:day/:title/
source: source
destination: public/
plugins: plugins
plugins_dir: plugins
code_dir: downloads/code
category_dir: blog/categories
markdown: rdiscount
rdiscount:
extensions:
- autolink
- footnotes
- smart
highlighter: pygments # default python pygments have been replaced by pygments.rb
markdown: kramdown
kramdown:
input: GFM
auto_ids: false
footnote_nr: 1
entity_output: as_char
toc_levels: 1..6
smart_quotes: lsquo,rsquo,ldquo,rdquo
parse_block_html: true
enable_coderay: true
coderay:
coderay_wrap: div
coderay_line_numbers: nil
coderay_line_number_start: 1
coderay_tab_width: 4
coderay_bold_every: 10
coderay_css: class
highlighter: rouge
gems:
- jekyll-time-to-read
- octopress-filters
- octopress-include-tag
paginate: 10 # Posts per page on the blog index
paginate_path: "blog/posts/:num" # Directory base for pagination URLs eg. /posts/2/

View File

@ -16,7 +16,7 @@ class SinatraStaticServer < Sinatra::Base
def send_sinatra_file(path, &missing_file_block)
file_path = File.join(File.dirname(__FILE__), 'public', path)
file_path = File.join(file_path, 'index.html') unless file_path =~ /\.[a-z]+$/i
file_path = File.join(file_path, 'index.html') if File.directory?(file_path)
File.exist?(file_path) ? send_file(file_path) : missing_file_block.call
end

163
generate-redirect.py Normal file
View File

@ -0,0 +1,163 @@
import os
dirs = ['components', 'getting-started', 'developers']
template = "<script>document.location = '/{}/{}/';</script>"
for check_dir in dirs:
for path in os.listdir(os.path.join('public', check_dir)):
check_path = os.path.join('public', check_dir, path)
if os.path.isdir(check_path):
new_path = os.path.join('source', check_dir, "{}.html".format(path))
# print(template.format(check_dir, path))
# print(new_path)
with open(new_path, 'w') as outp:
outp.write(template.format(check_dir, path))
# Generated
# source/components/alarm_control_panel.html
# source/components/alarm_control_panel.manual.html
# source/components/alarm_control_panel.mqtt.html
# source/components/arduino.html
# source/components/automation.html
# source/components/browser.html
# source/components/camera.foscam.html
# source/components/camera.generic.html
# source/components/configurator.html
# source/components/conversation.html
# source/components/device_sun_light_trigger.html
# source/components/device_tracker.html
# source/components/device_tracker.actiontec.html
# source/components/device_tracker.aruba.html
# source/components/device_tracker.asuswrt.html
# source/components/device_tracker.ddwrt.html
# source/components/device_tracker.geofancy.html
# source/components/device_tracker.luci.html
# source/components/device_tracker.mqtt.html
# source/components/device_tracker.netgear.html
# source/components/device_tracker.nmap_scanner.html
# source/components/device_tracker.owntracks.html
# source/components/device_tracker.snmp.html
# source/components/device_tracker.thomson.html
# source/components/device_tracker.tomato.html
# source/components/device_tracker.tplink.html
# source/components/device_tracker.ubus.html
# source/components/discovery.html
# source/components/downloader.html
# source/components/group.html
# source/components/history.html
# source/components/ifttt.html
# source/components/ifttt.manything.html
# source/components/introduction.html
# source/components/isy994.html
# source/components/keyboard.html
# source/components/light.html
# source/components/light.blinksticklight.html
# source/components/light.hue.html
# source/components/light.hyperion.html
# source/components/light.limitlessled.html
# source/components/light.rfxtrx.html
# source/components/light.tellstick.html
# source/components/light.vera.html
# source/components/light.wink.html
# source/components/logbook.html
# source/components/media_player.html
# source/components/media_player.cast.html
# source/components/media_player.denon.html
# source/components/media_player.firetv.html
# source/components/media_player.itunes.html
# source/components/media_player.kodi.html
# source/components/media_player.mpd.html
# source/components/media_player.plex.html
# source/components/media_player.sonos.html
# source/components/media_player.squeezebox.html
# source/components/modbus.html
# source/components/mqtt.html
# source/components/notify.html
# source/components/notify.file.html
# source/components/notify.instapush.html
# source/components/notify.nma.html
# source/components/notify.pushbullet.html
# source/components/notify.pushover.html
# source/components/notify.slack.html
# source/components/notify.smtp.html
# source/components/notify.syslog.html
# source/components/notify.telegram.html
# source/components/notify.xmpp.html
# source/components/rfxtrx.html
# source/components/scene.html
# source/components/script.html
# source/components/sensor.html
# source/components/sensor.arduino.html
# source/components/sensor.arest.html
# source/components/sensor.bitcoin.html
# source/components/sensor.command_sensor.html
# source/components/sensor.cpuspeed.html
# source/components/sensor.dht.html
# source/components/sensor.efergy.html
# source/components/sensor.forecast.html
# source/components/sensor.glances.html
# source/components/sensor.modbus.html
# source/components/sensor.mqtt.html
# source/components/sensor.mysensors.html
# source/components/sensor.openweathermap.html
# source/components/sensor.rest.html
# source/components/sensor.rfxtrx.html
# source/components/sensor.rpi_gpio.html
# source/components/sensor.sabnzbd.html
# source/components/sensor.swiss_public_transport.html
# source/components/sensor.systemmonitor.html
# source/components/sensor.tellstick.html
# source/components/sensor.temper.html
# source/components/sensor.time_date.html
# source/components/sensor.transmission.html
# source/components/sensor.vera.html
# source/components/sensor.wink.html
# source/components/sensor.worldclock.html
# source/components/shell_command.html
# source/components/simple_alarm.html
# source/components/sun.html
# source/components/switch.html
# source/components/switch.arduino.html
# source/components/switch.arest.html
# source/components/switch.command_switch.html
# source/components/switch.edimax.html
# source/components/switch.hikvision.html
# source/components/switch.modbus.html
# source/components/switch.mqtt.html
# source/components/switch.rest.html
# source/components/switch.rfxtrx.html
# source/components/switch.rpi_gpio.html
# source/components/switch.tellstick.html
# source/components/switch.transmission.html
# source/components/switch.vera.html
# source/components/switch.wemo.html
# source/components/switch.wink.html
# source/components/tellstick.html
# source/components/thermostat.html
# source/components/thermostat.heat_control.html
# source/components/thermostat.nest.html
# source/components/thermostat.radiotherm.html
# source/components/vera.html
# source/components/verisure.html
# source/components/wink.html
# source/components/zone.html
# source/components/zwave.html
# source/getting-started/android.html
# source/getting-started/automation.html
# source/getting-started/autostart.html
# source/getting-started/configuration.html
# source/getting-started/devices.html
# source/getting-started/presence-detection.html
# source/getting-started/troubleshooting.html
# source/getting-started/troubleshooting-configuration.html
# source/developers/add_new_platform.html
# source/developers/api.html
# source/developers/architecture.html
# source/developers/creating_components.html
# source/developers/credits.html
# source/developers/frontend.html
# source/developers/python_api.html
# source/developers/rest_api.html
# source/developers/website.html

View File

@ -1,42 +0,0 @@
require './plugins/pygments_code'
module BacktickCodeBlock
AllOptions = /([^\s]+)\s+(.+?)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?/i
LangCaption = /([^\s]+)\s*(.+)?/i
def self.render_code_block(input)
@options = nil
@caption = nil
@lang = nil
@url = nil
@title = nil
input.gsub(/^`{3} *([^\n]+)?\n(.+?)\n`{3}/m) do
@options = $1 || ''
str = $2
if @options =~ AllOptions
@lang = $1
@caption = "<figcaption><span>#{$2}</span><a href='#{$3}'>#{$4 || 'link'}</a></figcaption>"
elsif @options =~ LangCaption
@lang = $1
@caption = "<figcaption><span>#{$2}</span></figcaption>"
end
if str.match(/\A( {4}|\t)/)
str = str.gsub(/^( {4}|\t)/, '')
end
if @lang.nil? || @lang == 'plain'
code = HighlightCode::tableize_code(str.gsub('<','&lt;').gsub('>','&gt;'))
"<figure class='code'>#{@caption}#{code}</figure>"
else
if @lang.include? "-raw"
raw = "``` #{@options.sub('-raw', '')}\n"
raw += str
raw += "\n```\n"
else
code = HighlightCode::highlight(str, @lang)
"<figure class='code'>#{@caption}#{code}</figure>"
end
end
end
end
end

View File

@ -1,82 +0,0 @@
#
# Author: Brandon Mathis
# A full rewrite based on the work of: Josediaz Gonzalez - https://github.com/josegonzalez/josediazgonzalez.com/blob/master/_plugins/blockquote.rb
#
# Outputs a string with a given attribution as a quote
#
# {% blockquote Bobby Willis http://google.com/search?q=pants the search for bobby's pants %}
# Wheeee!
# {% endblockquote %}
# ...
# <blockquote>
# <p>Wheeee!</p>
# <footer>
# <strong>Bobby Willis</strong><cite><a href="http://google.com/search?q=pants">The Search For Bobby's Pants</a>
# </blockquote>
#
require './plugins/titlecase.rb'
module Jekyll
class Blockquote < Liquid::Block
FullCiteWithTitle = /(\S.*)\s+(https?:\/\/)(\S+)\s+(.+)/i
FullCite = /(\S.*)\s+(https?:\/\/)(\S+)/i
AuthorTitle = /([^,]+),([^,]+)/
Author = /(.+)/
def initialize(tag_name, markup, tokens)
@by = nil
@source = nil
@title = nil
if markup =~ FullCiteWithTitle
@by = $1
@source = $2 + $3
@title = $4.titlecase.strip
elsif markup =~ FullCite
@by = $1
@source = $2 + $3
elsif markup =~ AuthorTitle
@by = $1
@title = $2.titlecase.strip
elsif markup =~ Author
@by = $1
end
super
end
def render(context)
quote = paragraphize(super)
author = "<strong>#{@by.strip}</strong>" if @by
if @source
url = @source.match(/https?:\/\/(.+)/)[1].split('/')
parts = []
url.each do |part|
if (parts + [part]).join('/').length < 32
parts << part
end
end
source = parts.join('/')
source << '/&hellip;' unless source == @source
end
if !@source.nil?
cite = " <cite><a href='#{@source}'>#{(@title || source)}</a></cite>"
elsif !@title.nil?
cite = " <cite>#{@title}</cite>"
end
blockquote = if @by.nil?
quote
elsif cite
"#{quote}<footer>#{author + cite}</footer>"
else
"#{quote}<footer>#{author}</footer>"
end
"<blockquote>#{blockquote}</blockquote>"
end
def paragraphize(input)
"<p>#{input.lstrip.rstrip.gsub(/\n\n/, '</p><p>').gsub(/\n/, '<br/>')}</p>"
end
end
end
Liquid::Template.register_tag('blockquote', Jekyll::Blockquote)

View File

@ -1,92 +0,0 @@
# Title: Simple Code Blocks for Jekyll
# Author: Brandon Mathis http://brandonmathis.com
# Description: Write codeblocks with semantic HTML5 <figure> and <figcaption> elements and optional syntax highlighting — all with a simple, intuitive interface.
#
# Syntax:
# {% codeblock [title] [url] [link text] %}
# code snippet
# {% endcodeblock %}
#
# For syntax highlighting, put a file extension somewhere in the title. examples:
# {% codeblock file.sh %}
# code snippet
# {% endcodeblock %}
#
# {% codeblock Time to be Awesome! (awesome.rb) %}
# code snippet
# {% endcodeblock %}
#
# Example:
#
# {% codeblock Got pain? painreleif.sh http://site.com/painreleief.sh Download it! %}
# $ rm -rf ~/PAIN
# {% endcodeblock %}
#
# Output:
#
# <figure class='code'>
# <figcaption><span>Got pain? painrelief.sh</span> <a href="http://site.com/painrelief.sh">Download it!</a>
# <div class="highlight"><pre><code class="sh">
# -- nicely escaped highlighted code --
# </code></pre></div>
# </figure>
#
# Example 2 (no syntax highlighting):
#
# {% codeblock %}
# <sarcasm>Ooooh, sarcasm... How original!</sarcasm>
# {% endcodeblock %}
#
# <figure class='code'>
# <pre><code>&lt;sarcasm> Ooooh, sarcasm... How original!&lt;/sarcasm></code></pre>
# </figure>
#
require './plugins/pygments_code'
require './plugins/raw'
module Jekyll
class CodeBlock < Liquid::Block
CaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?/i
Caption = /(\S[\S\s]*)/
def initialize(tag_name, markup, tokens)
@title = nil
@caption = nil
@filetype = nil
@highlight = true
if markup =~ /\s*lang:(\S+)/i
@filetype = $1
markup = markup.sub(/\s*lang:(\S+)/i,'')
end
if markup =~ CaptionUrlTitle
@file = $1
@caption = "<figcaption><span>#{$1}</span><a href='#{$2}'>#{$3 || 'link'}</a></figcaption>"
elsif markup =~ Caption
@file = $1
@caption = "<figcaption><span>#{$1}</span></figcaption>\n"
end
if @file =~ /\S[\S\s]*\w+\.(\w+)/ && @filetype.nil?
@filetype = $1
end
super
end
def render(context)
output = super
code = super
source = "<figure class='code'>"
source += @caption if @caption
if @filetype
source += "#{HighlightCode::highlight(code, @filetype)}</figure>"
else
source += "#{HighlightCode::tableize_code(code.lstrip.rstrip.gsub(/</,'&lt;'))}</figure>"
end
source = TemplateWrapper::safe_wrap(source)
source = context['pygments_prefix'] + source if context['pygments_prefix']
source = source + context['pygments_suffix'] if context['pygments_suffix']
source
end
end
end
Liquid::Template.register_tag('codeblock', Jekyll::CodeBlock)

View File

@ -1,44 +0,0 @@
require 'json'
class ConfigTag < Liquid::Tag
def initialize(tag_name, options, tokens)
super
options = options.split(' ').map {|i| i.strip }
@key = options.slice!(0)
@tag = nil
@classname = nil
options.each do |option|
@tag = $1 if option =~ /tag:(\S+)/
@classname = $1 if option =~ /classname:(\S+)/
end
end
def render(context)
config_tag(context.registers[:site].config, @key, @tag, @classname)
end
end
def config_tag(config, key, tag=nil, classname=nil)
options = key.split('.').map { |k| config[k] }.last #reference objects with dot notation
tag ||= 'div'
classname ||= key.sub(/_/, '-').sub(/\./, '-')
output = "<#{tag} class='#{classname}'"
if options.respond_to? 'keys'
options.each do |k,v|
unless v.nil?
v = v.join ',' if v.respond_to? 'join'
v = v.to_json if v.respond_to? 'keys'
output += " data-#{k.sub'_','-'}='#{v}'"
end
end
elsif options.respond_to? 'join'
output += " data-value='#{config[key].join(',')}'"
else
output += " data-value='#{config[key]}'"
end
output += "></#{tag}>"
end
Liquid::Template.register_tag('config_tag', ConfigTag)

View File

@ -1,113 +0,0 @@
# Title: Dynamic directories for Jekyll
# Author: Tommy Sullivan http://superawesometommy.com, Robert Park http://exolucere.ca
# Description: The directory tag lets you iterate over files at a particular path. If files conform to the standard Jekyll format, YYYY-MM-DD-file-title, then those attributes will be populated on the yielded file object. The `forloop` object maintains [its usual context](http://wiki.shopify.com/UsingLiquid#For_loops).
#
# Syntax:
#
# {% directory path: path/from/source [reverse] [exclude] %}
# {{ file.url }}
# {{ file.name }}
# {{ file.date }}
# {{ file.slug }}
# {{ file.title }}
# {% enddirectory %}
#
# Options:
#
# - `reverse` - Defaults to 'false', ordering files the same way `ls` does: 0-9A-Za-z.
# - `exclude` - Defaults to '.html$', a Regexp of files to skip.
#
# File Attributes:
#
# - `url` - The absolute path to the published file
# - `name` - The basename
# - `date` - The date extracted from the filename, otherwise the file's creation time
# - `slug` - The basename with date and extension removed
# - `title` - The titlecase'd slug
#
module Jekyll
class DirectoryTag < Liquid::Block
include Convertible
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
attr_accessor :content, :data
def initialize(tag_name, markup, tokens)
attributes = {}
# Parse parameters
markup.scan(Liquid::TagAttributes) do |key, value|
attributes[key] = value
end
@path = attributes['path'] || '.'
@exclude = Regexp.new(attributes['exclude'] || '.html$', Regexp::EXTENDED | Regexp::IGNORECASE)
@rev = attributes['reverse'].nil?
super
end
def render(context)
context.registers[:directory] ||= Hash.new(0)
source_dir = context.registers[:site].source
directory_files = File.join(source_dir, @path, "*")
files = Dir.glob(directory_files).reject{|f| f =~ @exclude }
files.sort! {|x,y| @rev ? x <=> y : y <=> x }
length = files.length
result = []
context.stack do
files.each_with_index do |filename, index|
basename = File.basename(filename)
filepath = [@path, basename] - ['.']
path = filepath.join '/'
url = '/' + filepath.join('/')
m, cats, date, slug, ext = *basename.match(MATCHER)
if m
date = Time.parse(date)
ext = ext
slug = slug
else
date = File.ctime(filename)
ext = basename[/\.[a-z]+$/, 0]
slug = basename.sub(ext, '')
end
context['file'] = {
'date' => date,
'name' => basename,
'slug' => slug,
'url' => url
}
context['forloop'] = {
'name' => 'directory',
'length' => length,
'index' => index + 1,
'index0' => index,
'rindex' => length - index,
'rindex0' => length - index - 1,
'first' => (index == 0),
'last' => (index == length - 1)
}
result << render_all(@nodelist, context)
end
end
result
end
end
end
Liquid::Template.register_tag('directory', Jekyll::DirectoryTag)

View File

@ -1,130 +0,0 @@
# A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers.
# by: Brandon Tilly
# Source URL: https://gist.github.com/1027674
# Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html
#
# Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin
require 'cgi'
require 'digest/md5'
require 'net/https'
require 'uri'
module Jekyll
class GistTag < Liquid::Tag
def initialize(tag_name, text, token)
super
@text = text
@cache_disabled = false
@cache_folder = File.expand_path "../.gist-cache", File.dirname(__FILE__)
FileUtils.mkdir_p @cache_folder
end
def render(context)
if parts = @text.match(/([a-zA-Z\d]*) (.*)/)
gist, file = parts[1].strip, parts[2].strip
else
gist, file = @text.strip, ""
end
if gist.empty?
""
else
script_url = script_url_for gist, file
code = get_cached_gist(gist, file) || get_gist_from_web(gist, file)
html_output_for script_url, code
end
end
def html_output_for(script_url, code)
code = CGI.escapeHTML code
<<-HTML
<div><script src='#{script_url}'></script>
<noscript><pre><code>#{code}</code></pre></noscript></div>
HTML
end
def script_url_for(gist_id, filename)
url = "https://gist.github.com/#{gist_id}.js"
url = "#{url}?file=#{filename}" unless filename.nil? or filename.empty?
url
end
def get_gist_url_for(gist, file)
"https://gist.githubusercontent.com/raw/#{gist}/#{file}"
end
def cache(gist, file, data)
cache_file = get_cache_file_for gist, file
File.open(cache_file, "w") do |io|
io.write data
end
end
def get_cached_gist(gist, file)
return nil if @cache_disabled
cache_file = get_cache_file_for gist, file
File.read cache_file if File.exist? cache_file
end
def get_cache_file_for(gist, file)
bad_chars = /[^a-zA-Z0-9\-_.]/
gist = gist.gsub bad_chars, ''
file = file.gsub bad_chars, ''
md5 = Digest::MD5.hexdigest "#{gist}-#{file}"
File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache"
end
def get_gist_from_web(gist, file)
gist_url = get_gist_url_for(gist, file)
data = get_web_content(gist_url)
locations = Array.new
while (data.code.to_i == 301 || data.code.to_i == 302)
data = handle_gist_redirecting(data)
break if locations.include? data.header['Location']
locations << data.header['Location']
end
if data.code.to_i != 200
raise RuntimeError, "Gist replied with #{data.code} for #{gist_url}"
end
cache(gist, file, data.body) unless @cache_disabled
data.body
end
def handle_gist_redirecting(data)
redirected_url = data.header['Location']
if redirected_url.nil? || redirected_url.empty?
raise ArgumentError, "GitHub replied with a 302 but didn't provide a location in the response headers."
end
get_web_content(redirected_url)
end
def get_web_content(url)
raw_uri = URI.parse url
proxy = ENV['http_proxy']
if proxy
proxy_uri = URI.parse(proxy)
https = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new raw_uri.host, raw_uri.port
else
https = Net::HTTP.new raw_uri.host, raw_uri.port
end
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new raw_uri.request_uri
data = https.request request
end
end
class GistTagNoCache < GistTag
def initialize(tag_name, text, token)
super
@cache_disabled = true
end
end
end
Liquid::Template.register_tag('gist', Jekyll::GistTag)
Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache)

View File

@ -1,24 +0,0 @@
module Jekyll
require 'haml'
class HamlConverter < Converter
safe true
priority :low
def matches(ext)
ext =~ /haml/i
end
def output_ext(ext)
".html"
end
def convert(content)
begin
engine = Haml::Engine.new(content)
engine.render
rescue StandardError => e
puts "!!! HAML Error: " + e.message
end
end
end
end

View File

@ -1,50 +0,0 @@
# Title: Simple Image tag for Jekyll
# Authors: Brandon Mathis http://brandonmathis.com
# Felix Schäfer, Frederic Hemberger
# Description: Easily output images with optional class names, width, height, title and alt attributes
#
# Syntax {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %}
#
# Examples:
# {% img /images/ninja.png Ninja Attack! %}
# {% img left half http://site.com/images/ninja.png Ninja Attack! %}
# {% img left half http://site.com/images/ninja.png 150 150 "Ninja Attack!" "Ninja in attack posture" %}
#
# Output:
# <img src="/images/ninja.png">
# <img class="left half" src="http://site.com/images/ninja.png" title="Ninja Attack!" alt="Ninja Attack!">
# <img class="left half" src="http://site.com/images/ninja.png" width="150" height="150" title="Ninja Attack!" alt="Ninja in attack posture">
#
module Jekyll
class ImageTag < Liquid::Tag
@img = nil
def initialize(tag_name, markup, tokens)
attributes = ['class', 'src', 'width', 'height', 'title']
if markup =~ /(?<class>\S.*\s+)?(?<src>(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?<width>\d+))?(?:\s+(?<height>\d+))?(?<title>\s+.+)?/i
@img = attributes.reduce({}) { |img, attr| img[attr] = $~[attr].strip if $~[attr]; img }
if /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/ =~ @img['title']
@img['title'] = title
@img['alt'] = alt
else
@img['alt'] = @img['title'].gsub!(/"/, '&#34;') if @img['title']
end
@img['class'].gsub!(/"/, '') if @img['class']
end
super
end
def render(context)
if @img
"<img #{@img.collect {|k,v| "#{k}=\"#{v}\"" if v}.join(" ")}>"
else
"Error processing input, expected syntax: {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | \"title text\" [\"alt text\"]] %}"
end
end
end
end
Liquid::Template.register_tag('img', Jekyll::ImageTag)

View File

@ -1,71 +0,0 @@
# Title: Include Code Tag for Jekyll
# Author: Brandon Mathis http://brandonmathis.com
# Description: Import files on your filesystem into any blog post as embedded code snippets with syntax highlighting and a download link.
# Configuration: You can set default import path in _config.yml (defaults to code_dir: downloads/code)
#
# Syntax {% include_code path/to/file %}
#
# Example 1:
# {% include_code javascripts/test.js %}
#
# This will import test.js from source/downloads/code/javascripts/test.js
# and output the contents in a syntax highlighted code block inside a figure,
# with a figcaption listing the file name and download link
#
# Example 2:
# You can also include an optional title for the <figcaption>
#
# {% include_code Example 2 javascripts/test.js %}
#
# will output a figcaption with the title: Example 2 (test.js)
#
require './plugins/pygments_code'
require './plugins/raw'
require 'pathname'
module Jekyll
class IncludeCodeTag < Liquid::Tag
def initialize(tag_name, markup, tokens)
@title = nil
@file = nil
if markup.strip =~ /\s*lang:(\S+)/i
@filetype = $1
markup = markup.strip.sub(/lang:\S+/i,'')
end
if markup.strip =~ /(.*)?(\s+|^)(\/*\S+)/i
@title = $1 || nil
@file = $3
end
super
end
def render(context)
code_dir = (context.registers[:site].config['code_dir'].sub(/^\//,'') || 'downloads/code')
code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
file = code_path + @file
if File.symlink?(code_path)
return "Code directory '#{code_path}' cannot be a symlink"
end
unless file.file?
return "File #{file} could not be found"
end
Dir.chdir(code_path) do
code = file.read
@filetype = file.extname.sub('.','') if @filetype.nil?
title = @title ? "#{@title} (#{file.basename})" : file.basename
url = "/#{code_dir}/#{@file}"
source = "<figure class='code'><figcaption><span>#{title}</span> <a href='#{url}'>download</a></figcaption>\n"
source += "#{HighlightCode::highlight(code, @filetype)}</figure>"
TemplateWrapper::safe_wrap(source)
end
end
end
end
Liquid::Template.register_tag('include_code', Jekyll::IncludeCodeTag)

View File

@ -1,40 +0,0 @@
# Title: jsFiddle tag for Jekyll
# Author: Brian Arnold (@brianarn)
# Description:
# Given a jsFiddle shortcode, outputs the jsFiddle iframe code.
# Using 'default' will preserve defaults as specified by jsFiddle.
#
# Syntax: {% jsfiddle shorttag [tabs] [skin] [height] [width] %}
#
# Examples:
#
# Input: {% jsfiddle ccWP7 %}
# Output: <iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/ccWP7/embedded/js,resources,html,css,result/light/"></iframe>
#
# Input: {% jsfiddle ccWP7 js,html,result %}
# Output: <iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/ccWP7/embedded/js,html,result/light/"></iframe>
#
module Jekyll
class JsFiddle < Liquid::Tag
def initialize(tag_name, markup, tokens)
if /(?<fiddle>\w+\/?\d?)(?:\s+(?<sequence>[\w,]+))?(?:\s+(?<skin>\w+))?(?:\s+(?<height>\w+))?(?:\s+(?<width>\w+))?/ =~ markup
@fiddle = fiddle
@sequence = (sequence unless sequence == 'default') || 'js,resources,html,css,result'
@skin = (skin unless skin == 'default') || 'light'
@width = width || '100%'
@height = height || '300px'
end
end
def render(context)
if @fiddle
"<iframe style=\"width: #{@width}; height: #{@height}\" frameborder=\"0\" seamless=\"seamless\" src=\"http://jsfiddle.net/#{@fiddle}/embedded/#{@sequence}/#{@skin}/\"></iframe>"
else
"Error processing input, expected syntax: {% jsfiddle shorttag [tabs] [skin] [height] [width] %}"
end
end
end
end
Liquid::Template.register_tag('jsfiddle', Jekyll::JsFiddle)

View File

@ -1,142 +0,0 @@
#custom filters for Octopress
require './plugins/backtick_code_block'
require 'octopress-hooks'
require 'jekyll-sitemap'
require 'octopress-date-format'
require './plugins/raw'
require 'rubypants'
module OctopressFilters
def self.pre_filter(page)
if page.ext.match('html|textile|markdown|md|haml|slim|xml')
input = BacktickCodeBlock::render_code_block(page.content)
page.content = input.gsub /(<figure.+?>.+?<\/figure>)/m do
TemplateWrapper::safe_wrap($1)
end
end
end
def self.post_filter(page)
if page.ext.match('html|textile|markdown|md|haml|slim|xml')
page.output = TemplateWrapper::unwrap(page.output)
end
page.output = RubyPants.new(page.output).to_html
end
class PageFilters < Octopress::Hooks::Page
def pre_render(page)
OctopressFilters::pre_filter(page)
end
def post_render(page)
OctopressFilters::post_filter(page)
end
end
class PostFilters < Octopress::Hooks::Post
def pre_render(post)
OctopressFilters::pre_filter(post)
end
def post_render(post)
OctopressFilters::post_filter(post)
end
end
end
module OctopressLiquidFilters
# Used on the blog index to split posts on the <!--more--> marker
def excerpt(input)
if input.index(/<!--\s*more\s*-->/i)
input.split(/<!--\s*more\s*-->/i)[0]
else
input
end
end
# Checks for excerpts (helpful for template conditionals)
def has_excerpt(input)
input =~ /<!--\s*more\s*-->/i ? true : false
end
# Summary is used on the Archive pages to return the first block of content from a post.
def summary(input)
if input.index(/\n\n/)
input.split(/\n\n/)[0]
else
input
end
end
# Extracts raw content DIV from template, used for page description as {{ content }}
# contains complete sub-template code on main page level
def raw_content(input)
/<div class="entry-content">(?<content>[\s\S]*?)<\/div>\s*<(footer|\/article)>/ =~ input
return (content.nil?) ? input : content
end
# Escapes CDATA sections in post content
def cdata_escape(input)
input.gsub(/<!\[CDATA\[/, '&lt;![CDATA[').gsub(/\]\]>/, ']]&gt;')
end
# Replaces relative urls with full urls
def expand_urls(input, url='')
url ||= '/'
input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\/>]{1}[^\"'>]*)/ do
$1+url+$3
end
end
# Improved version of Liquid's truncate:
# - Doesn't cut in the middle of a word.
# - Uses typographically correct ellipsis (…) insted of '...'
def truncate(input, length)
if input.length > length && input[0..(length-1)] =~ /(.+)\b.+$/im
$1.strip + ' &hellip;'
else
input
end
end
# Improved version of Liquid's truncatewords:
# - Uses typographically correct ellipsis (…) insted of '...'
def truncatewords(input, length)
truncate = input.split(' ')
if truncate.length > length
truncate[0..length-1].join(' ').strip + ' &hellip;'
else
input
end
end
# Condenses multiple spaces and tabs into a single space
def condense_spaces(input)
input.gsub(/\s{2,}/, ' ')
end
# Removes trailing forward slash from a string for easily appending url segments
def strip_slash(input)
if input =~ /(.+)\/$|^\/$/
input = $1
end
input
end
# Returns a url without the protocol (http://)
def shorthand_url(input)
input.gsub /(https?:\/\/)(\S+)/ do
$2
end
end
# Returns a title cased string based on John Gruber's title case http://daringfireball.net/2008/08/title_case_update
def titlecase(input)
input.titlecase
end
end
Liquid::Template.register_filter OctopressLiquidFilters

View File

@ -1,45 +0,0 @@
#
# Author: Brandon Mathis
# Based on the semantic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/
#
# Outputs a span with a data-pullquote attribute set from the marked pullquote. Example:
#
# {% pullquote %}
# When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
# It is important to note, {" pullquotes are merely visual in presentation and should not appear twice in the text. "} That is why it is prefered
# to use a CSS only technique for styling pullquotes.
# {% endpullquote %}
# ...will output...
# <p>
# <span data-pullquote="pullquotes are merely visual in presentation and should not appear twice in the text.">
# When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
# It is important to note, pullquotes are merely visual in presentation and should not appear twice in the text. This is why a CSS only approach
# for styling pullquotes is prefered.
# </span>
# </p>
#
# {% pullquote left %} will create a left-aligned pullquote instead.
#
# Note: this plugin now creates pullquotes with the class of pullquote-right by default
module Jekyll
class PullquoteTag < Liquid::Block
def initialize(tag_name, markup, tokens)
@align = (markup =~ /left/i) ? "left" : "right"
super
end
def render(context)
output = super
if output =~ /\{"\s*(.+?)\s*"\}/m
@quote = RubyPants.new($1).to_html
"<span class='pullquote-#{@align}' data-pullquote='#{@quote}'>#{output.gsub(/\{"\s*|\s*"\}/, '')}</span>"
else
return "Surround your pullquote like this {\" text to be quoted \"}"
end
end
end
end
Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)

View File

@ -1,45 +0,0 @@
require 'pygments'
require 'fileutils'
require 'digest/md5'
PYGMENTS_CACHE_DIR = File.expand_path('../../.pygments-cache', __FILE__)
FileUtils.mkdir_p(PYGMENTS_CACHE_DIR)
module HighlightCode
def self.highlight(str, lang)
lang = 'ruby' if lang == 'ru'
lang = 'objc' if lang == 'm'
lang = 'perl' if lang == 'pl'
lang = 'yaml' if lang == 'yml'
str = pygments(str, lang).match(/<pre>(.+)<\/pre>/m)[1].to_s.gsub(/ *$/, '') #strip out divs <div class="highlight">
tableize_code(str, lang)
end
def self.pygments(code, lang)
if defined?(PYGMENTS_CACHE_DIR)
path = File.join(PYGMENTS_CACHE_DIR, "#{lang}-#{Digest::MD5.hexdigest(code)}.html")
if File.exist?(path)
highlighted_code = File.read(path)
else
begin
highlighted_code = Pygments.highlight(code, :lexer => lang, :formatter => 'html', :options => {:encoding => 'utf-8', :startinline => true})
rescue MentosError
raise "Pygments can't parse unknown language: #{lang}."
end
File.open(path, 'w') {|f| f.print(highlighted_code) }
end
else
highlighted_code = Pygments.highlight(code, :lexer => lang, :formatter => 'html', :options => {:encoding => 'utf-8', :startinline => true})
end
highlighted_code
end
def self.tableize_code (str, lang = '')
table = '<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers">'
code = ''
str.lines.each_with_index do |line,index|
table += "<span class='line-number'>#{index+1}</span>\n"
code += "<span class='line'>#{line}</span>"
end
table += "</pre></td><td class='code'><pre><code class='#{lang}'>#{code}</code></pre></td></tr></table></div>"
end
end

View File

@ -1,40 +0,0 @@
# Author: Brandon Mathis
# Description: Provides plugins with a method for wrapping and unwrapping input to prevent Markdown and Textile from parsing it.
# Purpose: This is useful for preventing Markdown and Textile from being too aggressive and incorrectly parsing in-line HTML.
module TemplateWrapper
# Wrap input with a <div>
def self.safe_wrap(input)
"<div class='bogus-wrapper'><notextile>#{input}</notextile></div>"
end
# This must be applied after the
def self.unwrap(input)
input.gsub /<div class='bogus-wrapper'><notextile>(.+?)<\/notextile><\/div>/m do
$1
end
end
end
# Author: phaer, https://github.com/phaer
# Source: https://gist.github.com/1020852
# Description: Raw tag for jekyll. Keeps liquid from parsing text betweeen {% raw %} and {% endraw %}
module Jekyll
class RawTag < Liquid::Block
def parse(tokens)
@nodelist ||= []
@nodelist.clear
while token = tokens.shift
if token =~ FullToken
if block_delimiter == $1
end_tag
return
end
end
@nodelist << token if not token.empty?
end
end
end
end
Liquid::Template.register_tag('raw', Jekyll::RawTag)

View File

@ -1,69 +0,0 @@
# Title: Render Partial Tag for Jekyll
# Author: Brandon Mathis http://brandonmathis.com
# Description: Import files on your filesystem into any blog post and render them inline.
# Note: Paths are relative to the source directory, if you import a file with yaml front matter, the yaml will be stripped out.
#
# Syntax {% render_partial path/to/file %}
#
# Example 1:
# {% render_partial about/_bio.markdown %}
#
# This will import source/about/_bio.markdown and render it inline.
# In this example I used an underscore at the beginning of the filename to prevent Jekyll
# from generating an about/bio.html (Jekyll doesn't convert files beginning with underscores)
#
# Example 2:
# {% render_partial ../README.markdown %}
#
# You can use relative pathnames, to include files outside of the source directory.
# This might be useful if you want to have a page for a project's README without having
# to duplicated the contents
#
#
require 'pathname'
require './plugins/octopress_filters'
module Jekyll
class RenderPartialTag < Liquid::Tag
include OctopressFilters
def initialize(tag_name, markup, tokens)
@file = nil
@raw = false
if markup =~ /^(\S+)\s?(\w+)?/
@file = $1.strip
@raw = $2 == 'raw'
end
super
end
def render(context)
file_dir = (context.registers[:site].source || 'source')
file_path = Pathname.new(file_dir).expand_path
file = file_path + @file
unless file.file?
return "File #{file} could not be found"
end
Dir.chdir(file_path) do
contents = file.read
if contents =~ /\A-{3}.+[^\A]-{3}\n(.+)/m
contents = $1.lstrip
end
contents = pre_filter(contents)
if @raw
contents
else
partial = Liquid::Template.parse(contents)
context.stack do
partial.render(context)
end
end
end
end
end
end
Liquid::Template.register_tag('render_partial', Jekyll::RenderPartialTag)

View File

@ -1,489 +0,0 @@
#
# = RubyPants -- SmartyPants ported to Ruby
#
# Ported by Christian Neukirchen <mailto:chneukirchen@gmail.com>
# Copyright (C) 2004 Christian Neukirchen
#
# Incooporates ideas, comments and documentation by Chad Miller
# Copyright (C) 2004 Chad Miller
#
# Original SmartyPants by John Gruber
# Copyright (C) 2003 John Gruber
#
#
# = RubyPants -- SmartyPants ported to Ruby
#
# == Synopsis
#
# RubyPants is a Ruby port of the smart-quotes library SmartyPants.
#
# The original "SmartyPants" is a free web publishing plug-in for
# Movable Type, Blosxom, and BBEdit that easily translates plain ASCII
# punctuation characters into "smart" typographic punctuation HTML
# entities.
#
#
# == Description
#
# RubyPants can perform the following transformations:
#
# * Straight quotes (<tt>"</tt> and <tt>'</tt>) into "curly" quote
# HTML entities
# * Backticks-style quotes (<tt>``like this''</tt>) into "curly" quote
# HTML entities
# * Dashes (<tt>--</tt> and <tt>---</tt>) into en- and em-dash
# entities
# * Three consecutive dots (<tt>...</tt> or <tt>. . .</tt>) into an
# ellipsis entity
#
# This means you can write, edit, and save your posts using plain old
# ASCII straight quotes, plain dashes, and plain dots, but your
# published posts (and final HTML output) will appear with smart
# quotes, em-dashes, and proper ellipses.
#
# RubyPants does not modify characters within <tt><pre></tt>,
# <tt><code></tt>, <tt><kbd></tt>, <tt><math></tt> or
# <tt><script></tt> tag blocks. Typically, these tags are used to
# display text where smart quotes and other "smart punctuation" would
# not be appropriate, such as source code or example markup.
#
#
# == Backslash Escapes
#
# If you need to use literal straight quotes (or plain hyphens and
# periods), RubyPants accepts the following backslash escape sequences
# to force non-smart punctuation. It does so by transforming the
# escape sequence into a decimal-encoded HTML entity:
#
# \\ \" \' \. \- \`
#
# This is useful, for example, when you want to use straight quotes as
# foot and inch marks: 6'2" tall; a 17" iMac. (Use <tt>6\'2\"</tt>
# resp. <tt>17\"</tt>.)
#
#
# == Algorithmic Shortcomings
#
# One situation in which quotes will get curled the wrong way is when
# apostrophes are used at the start of leading contractions. For
# example:
#
# 'Twas the night before Christmas.
#
# In the case above, RubyPants will turn the apostrophe into an
# opening single-quote, when in fact it should be a closing one. I
# don't think this problem can be solved in the general case--every
# word processor I've tried gets this wrong as well. In such cases,
# it's best to use the proper HTML entity for closing single-quotes
# ("<tt>&#8217;</tt>") by hand.
#
#
# == Bugs
#
# To file bug reports or feature requests (except see above) please
# send email to: mailto:chneukirchen@gmail.com
#
# If the bug involves quotes being curled the wrong way, please send
# example text to illustrate.
#
#
# == Authors
#
# John Gruber did all of the hard work of writing this software in
# Perl for Movable Type and almost all of this useful documentation.
# Chad Miller ported it to Python to use with Pyblosxom.
#
# Christian Neukirchen provided the Ruby port, as a general-purpose
# library that follows the *Cloth API.
#
#
# == Copyright and License
#
# === SmartyPants license:
#
# Copyright (c) 2003 John Gruber
# (http://daringfireball.net)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name "SmartyPants" nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# This software is provided by the copyright holders and contributors
# "as is" and any express or implied warranties, including, but not
# limited to, the implied warranties of merchantability and fitness
# for a particular purpose are disclaimed. In no event shall the
# copyright owner or contributors be liable for any direct, indirect,
# incidental, special, exemplary, or consequential damages (including,
# but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict
# liability, or tort (including negligence or otherwise) arising in
# any way out of the use of this software, even if advised of the
# possibility of such damage.
#
# === RubyPants license
#
# RubyPants is a derivative work of SmartyPants and smartypants.py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# This software is provided by the copyright holders and contributors
# "as is" and any express or implied warranties, including, but not
# limited to, the implied warranties of merchantability and fitness
# for a particular purpose are disclaimed. In no event shall the
# copyright owner or contributors be liable for any direct, indirect,
# incidental, special, exemplary, or consequential damages (including,
# but not limited to, procurement of substitute goods or services;
# loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict
# liability, or tort (including negligence or otherwise) arising in
# any way out of the use of this software, even if advised of the
# possibility of such damage.
#
#
# == Links
#
# John Gruber:: http://daringfireball.net
# SmartyPants:: http://daringfireball.net/projects/smartypants
#
# Chad Miller:: http://web.chad.org
#
# Christian Neukirchen:: http://kronavita.de/chris
#
class RubyPants < String
# Create a new RubyPants instance with the text in +string+.
#
# Allowed elements in the options array:
#
# 0 :: do nothing
# 1 :: enable all, using only em-dash shortcuts
# 2 :: enable all, using old school en- and em-dash shortcuts (*default*)
# 3 :: enable all, using inverted old school en and em-dash shortcuts
# -1 :: stupefy (translate HTML entities to their ASCII-counterparts)
#
# If you don't like any of these defaults, you can pass symbols to change
# RubyPants' behavior:
#
# <tt>:quotes</tt> :: quotes
# <tt>:backticks</tt> :: backtick quotes (``double'' only)
# <tt>:allbackticks</tt> :: backtick quotes (``double'' and `single')
# <tt>:dashes</tt> :: dashes
# <tt>:oldschool</tt> :: old school dashes
# <tt>:inverted</tt> :: inverted old school dashes
# <tt>:ellipses</tt> :: ellipses
# <tt>:convertquotes</tt> :: convert <tt>&quot;</tt> entities to
# <tt>"</tt> for Dreamweaver users
# <tt>:stupefy</tt> :: translate RubyPants HTML entities
# to their ASCII counterparts.
#
def initialize(string, options=[2])
super string
@options = [*options]
end
# Apply SmartyPants transformations.
def to_html
do_quotes = do_backticks = do_dashes = do_ellipses = do_stupify = nil
convert_quotes = false
if @options.include? 0
# Do nothing.
return self
elsif @options.include? 1
# Do everything, turn all options on.
do_quotes = do_backticks = do_ellipses = true
do_dashes = :normal
elsif @options.include? 2
# Do everything, turn all options on, use old school dash shorthand.
do_quotes = do_backticks = do_ellipses = true
do_dashes = :oldschool
elsif @options.include? 3
# Do everything, turn all options on, use inverted old school
# dash shorthand.
do_quotes = do_backticks = do_ellipses = true
do_dashes = :inverted
elsif @options.include?(-1)
do_stupefy = true
else
do_quotes = @options.include? :quotes
do_backticks = @options.include? :backticks
do_backticks = :both if @options.include? :allbackticks
do_dashes = :normal if @options.include? :dashes
do_dashes = :oldschool if @options.include? :oldschool
do_dashes = :inverted if @options.include? :inverted
do_ellipses = @options.include? :ellipses
convert_quotes = @options.include? :convertquotes
do_stupefy = @options.include? :stupefy
end
# Parse the HTML
tokens = tokenize
# Keep track of when we're inside <pre> or <code> tags.
in_pre = false
# Here is the result stored in.
result = ""
# This is a cheat, used to get some context for one-character
# tokens that consist of just a quote char. What we do is remember
# the last character of the previous text token, to use as context
# to curl single- character quote tokens correctly.
prev_token_last_char = nil
tokens.each { |token|
if token.first == :tag
result << token[1]
if token[1] =~ %r!<(/?)(?:pre|code|kbd|script|math)[\s>]!
in_pre = ($1 != "/") # Opening or closing tag?
end
else
t = token[1]
# Remember last char of this token before processing.
last_char = t[-1].chr
unless in_pre
t = process_escapes t
t.gsub!(/&quot;/, '"') if convert_quotes
if do_dashes
t = educate_dashes t if do_dashes == :normal
t = educate_dashes_oldschool t if do_dashes == :oldschool
t = educate_dashes_inverted t if do_dashes == :inverted
end
t = educate_ellipses t if do_ellipses
# Note: backticks need to be processed before quotes.
if do_backticks
t = educate_backticks t
t = educate_single_backticks t if do_backticks == :both
end
if do_quotes
if t == "'"
# Special case: single-character ' token
if prev_token_last_char =~ /\S/
t = "&#8217;"
else
t = "&#8216;"
end
elsif t == '"'
# Special case: single-character " token
if prev_token_last_char =~ /\S/
t = "&#8221;"
else
t = "&#8220;"
end
else
# Normal case:
t = educate_quotes t
end
end
t = stupefy_entities t if do_stupefy
end
prev_token_last_char = last_char
result << t
end
}
# Done
result
end
protected
# Return the string, with after processing the following backslash
# escape sequences. This is useful if you want to force a "dumb" quote
# or other character to appear.
#
# Escaped are:
# \\ \" \' \. \- \`
#
def process_escapes(str)
str.gsub('\\\\', '&#92;').
gsub('\"', '&#34;').
gsub("\\\'", '&#39;').
gsub('\.', '&#46;').
gsub('\-', '&#45;').
gsub('\`', '&#96;')
end
# The string, with each instance of "<tt>--</tt>" translated to an
# em-dash HTML entity.
#
def educate_dashes(str)
str.gsub(/--/, '&#8212;')
end
# The string, with each instance of "<tt>--</tt>" translated to an
# en-dash HTML entity, and each "<tt>---</tt>" translated to an
# em-dash HTML entity.
#
def educate_dashes_oldschool(str)
str.gsub(/---/, '&#8212;').gsub(/--/, '&#8211;')
end
# Return the string, with each instance of "<tt>--</tt>" translated
# to an em-dash HTML entity, and each "<tt>---</tt>" translated to
# an en-dash HTML entity. Two reasons why: First, unlike the en- and
# em-dash syntax supported by +educate_dashes_oldschool+, it's
# compatible with existing entries written before SmartyPants 1.1,
# back when "<tt>--</tt>" was only used for em-dashes. Second,
# em-dashes are more common than en-dashes, and so it sort of makes
# sense that the shortcut should be shorter to type. (Thanks to
# Aaron Swartz for the idea.)
#
def educate_dashes_inverted(str)
str.gsub(/---/, '&#8211;').gsub(/--/, '&#8212;')
end
# Return the string, with each instance of "<tt>...</tt>" translated
# to an ellipsis HTML entity. Also converts the case where there are
# spaces between the dots.
#
def educate_ellipses(str)
str.gsub('...', '&#8230;').gsub('. . .', '&#8230;')
end
# Return the string, with "<tt>``backticks''</tt>"-style single quotes
# translated into HTML curly quote entities.
#
def educate_backticks(str)
str.gsub("``", '&#8220;').gsub("''", '&#8221;')
end
# Return the string, with "<tt>`backticks'</tt>"-style single quotes
# translated into HTML curly quote entities.
#
def educate_single_backticks(str)
str.gsub("`", '&#8216;').gsub("'", '&#8217;')
end
# Return the string, with "educated" curly quote HTML entities.
#
def educate_quotes(str)
punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
str = str.dup
# Special case if the very first character is a quote followed by
# punctuation at a non-word-break. Close the quotes by brute
# force:
str.gsub!(/^'(?=#{punct_class}\B)/, '&#8217;')
str.gsub!(/^"(?=#{punct_class}\B)/, '&#8221;')
# Special case for double sets of quotes, e.g.:
# <p>He said, "'Quoted' words in a larger quote."</p>
str.gsub!(/"'(?=\w)/, '&#8220;&#8216;')
str.gsub!(/'"(?=\w)/, '&#8216;&#8220;')
# Special case for decade abbreviations (the '80s):
str.gsub!(/'(?=\d\ds)/, '&#8217;')
close_class = %![^\ \t\r\n\\[\{\(\-]!
dec_dashes = '&#8211;|&#8212;'
# Get most opening single quotes:
str.gsub!(/(\s|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];)'(?=\w)/,
'\1&#8216;')
# Single closing quotes:
str.gsub!(/(#{close_class})'/, '\1&#8217;')
str.gsub!(/'(\s|s\b|$)/, '&#8217;\1')
# Any remaining single quotes should be opening ones:
str.gsub!(/'/, '&#8216;')
# Get most opening double quotes:
str.gsub!(/(\s|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];)"(?=\w)/,
'\1&#8220;')
# Double closing quotes:
str.gsub!(/(#{close_class})"/, '\1&#8221;')
str.gsub!(/"(\s|s\b|$)/, '&#8221;\1')
# Any remaining quotes should be opening ones:
str.gsub!(/"/, '&#8220;')
str
end
# Return the string, with each RubyPants HTML entity translated to
# its ASCII counterpart.
#
# Note: This is not reversible (but exactly the same as in SmartyPants)
#
def stupefy_entities(str)
str.
gsub(/&#8211;/, '-'). # en-dash
gsub(/&#8212;/, '--'). # em-dash
gsub(/&#8216;/, "'"). # open single quote
gsub(/&#8217;/, "'"). # close single quote
gsub(/&#8220;/, '"'). # open double quote
gsub(/&#8221;/, '"'). # close double quote
gsub(/&#8230;/, '...') # ellipsis
end
# Return an array of the tokens comprising the string. Each token is
# either a tag (possibly with nested, tags contained therein, such
# as <tt><a href="<MTFoo>"></tt>, or a run of text between
# tags. Each element of the array is a two-element array; the first
# is either :tag or :text; the second is the actual value.
#
# Based on the <tt>_tokenize()</tt> subroutine from Brad Choate's
# MTRegex plugin. <http://www.bradchoate.com/past/mtregex.php>
#
# This is actually the easier variant using tag_soup, as used by
# Chad Miller in the Python port of SmartyPants.
#
def tokenize
tag_soup = /([^<]*)(<[^>]*>)/
tokens = []
prev_end = 0
scan(tag_soup) {
tokens << [:text, $1] if $1 != ""
tokens << [:tag, $2]
prev_end = $~.end(0)
}
if prev_end < size
tokens << [:text, self[prev_end..-1]]
end
tokens
end
end

View File

@ -1,56 +0,0 @@
# Title: Simple Video tag for Jekyll
# Author: Brandon Mathis http://brandonmathis.com
# Description: Easily output MPEG4 HTML5 video with a flash backup.
#
# Syntax {% video url/to/video [width height] [url/to/poster] %}
#
# Example:
# {% video http://site.com/video.mp4 720 480 http://site.com/poster-frame.jpg %}
#
# Output:
# <video width='720' height='480' preload='none' controls poster='http://site.com/poster-frame.jpg'>
# <source src='http://site.com/video.mp4' type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'/>
# </video>
#
module Jekyll
class VideoTag < Liquid::Tag
@video = nil
@poster = ''
@height = ''
@width = ''
def initialize(tag_name, markup, tokens)
if markup =~ /(https?:\S+)(\s+(https?:\S+))?(\s+(https?:\S+))?(\s+(\d+)\s(\d+))?(\s+(https?:\S+))?/i
@video = [$1, $3, $5].compact
@width = $7
@height = $8
@poster = $10
end
super
end
def render(context)
output = super
type = {
'mp4' => "type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'",
'ogv' => "type='video/ogg; codecs=theora, vorbis'",
'webm' => "type='video/webm; codecs=vp8, vorbis'"
}
if @video.size > 0
video = "<video width='#{@width}' height='#{@height}' preload='none' controls poster='#{@poster}'>"
@video.each do |v|
t = v.match(/([^\.]+)$/)[1]
video += "<source src='#{v}' #{type[t]}>"
end
video += "</video>"
else
"Error processing input, expected syntax: {% video url/to/video [url/to/video] [url/to/video] [width height] [url/to/poster] %}"
end
end
end
end
Liquid::Template.register_tag('video', Jekyll::VideoTag)

View File

@ -2,7 +2,7 @@
@import "partials/navigation";
@import "partials/blog";
@import "partials/sharing";
@import "partials/syntax";
// @import "partials/syntax";
@import "partials/archive";
@import "partials/sidebar";
@import "partials/footer";

144
sass/custom/_coderay.scss Normal file
View File

@ -0,0 +1,144 @@
code {
background: #fff;
font-size: .8em;
line-height: 1.5em;
color: #555;
border: 1px solid #ddd;
@include border-radius(.4em);
padding: 0 .3em;
}
.CodeRay {
background-color: #FFF;
border: 1px solid #CCC;
font-family: Monaco, "Courier New", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", monospace;
color: #000;
padding: 1em 0px 1em 1em;
font-size: 12px;
margin-bottom: 16px;
}
.CodeRay pre {
margin: 0px;
}
div.CodeRay { }
span.CodeRay { white-space: pre; border: 0px; padding: 2px }
table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px }
table.CodeRay td {
padding: 1em 0.5em;
vertical-align: top;
}
.CodeRay .line-numbers, .CodeRay .no {
background-color: #ECECEC;
color: #AAA;
text-align: right;
}
.CodeRay .line-numbers a {
color: #AAA;
}
.CodeRay .line-numbers tt { font-weight: bold }
.CodeRay .line-numbers .highlighted { color: red }
.CodeRay .line { display: block; float: left; width: 100%; }
.CodeRay span.line-numbers { padding: 0px 4px }
.CodeRay .code { width: 100% }
ol.CodeRay { font-size: 10pt }
ol.CodeRay li { white-space: pre }
.CodeRay .code pre { overflow: auto }
.CodeRay .debug { color:white ! important; background:blue ! important; }
.CodeRay .annotation { color:#007 }
.CodeRay .attribute-name { color:#f08 }
.CodeRay .attribute-value { color:#700 }
.CodeRay .binary { color:#509; font-weight:bold }
.CodeRay .comment { color:#998; font-style: italic;}
.CodeRay .char { color:#04D }
.CodeRay .char .content { color:#04D }
.CodeRay .char .delimiter { color:#039 }
.CodeRay .class { color:#458; font-weight:bold }
.CodeRay .complex { color:#A08; font-weight:bold }
.CodeRay .constant { color:teal; }
.CodeRay .color { color:#0A0 }
.CodeRay .class-variable { color:#369 }
.CodeRay .decorator { color:#B0B; }
.CodeRay .definition { color:#099; font-weight:bold }
.CodeRay .directive { color:#088; font-weight:bold }
.CodeRay .delimiter { color:black }
.CodeRay .doc { color:#970 }
.CodeRay .doctype { color:#34b }
.CodeRay .doc-string { color:#D42; font-weight:bold }
.CodeRay .escape { color:#666; font-weight:bold }
.CodeRay .entity { color:#800; font-weight:bold }
.CodeRay .error { color:#F00; background-color:#FAA }
.CodeRay .exception { color:#C00; font-weight:bold }
.CodeRay .filename { color:#099; }
.CodeRay .function { color:#900; font-weight:bold }
.CodeRay .global-variable { color:teal; font-weight:bold }
.CodeRay .hex { color:#058; font-weight:bold }
.CodeRay .integer { color:#099; }
.CodeRay .include { color:#B44; font-weight:bold }
.CodeRay .inline { color: black }
.CodeRay .inline .inline { background: #ccc }
.CodeRay .inline .inline .inline { background: #bbb }
.CodeRay .inline .inline-delimiter { color: #D14; }
.CodeRay .inline-delimiter { color: #D14; }
.CodeRay .important { color:#f00; }
.CodeRay .interpreted { color:#B2B; font-weight:bold }
.CodeRay .instance-variable { color:teal }
.CodeRay .label { color:#970; font-weight:bold }
.CodeRay .local-variable { color:#963 }
.CodeRay .octal { color:#40E; font-weight:bold }
.CodeRay .operator { }
.CodeRay .predefined-constant { font-weight:bold }
.CodeRay .predefined { color:#369; font-weight:bold }
.CodeRay .preprocessor { color:#579; }
.CodeRay .pseudo-class { color:#00C; font-weight:bold }
.CodeRay .predefined-type { color:#074; font-weight:bold }
.CodeRay .reserved, .keyword { color:#000; font-weight:bold }
.CodeRay .key { color: #808; }
.CodeRay .key .delimiter { color: #606; }
.CodeRay .key .char { color: #80f; }
.CodeRay .value { color: #088; }
.CodeRay .regexp { background-color:#fff0ff }
.CodeRay .regexp .content { color:#808 }
.CodeRay .regexp .delimiter { color:#404 }
.CodeRay .regexp .modifier { color:#C2C }
.CodeRay .regexp .function { color:#404; font-weight: bold }
.CodeRay .string { color: #D20; }
.CodeRay .string .string { }
.CodeRay .string .string .string { background-color:#ffd0d0 }
.CodeRay .string .content { color: #D14; }
.CodeRay .string .char { color: #D14; }
.CodeRay .string .delimiter { color: #D14; }
.CodeRay .shell { color:#D14 }
.CodeRay .shell .content { }
.CodeRay .shell .delimiter { color:#D14 }
.CodeRay .symbol { color:#990073 }
.CodeRay .symbol .content { color:#A60 }
.CodeRay .symbol .delimiter { color:#630 }
.CodeRay .tag { color:#070 }
.CodeRay .tag-special { color:#D70; font-weight:bold }
.CodeRay .type { color:#339; font-weight:bold }
.CodeRay .variable { color:#036 }
.CodeRay .insert { background: #afa; }
.CodeRay .delete { background: #faa; }
.CodeRay .change { color: #aaf; background: #007; }
.CodeRay .head { color: #f8f; background: #505 }
.CodeRay .insert .insert { color: #080; font-weight:bold }
.CodeRay .delete .delete { color: #800; font-weight:bold }
.CodeRay .change .change { color: #66f; }
.CodeRay .head .head { color: #f4f; }

View File

@ -16,14 +16,18 @@
}
.front-install {
border: none;
font-size: 1em;
background-color: #333;
margin-bottom: 16px;
display: inline-block;
padding: 8px;
color: #DDD;
.sh {
div:before {
content: '$';
color: #c82829;
margin-right: 6px;
}
}
}

View File

@ -1,333 +1,333 @@
// This file is just a butchered version fo the one included in the default Octopress theme.
// It could most definitely do with some cleaning up in the future.
// // This file is just a butchered version fo the one included in the default Octopress theme.
// // It could most definitely do with some cleaning up in the future.
@mixin selection($bg, $color: inherit, $text-shadow: none){
* {
&::-moz-selection { background: $bg; color: $color; text-shadow: $text-shadow; }
&::-webkit-selection { background: $bg; color: $color; text-shadow: $text-shadow; }
&::selection { background: $bg; color: $color; text-shadow: $text-shadow; }
}
}
// @mixin selection($bg, $color: inherit, $text-shadow: none){
// * {
// &::-moz-selection { background: $bg; color: $color; text-shadow: $text-shadow; }
// &::-webkit-selection { background: $bg; color: $color; text-shadow: $text-shadow; }
// &::selection { background: $bg; color: $color; text-shadow: $text-shadow; }
// }
// }
$base03: #002b36 !default; //darkest blue
$base02: #073642 !default; //dark blue
$base01: #586e75 !default; //darkest gray
$base00: #657b83 !default; //dark gray
$base0: #839496 !default; //medium gray
$base1: #93a1a1 !default; //medium light gray
$base2: #eee8d5 !default; //cream
$base3: #fdf6e3 !default; //white
$solar-yellow: #b58900 !default;
$solar-orange: #cb4b16 !default;
$solar-red: #dc322f !default;
$solar-magenta: #d33682 !default;
$solar-violet: #6c71c4 !default;
$solar-blue: #268bd2 !default;
$solar-cyan: #2aa198 !default;
$solar-green: #859900 !default;
// $base03: #002b36 !default; //darkest blue
// $base02: #073642 !default; //dark blue
// $base01: #586e75 !default; //darkest gray
// $base00: #657b83 !default; //dark gray
// $base0: #839496 !default; //medium gray
// $base1: #93a1a1 !default; //medium light gray
// $base2: #eee8d5 !default; //cream
// $base3: #fdf6e3 !default; //white
// $solar-yellow: #b58900 !default;
// $solar-orange: #cb4b16 !default;
// $solar-red: #dc322f !default;
// $solar-magenta: #d33682 !default;
// $solar-violet: #6c71c4 !default;
// $solar-blue: #268bd2 !default;
// $solar-cyan: #2aa198 !default;
// $solar-green: #859900 !default;
$solarized: dark !default;
// $solarized: dark !default;
@if $solarized == light {
// @if $solarized == light {
$_base03: $base03;
$_base02: $base02;
$_base01: $base01;
$_base00: $base00;
$_base0: $base0;
$_base1: $base1;
$_base2: $base2;
$_base3: $base3;
// $_base03: $base03;
// $_base02: $base02;
// $_base01: $base01;
// $_base00: $base00;
// $_base0: $base0;
// $_base1: $base1;
// $_base2: $base2;
// $_base3: $base3;
$base03: $_base3;
$base02: $_base2;
$base01: $_base1;
$base00: $_base0;
$base0: $_base00;
$base1: $_base01;
$base2: $_base02;
$base3: $_base03;
}
// $base03: $_base3;
// $base02: $_base2;
// $base01: $_base1;
// $base00: $_base0;
// $base0: $_base00;
// $base1: $_base01;
// $base2: $_base02;
// $base3: $_base03;
// }
/* non highlighted code colors */
$pre-bg: $base03 !default;
$pre-border: darken($base02, 5) !default;
$pre-color: $base1 !default;
// /* non highlighted code colors */
// $pre-bg: $base03 !default;
// $pre-border: darken($base02, 5) !default;
// $pre-color: $base1 !default;
$noise-bg: image-url('noise.png') top left !default;
$sans: "Helvetica Neue", Arial, sans-serif !default;
$mono: Menlo, Monaco, "Andale Mono", "lucida console", "Courier New", monospace !default;
.sans { font-family: $sans; }
.mono { font-family: $mono; }
// $noise-bg: image-url('noise.png') top left !default;
// $sans: "Helvetica Neue", Arial, sans-serif !default;
// $mono: Menlo, Monaco, "Andale Mono", "lucida console", "Courier New", monospace !default;
// .sans { font-family: $sans; }
// .mono { font-family: $mono; }
.highlight {
table {margin-bottom: 0;}
.gutter, .code {
padding: 0;
}
.gutter {
.line-number {
display: block;
}
}
}
// .highlight {
// table {margin-bottom: 0;}
// .gutter, .code {
// padding: 0;
// }
// .gutter {
// .line-number {
// display: block;
// }
// }
// }
.highlight, html .gist .gist-file .gist-syntax .gist-highlight {
table td.code { width: 100%; }
border: 1px solid $pre-border !important;
}
.highlight .line-numbers, html .gist .gist-file .gist-syntax .highlight .line_numbers {
text-align: right;
font-size: 13px;
line-height: 1.45em;
@if $solarized == light {
background: lighten($base03, 1) $noise-bg !important;
border-right: 1px solid darken($base02, 2) !important;
@include box-shadow(lighten($base03, 2) -1px 0 inset);
text-shadow: lighten($base02, 2) 0 -1px;
} @else {
background: $base02 $noise-bg !important;
border-right: 1px solid darken($base03, 2) !important;
@include box-shadow(lighten($base02, 2) -1px 0 inset);
text-shadow: darken($base02, 10) 0 -1px;
}
span { color: $base01 !important; }
padding: .8em !important;
@include border-radius(0);
}
// .highlight, html .gist .gist-file .gist-syntax .gist-highlight {
// table td.code { width: 100%; }
// border: 1px solid $pre-border !important;
// }
// .highlight .line-numbers, html .gist .gist-file .gist-syntax .highlight .line_numbers {
// text-align: right;
// font-size: 13px;
// line-height: 1.45em;
// @if $solarized == light {
// background: lighten($base03, 1) $noise-bg !important;
// border-right: 1px solid darken($base02, 2) !important;
// @include box-shadow(lighten($base03, 2) -1px 0 inset);
// text-shadow: lighten($base02, 2) 0 -1px;
// } @else {
// background: $base02 $noise-bg !important;
// border-right: 1px solid darken($base03, 2) !important;
// @include box-shadow(lighten($base02, 2) -1px 0 inset);
// text-shadow: darken($base02, 10) 0 -1px;
// }
// span { color: $base01 !important; }
// padding: .8em !important;
// @include border-radius(0);
// }
figure.code, .gist-file, pre {
@include box-shadow(rgba(#000, .06) 0 0 10px);
.highlight pre { @include box-shadow(none); }
}
// figure.code, .gist-file, pre {
// @include box-shadow(rgba(#000, .06) 0 0 10px);
// .highlight pre { @include box-shadow(none); }
// }
.gist .highlight, figure.code .highlight {
@include selection(adjust-color($base03, $lightness: 23%, $saturation: -65%), $text-shadow: $base03 0 1px);
}
html .gist .gist-file {
margin-bottom: 1.8em;
position: relative;
border: none;
padding-top: image-height("code_bg.png") !important;
.highlight {
margin-bottom: 0;
}
.gist-syntax {
border-bottom: 0 !important;
background: none !important;
.gist-highlight {
background: $base03 !important;
}
.highlight pre {
@extend .pre-code;
padding: 0;
}
}
.gist-meta {
padding: .6em 0.8em;
border: 1px solid lighten($base02, 2) !important;
color: $base01;
font-size: .7em !important;
@if $solarized == light {
background: lighten($base03, 2) $noise-bg;
border: 1px solid $pre-border !important;
border-top: 1px solid lighten($base03, 2) !important;
} @else {
background: $base02 $noise-bg;
}
@extend .sans;
line-height: 1.5em;
a {
color: mix($base1, $base01) !important;
&:hover { color: $base1 !important; }
}
a[href*='#file'] {
position: absolute; top: 0; left:0; right:-10px;
color: #474747 !important;
@extend .code-title;
&:hover { color: $link-color !important; }
}
a[href*=raw]{
@extend .download-source;
top: .4em;
}
}
}
pre {
background: $pre-bg $noise-bg;
@include border-radius(.4em);
@extend .mono;
border: 1px solid $pre-border;
line-height: 1.45em;
font-size: 13px;
margin-bottom: 2.1em;
padding: .8em 1em;
color: $pre-color;
overflow: auto;
}
h3.filename {
@extend .code-title;
+ pre { @include border-radius(0px); }
}
// .gist .highlight, figure.code .highlight {
// @include selection(adjust-color($base03, $lightness: 23%, $saturation: -65%), $text-shadow: $base03 0 1px);
// }
// html .gist .gist-file {
// margin-bottom: 1.8em;
// position: relative;
// border: none;
// padding-top: image-height("code_bg.png") !important;
// .highlight {
// margin-bottom: 0;
// }
// .gist-syntax {
// border-bottom: 0 !important;
// background: none !important;
// .gist-highlight {
// background: $base03 !important;
// }
// .highlight pre {
// @extend .pre-code;
// padding: 0;
// }
// }
// .gist-meta {
// padding: .6em 0.8em;
// border: 1px solid lighten($base02, 2) !important;
// color: $base01;
// font-size: .7em !important;
// @if $solarized == light {
// background: lighten($base03, 2) $noise-bg;
// border: 1px solid $pre-border !important;
// border-top: 1px solid lighten($base03, 2) !important;
// } @else {
// background: $base02 $noise-bg;
// }
// @extend .sans;
// line-height: 1.5em;
// a {
// color: mix($base1, $base01) !important;
// &:hover { color: $base1 !important; }
// }
// a[href*='#file'] {
// position: absolute; top: 0; left:0; right:-10px;
// color: #474747 !important;
// @extend .code-title;
// &:hover { color: $link-color !important; }
// }
// a[href*=raw]{
// @extend .download-source;
// top: .4em;
// }
// }
// }
// pre {
// background: $pre-bg $noise-bg;
// @include border-radius(.4em);
// @extend .mono;
// border: 1px solid $pre-border;
// line-height: 1.45em;
// font-size: 13px;
// margin-bottom: 2.1em;
// padding: .8em 1em;
// color: $pre-color;
// overflow: auto;
// }
// h3.filename {
// @extend .code-title;
// + pre { @include border-radius(0px); }
// }
p, li {
code {
@extend .mono;
display: inline-block;
white-space: no-wrap;
background: #fff;
font-size: .8em;
line-height: 1.5em;
color: #555;
border: 1px solid #ddd;
@include border-radius(.4em);
padding: 0 .3em;
margin: -1px 0;
}
pre code { font-size: 1em !important; background: none; border: none; }
}
// p, li {
// code {
// @extend .mono;
// display: inline-block;
// white-space: no-wrap;
// background: #fff;
// font-size: .8em;
// line-height: 1.5em;
// color: #555;
// border: 1px solid #ddd;
// @include border-radius(.4em);
// padding: 0 .3em;
// margin: -1px 0;
// }
// pre code { font-size: 1em !important; background: none; border: none; }
// }
.pre-code {
font-family: $mono !important;
overflow: scroll;
overflow-y: hidden;
display: block;
padding: .8em;
overflow-x: auto;
line-height: 1.45em;
background: $base03 $noise-bg !important;
color: $base1 !important;
span { color: $base1 !important; }
span { font-style: normal !important; font-weight: normal !important; }
// .pre-code {
// font-family: $mono !important;
// overflow: scroll;
// overflow-y: hidden;
// display: block;
// padding: .8em;
// overflow-x: auto;
// line-height: 1.45em;
// background: $base03 $noise-bg !important;
// color: $base1 !important;
// span { color: $base1 !important; }
// span { font-style: normal !important; font-weight: normal !important; }
.c { color: $base01 !important; font-style: italic !important; } /* Comment */
.cm { color: $base01 !important; font-style: italic !important; } /* Comment.Multiline */
.cp { color: $base01 !important; font-style: italic !important; } /* Comment.Preproc */
.c1 { color: $base01 !important; font-style: italic !important; } /* Comment.Single */
.cs { color: $base01 !important; font-weight: bold !important; font-style: italic !important; } /* Comment.Special */
.err { color: $solar-red !important; background: none !important; } /* Error */
.k { color: $solar-orange !important; } /* Keyword */
.o { color: $base1 !important; font-weight: bold !important; } /* Operator */
.p { color: $base1 !important; } /* Operator */
.ow { color: $solar-cyan !important; font-weight: bold !important; } /* Operator.Word */
.gd { color: $base1 !important; background-color: mix($solar-red, $base03, 25%) !important; display: inline-block; } /* Generic.Deleted */
.gd .x { color: $base1 !important; background-color: mix($solar-red, $base03, 35%) !important; display: inline-block; } /* Generic.Deleted.Specific */
.ge { color: $base1 !important; font-style: italic !important; } /* Generic.Emph */
//.gr { color: #aa0000 } /* Generic.Error */
.gh { color: $base01 !important; } /* Generic.Heading */
.gi { color: $base1 !important; background-color: mix($solar-green, $base03, 20%) !important; display: inline-block; } /* Generic.Inserted */
.gi .x { color: $base1 !important; background-color: mix($solar-green, $base03, 40%) !important; display: inline-block; } /* Generic.Inserted.Specific */
//.go { color: #888888 } /* Generic.Output */
//.gp { color: #555555 } /* Generic.Prompt */
.gs { color: $base1 !important; font-weight: bold !important; } /* Generic.Strong */
.gu { color: $solar-violet !important; } /* Generic.Subheading */
//.gt { color: #aa0000 } /* Generic.Traceback */
.kc { color: $solar-green !important; font-weight: bold !important; } /* Keyword.Constant */
.kd { color: $solar-blue !important; } /* Keyword.Declaration */
.kp { color: $solar-orange !important; font-weight: bold !important; } /* Keyword.Pseudo */
.kr { color: $solar-magenta !important; font-weight: bold !important; } /* Keyword.Reserved */
.kt { color: $solar-cyan !important; } /* Keyword.Type */
.n { color: $solar-blue !important; }
.na { color: $solar-blue !important; } /* Name.Attribute */
.nb { color: $solar-green !important; } /* Name.Builtin */
.nc { color: $solar-magenta !important;} /* Name.Class */
.no { color: $solar-yellow !important; } /* Name.Constant */
//.ni { color: #800080 } /* Name.Entity */
.nl { color: $solar-green !important; }
.ne { color: $solar-blue !important; font-weight: bold !important; } /* Name.Exception */
.nf { color: $solar-blue !important; font-weight: bold !important; } /* Name.Function */
.nn { color: $solar-yellow !important; } /* Name.Namespace */
.nt { color: $solar-blue !important; font-weight: bold !important; } /* Name.Tag */
.nx { color: $solar-yellow !Important; }
//.bp { color: #999999 } /* Name.Builtin.Pseudo */
//.vc { color: #008080 } /* Name.Variable.Class */
.vg { color: $solar-blue !important; } /* Name.Variable.Global */
.vi { color: $solar-blue !important; } /* Name.Variable.Instance */
.nv { color: $solar-blue !important; } /* Name.Variable */
//.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: $solar-cyan !important; } /* Literal.Number.Float */
.m { color: $solar-cyan !important; } /* Literal.Number */
.mh { color: $solar-cyan !important; } /* Literal.Number.Hex */
.mi { color: $solar-cyan !important; } /* Literal.Number.Integer */
//.mo { color: #009999 } /* Literal.Number.Oct */
.s { color: $solar-cyan !important; } /* Literal.String */
//.sb { color: #d14 } /* Literal.String.Backtick */
//.sc { color: #d14 } /* Literal.String.Char */
.sd { color: $solar-cyan !important; } /* Literal.String.Doc */
.s2 { color: $solar-cyan !important; } /* Literal.String.Double */
.se { color: $solar-red !important; } /* Literal.String.Escape */
//.sh { color: #d14 } /* Literal.String.Heredoc */
.si { color: $solar-blue !important; } /* Literal.String.Interpol */
//.sx { color: #d14 } /* Literal.String.Other */
.sr { color: $solar-cyan !important; } /* Literal.String.Regex */
.s1 { color: $solar-cyan !important; } /* Literal.String.Single */
//.ss { color: #990073 } /* Literal.String.Symbol */
//.il { color: #009999 } /* Literal.Number.Integer.Long */
div { .gd, .gd .x, .gi, .gi .x { display: inline-block; width: 100%; }}
}
// .c { color: $base01 !important; font-style: italic !important; } /* Comment */
// .cm { color: $base01 !important; font-style: italic !important; } /* Comment.Multiline */
// .cp { color: $base01 !important; font-style: italic !important; } /* Comment.Preproc */
// .c1 { color: $base01 !important; font-style: italic !important; } /* Comment.Single */
// .cs { color: $base01 !important; font-weight: bold !important; font-style: italic !important; } /* Comment.Special */
// .err { color: $solar-red !important; background: none !important; } /* Error */
// .k { color: $solar-orange !important; } /* Keyword */
// .o { color: $base1 !important; font-weight: bold !important; } /* Operator */
// .p { color: $base1 !important; } /* Operator */
// .ow { color: $solar-cyan !important; font-weight: bold !important; } /* Operator.Word */
// .gd { color: $base1 !important; background-color: mix($solar-red, $base03, 25%) !important; display: inline-block; } /* Generic.Deleted */
// .gd .x { color: $base1 !important; background-color: mix($solar-red, $base03, 35%) !important; display: inline-block; } /* Generic.Deleted.Specific */
// .ge { color: $base1 !important; font-style: italic !important; } /* Generic.Emph */
// //.gr { color: #aa0000 } /* Generic.Error */
// .gh { color: $base01 !important; } /* Generic.Heading */
// .gi { color: $base1 !important; background-color: mix($solar-green, $base03, 20%) !important; display: inline-block; } /* Generic.Inserted */
// .gi .x { color: $base1 !important; background-color: mix($solar-green, $base03, 40%) !important; display: inline-block; } /* Generic.Inserted.Specific */
// //.go { color: #888888 } /* Generic.Output */
// //.gp { color: #555555 } /* Generic.Prompt */
// .gs { color: $base1 !important; font-weight: bold !important; } /* Generic.Strong */
// .gu { color: $solar-violet !important; } /* Generic.Subheading */
// //.gt { color: #aa0000 } /* Generic.Traceback */
// .kc { color: $solar-green !important; font-weight: bold !important; } /* Keyword.Constant */
// .kd { color: $solar-blue !important; } /* Keyword.Declaration */
// .kp { color: $solar-orange !important; font-weight: bold !important; } /* Keyword.Pseudo */
// .kr { color: $solar-magenta !important; font-weight: bold !important; } /* Keyword.Reserved */
// .kt { color: $solar-cyan !important; } /* Keyword.Type */
// .n { color: $solar-blue !important; }
// .na { color: $solar-blue !important; } /* Name.Attribute */
// .nb { color: $solar-green !important; } /* Name.Builtin */
// .nc { color: $solar-magenta !important;} /* Name.Class */
// .no { color: $solar-yellow !important; } /* Name.Constant */
// //.ni { color: #800080 } /* Name.Entity */
// .nl { color: $solar-green !important; }
// .ne { color: $solar-blue !important; font-weight: bold !important; } /* Name.Exception */
// .nf { color: $solar-blue !important; font-weight: bold !important; } /* Name.Function */
// .nn { color: $solar-yellow !important; } /* Name.Namespace */
// .nt { color: $solar-blue !important; font-weight: bold !important; } /* Name.Tag */
// .nx { color: $solar-yellow !Important; }
// //.bp { color: #999999 } /* Name.Builtin.Pseudo */
// //.vc { color: #008080 } /* Name.Variable.Class */
// .vg { color: $solar-blue !important; } /* Name.Variable.Global */
// .vi { color: $solar-blue !important; } /* Name.Variable.Instance */
// .nv { color: $solar-blue !important; } /* Name.Variable */
// //.w { color: #bbbbbb } /* Text.Whitespace */
// .mf { color: $solar-cyan !important; } /* Literal.Number.Float */
// .m { color: $solar-cyan !important; } /* Literal.Number */
// .mh { color: $solar-cyan !important; } /* Literal.Number.Hex */
// .mi { color: $solar-cyan !important; } /* Literal.Number.Integer */
// //.mo { color: #009999 } /* Literal.Number.Oct */
// .s { color: $solar-cyan !important; } /* Literal.String */
// //.sb { color: #d14 } /* Literal.String.Backtick */
// //.sc { color: #d14 } /* Literal.String.Char */
// .sd { color: $solar-cyan !important; } /* Literal.String.Doc */
// .s2 { color: $solar-cyan !important; } /* Literal.String.Double */
// .se { color: $solar-red !important; } /* Literal.String.Escape */
// //.sh { color: #d14 } /* Literal.String.Heredoc */
// .si { color: $solar-blue !important; } /* Literal.String.Interpol */
// //.sx { color: #d14 } /* Literal.String.Other */
// .sr { color: $solar-cyan !important; } /* Literal.String.Regex */
// .s1 { color: $solar-cyan !important; } /* Literal.String.Single */
// //.ss { color: #990073 } /* Literal.String.Symbol */
// //.il { color: #009999 } /* Literal.Number.Integer.Long */
// div { .gd, .gd .x, .gi, .gi .x { display: inline-block; width: 100%; }}
// }
.highlight, .gist-highlight {
pre { background: none; @include border-radius(0px); border: none; padding: 0; margin-bottom: 0; }
margin-bottom: 1.8em;
background: $base03;
overflow-y: hidden;
overflow-x: auto;
}
// .highlight, .gist-highlight {
// pre { background: none; @include border-radius(0px); border: none; padding: 0; margin-bottom: 0; }
// margin-bottom: 1.8em;
// background: $base03;
// overflow-y: hidden;
// overflow-x: auto;
// }
$solar-scroll-bg: rgba(#fff, .15);
$solar-scroll-thumb: rgba(#fff, .2);
@if $solarized == light {
$solar-scroll-bg: rgba(#000, .15);
$solar-scroll-thumb: rgba(#000, .15);
}
// $solar-scroll-bg: rgba(#fff, .15);
// $solar-scroll-thumb: rgba(#fff, .2);
// @if $solarized == light {
// $solar-scroll-bg: rgba(#000, .15);
// $solar-scroll-thumb: rgba(#000, .15);
// }
pre, .highlight, .gist-highlight {
&::-webkit-scrollbar { height: .5em; background: $solar-scroll-bg; }
&::-webkit-scrollbar-thumb:horizontal { background: $solar-scroll-thumb; -webkit-border-radius: 4px; border-radius: 4px }
}
// pre, .highlight, .gist-highlight {
// &::-webkit-scrollbar { height: .5em; background: $solar-scroll-bg; }
// &::-webkit-scrollbar-thumb:horizontal { background: $solar-scroll-thumb; -webkit-border-radius: 4px; border-radius: 4px }
// }
.highlight code {
@extend .pre-code; background: #000;
}
figure.code {
background: none;
padding: 0;
border: 0;
margin-bottom: 1.5em;
pre { margin-bottom: 0; }
figcaption {
position: relative;
@extend .code-title;
a { @extend .download-source; }
}
.highlight {
margin-bottom: 0;
}
}
// .highlight code {
// @extend .pre-code; background: #000;
// }
// figure.code {
// background: none;
// padding: 0;
// border: 0;
// margin-bottom: 1.5em;
// pre { margin-bottom: 0; }
// figcaption {
// position: relative;
// @extend .code-title;
// a { @extend .download-source; }
// }
// .highlight {
// margin-bottom: 0;
// }
// }
.code-title {
text-align: center;
font-size: 13px;
line-height: 2em;
text-shadow: #cbcccc 0 1px 0;
color: #474747;
font-weight: normal;
margin-bottom: 0;
@include border-radius(5px 5px 0 0);
font-family: "Helvetica Neue", Arial, "Lucida Grande", "Lucida Sans Unicode", Lucida, sans-serif;
background: #aaaaaa image-url("code_bg.png") top repeat-x;
border: 1px solid #565656;
border-top-color: #cbcbcb;
border-left-color: #a5a5a5;
border-right-color: #a5a5a5;
border-bottom: 0;
}
// .code-title {
// text-align: center;
// font-size: 13px;
// line-height: 2em;
// text-shadow: #cbcccc 0 1px 0;
// color: #474747;
// font-weight: normal;
// margin-bottom: 0;
// @include border-radius(5px 5px 0 0);
// font-family: "Helvetica Neue", Arial, "Lucida Grande", "Lucida Sans Unicode", Lucida, sans-serif;
// background: #aaaaaa image-url("code_bg.png") top repeat-x;
// border: 1px solid #565656;
// border-top-color: #cbcbcb;
// border-left-color: #a5a5a5;
// border-right-color: #a5a5a5;
// border-bottom: 0;
// }
.download-source {
position: absolute; right: .8em;
color: #666 !important;
z-index: 1;
font-size: 13px;
text-shadow: #cbcccc 0 1px 0;
padding-left: 3em;
}
// .download-source {
// position: absolute; right: .8em;
// color: #666 !important;
// z-index: 1;
// font-size: 13px;
// text-shadow: #cbcccc 0 1px 0;
// padding-left: 3em;
// }

View File

@ -1,2 +1,3 @@
@import 'oscailte/oscailte';
@import 'custom/paulus';
@import 'custom/coderay';

View File

@ -12,7 +12,7 @@ footer: true
Home Assistant can give you an interface with is similar to a classic alarm system. There are several panels supported:
- [Manual](/components/alarm_control_panel.manual.html)
- [MQTT](/components/alarm_control_panel.mqtt.html)
- [Verisure](/components/verisure.html)
- [Manual](/components/alarm_control_panel.manual/)
- [MQTT](/components/alarm_control_panel.mqtt/)
- [Verisure](/components/verisure/)

View File

@ -12,10 +12,7 @@ ha_category: Alarm
---
This platform enables the possibility to control an MQTT alarm. The alarm will only change state after
receiving the a new state from `state_topic`. If these messages are published with RETAIN flag, the MQTT
alarm will receive an instant state update after subscription and will start with correct state. Otherwise,
the initial state will be `unknown`.
This platform enables the possibility to control an MQTT alarm. The alarm will only change state after receiving the a new state from `state_topic`. If these messages are published with RETAIN flag, the MQTT alarm will receive an instant state update after subscription and will start with correct state. Otherwise, the initial state will be `unknown`.
```yaml
# Example configuration.yaml entry

View File

@ -35,7 +35,7 @@ Configuration variables:
- **port** (*Required*): The port where your board is connected to your Home Assistant host. If you are using an original Arduino the port will be named `ttyACM*`. The exact number can be determined with `ls /dev/ttyACM*`.
```bash
ls /dev/ttyACM*
$ ls /dev/ttyACM*
```
If that is not working, check your `dmesg` or `journalctl -f` output. Keep in mind that Arduino clones are often using a different name for the port (e.g. `/dev/ttyUSB*`).
@ -46,6 +46,6 @@ A word of caution: The Arduino boards are not storing states. This means that wi
## Building on top of the Arduino component
- [Arduino Sensor](/components/sensor.arduino.html)
- [Arduino Switch](/components/switch.arduino.html)
- [Arduino Sensor](/components/sensor.arduino/)
- [Arduino Switch](/components/switch.arduino/)

View File

@ -10,12 +10,9 @@ footer: true
ha_category: Automation
---
This page will go into more detail about the various options the `automation` component offers. If
you haven't yet, read the [getting started page on automation](/getting-started/automation.html).
This page will go into more detail about the various options the `automation` component offers. If you haven't yet, read the [getting started page on automation](/getting-started/automation/).
A configuration section of an automation requires a `trigger` and an `action` section. `condition` and
`condition_type` are optional. To keep this page compact, all following sections will not show the
full configuration but only the relevant part.
A configuration section of an automation requires a `trigger` and an `action` section. `condition` and `condition_type` are optional. To keep this page compact, all following sections will not show the full configuration but only the relevant part.
```yaml
# Example of entry in configuration.yaml
@ -77,13 +74,10 @@ automation:
## {% linkable_title Triggers %}
Triggers are what starts the processing of an automation rule. It is possible to specify multiple
triggers for the same rule. Once a trigger starts, Home Assistant will validate the conditions, if any,
and call the action.
Triggers are what starts the processing of an automation rule. It is possible to specify multiple triggers for the same rule. Once a trigger starts, Home Assistant will validate the conditions, if any, and call the action.
#### {% linkable_title Event trigger %}
Triggers when an event is being processed. Events are the raw building blocks of Home Assistant.
You can match events on just the event name or also require specific event data to be present.
Triggers when an event is being processed. Events are the raw building blocks of Home Assistant. You can match events on just the event name or also require specific event data to be present.
```yaml
automation:
@ -96,8 +90,7 @@ automation:
```
#### {% linkable_title MQTT trigger %}
Triggers when a specific message is received on given topic. Optionally can match on the payload
being sent over the topic.
Triggers when a specific message is received on given topic. Optionally can match on the payload being sent over the topic.
```yaml
automation:
@ -109,8 +102,7 @@ automation:
```
#### {% linkable_title Numeric state trigger %}
On state change of a specified entity, attempts to parse the state as a number and triggers if value
is above and/or below a threshold.
On state change of a specified entity, attempts to parse the state as a number and triggers if value is above and/or below a threshold.
```yaml
automation:
@ -123,6 +115,7 @@ automation:
```
#### {% linkable_title State trigger %}
Triggers when the state of an entity changes. If only entity_id given will match all state changes.
```yaml
@ -136,13 +129,11 @@ automation:
```
<p class='note warning'>
Use quotes around your values for <code>from</code> and <code>to</code> to avoid the YAML parser
interpreting some values as booleans.
Use quotes around your values for `from` and `to` to avoid the YAML parser interpreting values as booleans.
</p>
#### {% linkable_title Sun trigger %}
Trigger when the sun is setting or rising. An optional time offset can be given to have it trigger for
example 45 minutes before sunset, when dusk is setting in.
Trigger when the sun is setting or rising. An optional time offset can be given to have it trigger for example 45 minutes before sunset, when dusk is setting in.
```yaml
automation:
@ -155,10 +146,8 @@ automation:
```
#### {% linkable_title Time trigger %}
Time can be triggered in many ways. The most common is to specify `after` and trigger at a specific
point in time each day. Alternatively, you can also match if the hour, minute or second of the current
time has a specific value. For example, by only setting minutes in the config to 5 it will trigger every
hour when it is 5 minutes past whole. You cannot use `after` together with hour, minute or second.
Time can be triggered in many ways. The most common is to specify `after` and trigger at a specific point in time each day. Alternatively, you can also match if the hour, minute or second of the current time has a specific value. For example, by only setting minutes in the config to 5 it will trigger every hour when it is 5 minutes past whole. You cannot use `after` together with hour, minute or second.
```yaml
automation:
@ -176,16 +165,13 @@ automation:
- sun
```
You can use `weekday` to limit the trigger times to speific days as well (also available in conditions).
Valid values for `weekday` are (`sun`, `mon`, `tue`, `wed`, `thu`, `fri` & `sat`)
You can use `weekday` to limit the trigger times to speific days as well (also available in conditions). Valid values for `weekday` are (`sun`, `mon`, `tue`, `wed`, `thu`, `fri` & `sat`)
The above example will trigger on Saturday and Sunday every hour on the 5 (2:05, 3:05, 4:05, etc).
#### {% linkable_title Zone trigger %}
Zone triggers can trigger when an entity is entering or leaving the zone. For zone automation to work,
you need to have setup a device tracker platform that supports reporting GPS coordinates. Currently
this is limited to the [OwnTracks platform](/components/device_tracker.owntracks.html).
Zone triggers can trigger when an entity is entering or leaving the zone. For zone automation to work, you need to have setup a device tracker platform that supports reporting GPS coordinates. Currently this is limited to the [OwnTracks platform](/components/device_tracker.owntracks/).
```yaml
automation:
@ -199,15 +185,9 @@ automation:
## {% linkable_title Conditions %}
Conditions are an optional part of an automation rule and be used to prevent an action from happening
when triggered. Conditions look very familiar to triggers but are very different. A trigger will look
at events happening at the system while a condition only looks at how the system looks right now.
A trigger can observe that a switch is being turned on. A condition can only see if a switch is on
or off.
Conditions are an optional part of an automation rule and be used to prevent an action from happening when triggered. Conditions look very familiar to triggers but are very different. A trigger will look at events happening at the system while a condition only looks at how the system looks right now. A trigger can observe that a switch is being turned on. A condition can only see if a switch is on or off.
An automation rule can have mulitiple triggers. By default the action will only fire if all conditions
pass. An optional key `condition_type: 'or'` can be set on the automation rule to fire action if any
condition matches. In the example below, the automation would trigger if the time is before 05:00 _OR_ after 20:00.
An automation rule can have mulitiple triggers. By default the action will only fire if all conditions pass. An optional key `condition_type: 'or'` can be set on the automation rule to fire action if any condition matches. In the example below, the automation would trigger if the time is before 05:00 _OR_ after 20:00.
```yaml
automation:
@ -219,16 +199,16 @@ automation:
after: '20:00'
```
If your triggers and conditions are exactly the same, you can use a shortcut to specify conditions.
In this case, triggers that are not valid conditions will be ignored.
If your triggers and conditions are exactly the same, you can use a shortcut to specify conditions. In this case, triggers that are not valid conditions will be ignored.
```yaml
automation:
condition: use_trigger_values
```
#### {% linkable_title Numeric state condition %}
Attempts to parse the state of specified entity as a number and triggers if value is above and/or
below a threshold.
Attempts to parse the state of specified entity as a number and triggers if value is above and/or below a threshold.
```yaml
automation:
@ -241,6 +221,7 @@ automation:
```
#### {% linkable_title State condition %}
Tests if an entity is a specified state.
```yaml
@ -252,8 +233,8 @@ automation:
```
#### {% linkable_title Time condition %}
The time condition can test if it is after a specified time, before a specified time or if it is a
certain day of the week
The time condition can test if it is after a specified time, before a specified time or if it is a certain day of the week
```yaml
automation:
@ -268,12 +249,11 @@ automation:
- fri
```
Valid values for `weekday` are (sun, mon, tue, wed, thu, fri & sat)
Valid values for `weekday` are (`sun`, `mon`, `tue`, `wed`, `thu`, `fri` & `sat`)
#### {% linkable_title Zone condition %}
Zone conditions test if an entity is in a certain zone. For zone automation to work,
you need to have setup a device tracker platform that supports reporting GPS coordinates. Currently
this is limited to the [OwnTracks platform](/components/device_tracker.owntracks.html).
Zone conditions test if an entity is in a certain zone. For zone automation to work, you need to have setup a device tracker platform that supports reporting GPS coordinates. Currently this is limited to the [OwnTracks platform](/components/device_tracker.owntracks/).
```yaml
automation:
@ -285,8 +265,7 @@ automation:
## {% linkable_title Actions %}
When an automation rule fires, it calls a service. For this service you can specify an entity id it
should apply to and optional service parameters (to specify for example the brightness).
When an automation rule fires, it calls a service. For this service you can specify an entity id it should apply to and optional service parameters (to specify for example the brightness).
```yaml
automation:
@ -310,23 +289,19 @@ automation:
message: Something just happened, better take a look!
```
If you want to specify multiple services to be called or include a delay, have a look at the
[script component](/components/script.html). If you want to describe how certain entities should look,
check out the [scene component](/components/scene.html).
If you want to specify multiple services to be called or include a delay, have a look at the [script component](/components/script/). If you want to describe how certain entities should look, check out the [scene component](/components/scene/).
## {% linkable_title Troubleshooting %}
You can verify that your automation rules are being initialized correctly by watching both the realtime
logs and also the logbook. The realtime logs will show the rules being initialized (once for each trigger):
You can verify that your automation rules are being initialized correctly by watching both the realtime logs and also the logbook. The realtime logs will show the rules being initialized (once for each trigger):
```bash
```plain
INFO [homeassistant.components.automation] Initialized rule Rainy Day
INFO [homeassistant.components.automation] Initialized rule Rainy Day
INFO [homeassistant.components.automation] Initialized rule Rainy Day
INFO [homeassistant.components.automation] Initialized rule Rain is over
```
The Logbook component will show a line entry when an automation is triggered. You can look at the
previous entry to determine which trigger in the rule triggered the event.
The Logbook component will show a line entry when an automation is triggered. You can look at the previous entry to determine which trigger in the rule triggered the event.
![Logbook example](/images/components/automation/logbook.png)

View File

@ -15,7 +15,8 @@ The browser component provides a service to open urls in the default browser on
To load this component, add the following lines to your `configuration.yaml`:
```
```yaml
# Example configuration.yaml entry
browser:
```

View File

@ -16,6 +16,7 @@ This component allows you to integrate any IP camera into Home Assistant. It sup
Home Assistant will serve the images via its server, making it possible to view your IP camera's while outside of your network.
As part of the basic support the following features will be provided:
- MJPEG video streaming
- Saving a snapshot
- Recording(JPEG frame capture)

View File

@ -20,6 +20,6 @@ The configurator component allows components to request information from the use
- Input fields can be defined with a description, and optional type
- It will trigger a callback when the button is pressed
The Hue component in [the demo](/demo) and Plex are implemented using the configurator. See [the source of the demo component](https://github.com/balloob/home-assistant/blob/master/homeassistant/components/demo.py#L72) for a simple example.
The Hue component in [the demo](/demo) and Plex are implemented using the configurator. See [the source of the demo component](https://github.com/balloob/home-assistant/blob/master/homeassistant/components/demo.py#L132) for a simple example.
See [the source](https://github.com/balloob/home-assistant/blob/master/homeassistant/components/configurator.py#L39) for more details on how to use the configurator component.

View File

@ -15,7 +15,8 @@ The conversation component can process sentences into commands for Home Assistan
To enable the conversion option in your installation, add the following to your `configuration.yaml` file:
```
```yaml
# Example configuration.yaml entry
conversation:
```

View File

@ -16,7 +16,7 @@ Home Assistant has a built-in component called `device_sun_light_trigger` to hel
* Turn on the lights when people get home after the sun has set
* Turn off the lights when all people leave the house
This component requires the components [sun](/components/sun.html), [device_tracker](/components/device_tracker.html) and [light](/components/light.html) to be enabled.
This component requires the components [sun](/components/sun/), [device_tracker](/components/device_tracker/) and [light](/components/light/) to be enabled.
To enable this component, add the following lines to your `configuration.yaml` file:

View File

@ -39,5 +39,5 @@ Configuration variables:
- **password** (*Required*): The password for your given admin account.
- **home_interval** (*Optional*): If the home_interval is set then the component will not let a device be AWAY if it has been HOME in the last home_interval minutes. This is in addition to the 3 minute wait built into the device_tracker component.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -37,5 +37,5 @@ Configuration variables:
- **username** *Required*: The username of an user with administrative privileges, usually *admin*.
- **password** *Required*: The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -35,4 +35,4 @@ Configuration variables:
- **username** (*Required*: The username of an user with administrative privileges, usually *admin*.
- **password** (*Required*): The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -31,4 +31,4 @@ Configuration variables:
- **username** (*Required*: The username of an user with administrative privileges, usually *admin*.
- **password** (*Required*): The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -11,7 +11,7 @@ logo: openwrt.png
ha_category: Presence Detection
---
_This is one of the two ways we support OpenWRT. If you encounter problems, try [ubus](/components/device_tracker.ubus.html)._
_This is one of the two ways we support OpenWRT. If you encounter problems, try [ubus](/components/device_tracker.ubus/)._
This is a presence detection scanner for OpenWRT using [luci](http://wiki.openwrt.org/doc/techref/luci).
@ -36,4 +36,4 @@ Configuration variables:
- **username** (*Required*): The username of an user with administrative privileges, usually *admin*.
- **password** (*Required*): The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -11,7 +11,7 @@ footer: true
Home Assistant can get information from your wireless router to track which devices are connected. Please check the sidebar for a list of brands of supported wireless routers.
There are also trackers available which uses different technologies like [MQTT](/components/mqtt.html) or [nmap](/components/device_tracker.nmap_scanner.html) to scan the network for devices
There are also trackers available which uses different technologies like [MQTT](/components/mqtt/) or [nmap](/components/device_tracker.nmap_scanner/) to scan the network for devices
To get started add the following lines to your `configuration.yaml` (example for Netgear):

View File

@ -12,8 +12,7 @@ ha_category: Presence Detection
---
This platform allows you to detect presence by monitoring an MQTT topic for new locations. To use this
platform, you specify a unique topic for each device.
This platform allows you to detect presence by monitoring an MQTT topic for new locations. To use this platform, you specify a unique topic for each device.
```yaml
# Example configuration.yaml entry

View File

@ -29,4 +29,4 @@ Configuration variables:
- **username** (*Required*: The username of an user with administrative privileges, usually *admin*.
- **password** (*Required*): The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -12,12 +12,9 @@ featured: true
---
As an alternative to the router-based device tracking, it is possible to directly scan the network
for devices by using Nmap. The IP addresses to scan can be specified in any format that Nmap understands,
including the network-prefix notation (`192.168.1.1/24`) and the range notation (`192.168.1.1-255`).
As an alternative to the router-based device tracking, it is possible to directly scan the network for devices by using Nmap. The IP addresses to scan can be specified in any format that Nmap understands, including the network-prefix notation (`192.168.1.1/24`) and the range notation (`192.168.1.1-255`).
If you're on Debian or Ubuntu, you might have to install the packages for arp and nmap. Do so by
running `apt-get install net-tools nmap`.
If you're on Debian or Ubuntu, you might have to install the packages for arp and nmap. Do so by running `apt-get install net-tools nmap`.
```yaml
# Example configuration.yaml entry
@ -27,8 +24,6 @@ device_tracker:
home_interval: 10
```
`home_interval` is an optional value set in minutes. This will be the number of minutes nmap will not
scan this device, assuming it is home, in order to preserve the device battery.
`home_interval` is an optional value set in minutes. This will be the number of minutes nmap will not scan this device, assuming it is home, in order to preserve the device battery.
See the [device tracker component page](/components/device_tracker.html) for instructions how to
configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -13,12 +13,9 @@ featured: true
---
This platform allows you to detect presence using [Owntracks](http://owntracks.org/). OwnTracks allows
users to track their location on Android and iOS phones and publish it to an MQTT broker. This platform
will connect to the broker and monitor for new locations.
This platform allows you to detect presence using [Owntracks](http://owntracks.org/). OwnTracks allows users to track their location on Android and iOS phones and publish it to an MQTT broker. This platform will connect to the broker and monitor for new locations.
This component requires [the MQTT component](/components/mqtt.html) to be set up and works very well
together with [the zone component](/components/zone.html).
This component requires [the MQTT component](/components/mqtt/) to be set up and works very well together with [the zone component](/components/zone/).
To integrate Owntracks in Home Assistant, add the following section to your `configuration.yaml` file:

View File

@ -39,4 +39,4 @@ Configuration variables:
- **baseoid** (*Required*): The OID prefix where wireless client registrations can be found, usually vendor specific. It's advised to use the numerical notation. To find this base OID, check vendor documentation or check the MIB file for your device.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -31,4 +31,4 @@ Configuration variables:
- **username** (*Required*: The username of an user with administrative privileges, usually *admin*.
- **password** (*Required*): The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -30,4 +30,4 @@ Configuration variables:
- **password** (*Required*): The password for your given admin account.
- **http_id** (*Required*): The value can be obtained by logging in to the Tomato admin interface and search for `http_id` in the page source code.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -38,4 +38,4 @@ For Archer C9 models running firmware version 150811 or later please use the enc
5. Type ```document.getElementById("login-password").value;```.
6. Copy the returned value to your Home Assistant configuration as password.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -11,7 +11,7 @@ logo: openwrt.png
ha_category: Presence Detection
---
_This is one of the two ways we support OpenWRT. If you encounter problems, try [luci](/components/device_tracker.luci.html)._
_This is one of the two ways we support OpenWRT. If you encounter problems, try [luci](/components/device_tracker.luci/)._
This is a presence detection scanner for OpenWRT using [ubus](http://wiki.openwrt.org/doc/techref/ubus).
@ -55,4 +55,4 @@ Configuration variables:
- **username** (*Required*): The username of an user with administrative privileges, usually *admin*.
- **password** (*Required*): The password for your given admin account.
See the [device tracker component page](/components/device_tracker.html) for instructions how to configure the people to be tracked.
See the [device tracker component page](/components/device_tracker/) for instructions how to configure the people to be tracked.

View File

@ -28,7 +28,7 @@ To load this component, add the following lines to your `configuration.yaml`:
discovery:
```
If you are developing a new platform, please read [how to make your platform discoverable]({{site_root}}/developers/add_new_platform.html#discovery).
If you are developing a new platform, please read [how to make your platform discoverable]({{site_root}}/developers/add_new_platform/#discovery).
<p class='note warning'>
There is currently a <a href='https://bitbucket.org/al45tair/netifaces/issues/17/dll-fails-to-load-windows-81-64bit'>known issue</a> with running this playform on a 64-bit version of Python.

View File

@ -11,11 +11,9 @@ logo: manything.png
ha_category: Camera
---
[Manything](https://manything.com) is a smart app that turns your iPhone, iPod, or iPad into a wifi
camera for monitoring your home, your pets, anything! Comes with live streaming, motion activated alerts, cloud video recording, and more.
[Manything](https://manything.com) is a smart app that turns your iPhone, iPod, or iPad into a wifi camera for monitoring your home, your pets, anything! Comes with live streaming, motion activated alerts, cloud video recording, and more.
To get manything support, HA will use IFTTT's [Maker Channel](https://ifttt.com/maker) and the [ManyThing Channel](https://ifttt.com/manything).
Use the [IFTTT Setup instructions](/components/ifttt.html) to activate the IFTTT Platform.
To get manything support, HA will use IFTTT's [Maker Channel](https://ifttt.com/maker) and the [ManyThing Channel](https://ifttt.com/manything). Use the [IFTTT Setup instructions](/components/ifttt/) to activate the IFTTT Platform.
After setting up IFTTT, Maker Channel and ManyThing Channel, you can use the following examples to configure Home Assistant.
@ -62,7 +60,7 @@ automation:
<p class='img'>
<img src='/images/components/ifttt/IFTTT_manything_trigger.png' />
You need to setup a unique trigger for each event you sent to IFTTT.
For ManyThing support, you need to set up an <code>on</code> and <code>off</code> event.
For ManyThing support, you need to set up an `on` and `off` event.
</p>
### {% linkable_title Testing your trigger %}

View File

@ -12,10 +12,7 @@ ha_category: Automation
featured: true
---
[IFTTT](https://ifttt.com) is a web service that allows users to create chains of simple conditional
statements, so called "recipes". With the ifttt component you can trigger recipes through the "maker"
channel. See the [announcement blog post](/blog/2015/09/13/home-assistant-meets-ifttt/) for examples
how to use it.
[IFTTT](https://ifttt.com) is a web service that allows users to create chains of simple conditional statements, so called "recipes". With the IFTTT component you can trigger recipes through the "maker" channel. See the [announcement blog post](/blog/2015/09/13/home-assistant-meets-ifttt/) for examples how to use it.
```yaml
# Example configuration.yaml entry
@ -60,10 +57,7 @@ You need to setup a unique trigger for each event you sent to IFTTT.
### {% linkable_title Sending events from IFTTT to Home Assistant %}
To be able to receive events from IFTTT, your Home Assistant instance needs to be accessible from
the web. This can be achieved by forwarding port 8123 from your router to the device running Home
Assistant. If your ISP is giving you a new IP address from time to time, consider using
[DuckDNS][duck-dns].
To be able to receive events from IFTTT, your Home Assistant instance needs to be accessible from the web. This can be achieved by forwarding port 8123 from your router to the device running Home Assistant. If your ISP is giving you a new IP address from time to time, consider using [DuckDNS][duck-dns].
[duck-dns]: https://duckdns.org
@ -72,8 +66,9 @@ Assistant. If your ISP is giving you a new IP address from time to time, conside
</p>
### {% linkable_title Additional Channel Examples %}
Additional examples of using IFTTT channels can be found below.
Channel | Description
----- | -----
[Manything](/components/ifttt.manything.html) | Automates turning recording ON and OFF based on Home Assistant AWAY and HOME values.
[Manything](/components/ifttt.manything/) | Automates turning recording ON and OFF based on Home Assistant AWAY and HOME values.

View File

@ -22,7 +22,7 @@ The `keyboard` component simulates key presses on the host machine. It currently
To load this component, add the following lines to your `configuration.yaml`:
```
```yaml
keyboard:
```
@ -30,8 +30,8 @@ keyboard:
You may need to install platform-specific [dependencies for PyUserInput](https://github.com/SavinaRoja/PyUserInput#dependencies) in order to use the keyboard component. In most cases this can be done by running:
```
pip3 install [package name]
```bash
$ pip3 install [package name]
```
#### {% linkable_title Windows %}

View File

@ -14,7 +14,7 @@ featured: true
Philips Hue support is integrated into Home Assistant as a light platform. The preferred way to setup the Philips Hue platform is by enabling the [the discovery component]({{site_root}}/components/discovery.html).
Philips Hue support is integrated into Home Assistant as a light platform. The preferred way to setup the Philips Hue platform is by enabling the [the discovery component]({{site_root}}/components/discovery/).
If you want to enable the light component directly, add the following lines to your `configuration.yaml`:

View File

@ -18,7 +18,7 @@ It supports the following platforms:
* `hue` for Philips Hue
* `wink` for Wink
Preferred way to setup the Philips Hue platform is through the [the discovery component]({{site_root}}/components/discovery.html). For the Wink light platform enable [the wink component]({{site_root}}/components/wink.html).
Preferred way to setup the Philips Hue platform is through the [the discovery component]({{site_root}}/components/discovery/). For the Wink light platform enable [the wink component]({{site_root}}/components/wink/).
If you want to enable the light component directly, add the following lines to your `configuration.yaml`:
@ -33,7 +33,7 @@ The light component supports multiple entries in <code>configuration.yaml</code>
### Service `light.turn_on`
Turns one light on or multiple lights on using [groups]({{site_root}}/components/group.html).
Turns one light on or multiple lights on using [groups]({{site_root}}/components/group/).
| Service data attribute | Optional | Description |
| ---------------------- | -------- | ----------- |

View File

@ -14,4 +14,4 @@ ha_category: Light
The wink sensor platform allows you to use your [Wink](http://www.wink.com/) lights.
The requirement is that you have setup your [Wink hub](/components/light.wink.html).
The requirement is that you have setup your [Wink hub](/components/light.wink/).

View File

@ -10,10 +10,7 @@ footer: true
ha_category: "History"
---
<img src='/images/screenshots/logbook.png' style='margin-left:10px; float: right;' height="100" />
The logbook component provides a different perspective on the history of your house by showing all
the changes that happened to your house in reverse chronological order.
[See the demo for a live example](/demo/).
<img src='/images/screenshots/logbook.png' style='margin-left:10px; float: right;' height="100" /> The logbook component provides a different perspective on the history of your house by showing all the changes that happened to your house in reverse chronological order. [See the demo for a live example](/demo/).
To enable the logbook in your installation, add the following to your `configuration.yaml` file:

View File

@ -13,7 +13,7 @@ featured: true
---
Google Cast devices will be automatically discovered if you enable [the discovery component]({{site_root}}/components/discovery.html). There is a issue where Chromecasts can only be discovered if your device is connected to the same subnet as your Chromecast.
Google Cast devices will be automatically discovered if you enable [the discovery component]({{site_root}}/components/discovery/). There is a issue where Chromecasts can only be discovered if your device is connected to the same subnet as your Chromecast.
Chromecast platform can also be forced to load by adding the following lines to your `configuration.yaml`:

View File

@ -13,11 +13,9 @@ featured: true
---
The Plex platform allows you to connect a [Plex Media Server](https://plex.tv) to Home Assistant. It will allow you to control media playback and see the current playing item.
The preferred way to setup the Plex platform is by enabling the the [the discovery component]({{site_root}}/components/discovery.html) and requires GDM to be enabled.
If local authentication is enabled or multiple users are defined, HASS requires an authentication token to be entered in the webinterface. See <A TARGET="_new" HREF=https://support.plex.tv/hc/en-us/articles/204059436>Finding your account token / X-Plex-Token</A>.
The Plex platform allows you to connect a [Plex Media Server](https://plex.tv) to Home Assistant. It will allow you to control media playback and see the current playing item. The preferred way to setup the Plex platform is by enabling the the [the discovery component](/components/discovery/) and requires GDM to be enabled.
If local authentication is enabled or multiple users are defined, HASS requires an authentication token to be entered in the webinterface. See [Finding your account token / X-Plex-Token](https://support.plex.tv/hc/en-us/articles/204059436).
If you want to enable the plex platform directly, add the following lines to your `configuration.yaml`:
@ -29,12 +27,12 @@ media_player:
You may also need to create the file `plex.conf`.
```
{'IP_ADDRESS:PORT': {'token': 'TOKEN'}}
```json
{"<IP_ADDRESS>:<PORT>": {"token": "<TOKEN>"}}
```
- **IP_ADDRESS** *Required*: IP address of the Plex Media Server
- **PORT** *required*: Default is 32400
- **TOKEN** *Optional*: Only is authentication is required. Set to `None` (without quotes) otherwise.
- `<IP_ADDRESS>` *Required*: IP address of the Plex Media Server
- `<PORT>` *required*: Default is 32400
- `<TOKEN>` *Optional*: Only if authentication is required. Set to `None` (without quotes) otherwise.
At this moment, the Plex platform only supports one Plex Media Server.

View File

@ -18,6 +18,7 @@ To add modbus to your installation, add the following to your `configuration.yam
For a network connection:
```yaml
#Modbus TCP
modbus:
type: tcp
@ -57,6 +58,6 @@ Configuration variables:
## {% linkable_title Building on top of Modbus %}
- [Modbus Sensor](/components/sensor.modbus.html)
- [Modbus Switch](/components/switch.modbus.html)
- [Modbus Sensor](/components/sensor.modbus/)
- [Modbus Switch](/components/switch.modbus/)

View File

@ -40,14 +40,11 @@ Configuration variables:
## {% linkable_title Picking a broker %}
The MQTT component needs you to run an MQTT broker for Home Assistant to connect to.
There are three options, each with various degrees of ease of setup and privacy.
The MQTT component needs you to run an MQTT broker for Home Assistant to connect to. There are three options, each with various degrees of ease of setup and privacy.
#### {% linkable_title Run your own %}
Most private option but requires a bit more work. There are two free and open-source brokers to pick
from: [Mosquitto](http://mosquitto.org/) and [Mosca](http://www.mosca.io/).
Most private option but requires a bit more work. There are two free and open-source brokers to pick from: [Mosquitto](http://mosquitto.org/) and [Mosca](http://www.mosca.io/).
```yaml
# Example configuration.yaml entry
@ -62,9 +59,7 @@ mqtt:
#### {% linkable_title Public MQTT %}
The Mosquitto project runs a [public broker](http://test.mosquitto.org). Easiest to setup but there
is 0 privacy as all messages are public. Use this only for testing purposes and not for real tracking
of your devices.
The Mosquitto project runs a [public broker](http://test.mosquitto.org). Easiest to setup but there is 0 privacy as all messages are public. Use this only for testing purposes and not for real tracking of your devices.
```yaml
mqtt:
@ -80,9 +75,7 @@ mqtt:
#### {% linkable_title CloudMQTT %}
[CloudMQTT](https://www.cloudmqtt.com) is a hosted private MQTT instance that is free up to 10
connected devices. This is enough to get started with for example
[OwnTracks](/components/device_tracker.owntracks.html) and give you a taste of what is possible.
[CloudMQTT](https://www.cloudmqtt.com) is a hosted private MQTT instance that is free up to 10 connected devices. This is enough to get started with for example [OwnTracks](/components/device_tracker.owntracks/) and give you a taste of what is possible.
<p class='note'>
Home Assistant is not affiliated with CloudMQTT nor will receive any kickbacks.
@ -97,6 +90,7 @@ Home Assistant is not affiliated with CloudMQTT nor will receive any kickbacks.
a. Under manage users, fill in username, password and click add
b. Under ACLs, select user, topic `#`, check 'read access' and 'write access'
5. Copy the instance info to your configuration.yaml:
```yaml
mqtt:
broker: <Server>
@ -106,26 +100,25 @@ Home Assistant is not affiliated with CloudMQTT nor will receive any kickbacks.
```
<p class='note'>
Home Assistant will automatically load the correct certificate if you connect to an encrypted channel
of CloudMQTT (port range 20 000 - 30 000).
Home Assistant will automatically load the correct certificate if you connect to an encrypted channel of CloudMQTT (port range 20 000 - 30 000).
</p>
## {% linkable_title Building on top of MQTT %}
- [MQTT Sensor](/components/sensor.mqtt.html)
- [MQTT Switch](/components/switch.mqtt.html)
- [MQTT Device Tracker](/components/device_tracker.mqtt.html)
- [OwnTracks Device Tracker](/components/device_tracker.owntracks.html)
- [MQTT automation rule](/components/automation.html#mqtt-based-automation)
- [MQTT alarm](/components/alarm_control_panel.mqtt.html)
- Integrating it into a component. See the [MQTT example component](https://github.com/balloob/home-assistant/blob/dev/config/custom_components/mqtt_example.py) how to do this.
- [MQTT Sensor](/components/sensor.mqtt/)
- [MQTT Switch](/components/switch.mqtt/)
- [MQTT Device Tracker](/components/device_tracker.mqtt/)
- [OwnTracks Device Tracker](/components/device_tracker.owntracks/)
- [MQTT automation rule](/components/automation/#mqtt-based-automation)
- [MQTT alarm](/components/alarm_control_panel.mqtt/)
- Integrating it into own component. See the [MQTT example component](https://github.com/balloob/home-assistant/blob/dev/config/custom_components/mqtt_example.py) how to do this.
## {% linkable_title Testing your setup %}
For debugging purposes `mosquitto` is shipping commandline tools to send and recieve MQTT messages. For sending test messages to a broker running on localhost:
```bash
mosquitto_pub -h 127.0.0.1 -t home-assistant/switch/1/on -m "Switch is ON"
$ mosquitto_pub -h 127.0.0.1 -t home-assistant/switch/1/on -m "Switch is ON"
```
Another way to send MQTT messages by hand is to use the "Developer Tools" in the Frontend. Choose "Call Service" and then `mqtt/mqtt_send` under "Available Services". Enter something similar to the example below into the "Service Data" field.
@ -146,5 +139,5 @@ The message should appear on the bus:
For reading all messages sent on the topic `home-assistant` to a broker running on localhost:
```bash
mosquitto_sub -h 127.0.0.1 -v -t "home-assistant/#"
$ mosquitto_sub -h 127.0.0.1 -v -t "home-assistant/#"
```

View File

@ -30,4 +30,4 @@ Configuration variables:
- **filename** (*Required*): Name of the file to use. The file will be created if it doesn't exist and saved in your `config/` folder.
- **timestamp** (*Optional*): Setting `timestamp` to 1 adds a timestamp to every entry.
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -49,4 +49,4 @@ curl -X POST \
```
For further details, please check the [API](https://instapush.im/developer/rest).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -40,4 +40,4 @@ automation:
service_data: {"message":"YAY"}
```
For more automation examples, see the [getting started with automation page]({{site_root}}/components/automation.html).
For more automation examples, see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -31,4 +31,4 @@ Configuration variables:
Details for the API : https://www.notifymyandroid.com/api.jsp
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -30,4 +30,4 @@ Configuration variables:
- **name** (*Optional*): Setting the optional parameter `name` allows multiple notifiers to be created. The default value is `notify`. The notifier will bind to the service `notify.NOTIFIER_NAME`.
- **api_key** (*Required*): Enter the API key for PushBullet. Go to https://www.pushbullet.com/ to retrieve your API key.
For more automation examples, see the [getting started with automation page]({{site_root}}/components/automation.html).
For more automation examples, see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -32,9 +32,9 @@ Configuration variables:
- **user_key** (*Required*): To retrieve this value log into your account at https://pushover.net
This is a quote from the pushover website regarding free/open source apps:
> "If you are creating a client-side library, application, or open source project that will be redistributed and installed by end-users, you may want to require each of your users to register their own application rather than including your own API token with the software."
<blockquote>
If you are creating a client-side library, application, or open source project that will be redistributed and installed by end-users, you may want to require each of your users to register their own application rather than including your own API token with the software.
</blockquote>
When setting up the application you can use this [icon](https://home-assistant.io/images/favicon-192x192.png).
For more automation examples, see the [getting started with automation page]({{site_root}}/components/automation.html).

View File

@ -33,5 +33,5 @@ Configuration variables:
- **api_key** (*Required*): The slack API token to use for sending slack messages. You can get your slack API token here https://api.slack.com/web?sudo=1
- **default_channel** (*Required*): The default channel to post to if no channel is explicitly specified when sending the notification message.
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -51,4 +51,4 @@ Keep in mind that if the password contains a colon, it needs to be wrapped in ap
For Google Mail (smtp.gmail.com) an additional step in the setup process is needed. Google has some extra layers of protection
which need special attention. By default, the usage by external applications, especially scripts, is limited. Visit the [Less secure apps](https://www.google.com/settings/security/lesssecureapps) page and enable it.
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -57,4 +57,4 @@ The table contains values to use in your `configuration.yaml` file.
For details about facility, option, and priority please consult the [wikpedia article](http://en.wikipedia.org/wiki/Syslog) and [RFC 3164](http://tools.ietf.org/html/rfc3164).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -48,4 +48,4 @@ The default value is `notify`. The notifier will bind to the service
- **api_key** (*Required*): The API token of your bot.
- **chat_id** (*Required*: The chat ID of your user.
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -34,4 +34,4 @@ Configuration variables:
All Jabber IDs (JID) must include the domain. Make sure that the password matches the account provided as sender.
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation.html).
To use notifications, please see the [getting started with automation page]({{site_root}}/components/automation/).

View File

@ -10,25 +10,14 @@ footer: true
ha_category: Organization
---
A user can create scenes that capture the states you want certain entities to be. For example a scene
can contain that light A should be turned on and light B should be bright red.
A user can create scenes that capture the states you want certain entities to be. For example a scene can contain that light A should be turned on and light B should be bright red.
A scene is active if all states of the scene match the actual states. An optional `fuzzy_match` option
can be given to allow entities to match if attributes are not exact but are in range of the preferred
state.
If a scene is manually activated it will store the previous state of the entities. These will be
restored when the state is deactivated manually. If one of the enties that are being tracked change
state on its own, the old state will not be restored when it is being deactivated.
Scenes can be activated using the service `scene.turn_on` and deactivated using the service `scene.turn_off`.
Scenes can be activated using the service `scene.turn_on`.
```yaml
# Example configuration.yaml entry
scene:
- name: Romantic
# Optional, allow fuzzy matching number atttributes to check if scene is on
fuzzy_match: 0.2
entities:
light.tv_back_light: on
light.ceiling:

View File

@ -10,8 +10,7 @@ footer: true
ha_category: Automation
---
The script component allows users to create a sequence of service calls and delays. Scripts can be
started using the service `script/turn_on` and interrupted using the service `script/turn_off`.
The script component allows users to create a sequence of service calls and delays. Scripts can be started using the service `script/turn_on` and interrupted using the service `script/turn_off`.
```yaml
# Example configuration.yaml entry

View File

@ -43,7 +43,7 @@ In this section you find some real life examples of how to use this sensor.
There are several ways to get the temperature of your hard drive. A simple solution is to use [hddtemp](https://savannah.nongnu.org/projects/hddtemp/).
```bash
hddtemp -n /dev/sda
$ hddtemp -n /dev/sda
```
To use those information, the entry for a sensor in the `configuration.yaml` file will look like this.
@ -59,8 +59,7 @@ sensor:
### {% linkable_title CPU temperature %}
Thanks to the [`proc`](https://en.wikipedia.org/wiki/Procfs) file system, various details about a system can be retrieved. Here the CPU temperature
is of interest. Add something similar to your `configuration.yaml` file:
Thanks to the [`proc`](https://en.wikipedia.org/wiki/Procfs) file system, various details about a system can be retrieved. Here the CPU temperature is of interest. Add something similar to your `configuration.yaml` file:
```yaml
# Example configuration.yaml entry
@ -75,19 +74,18 @@ The `correction_factor` will make sure that the value is shown in a useful forma
### {% linkable_title Use an external script %}
The example is doing the same as the [aREST sensor](/components/sensor.arest.html) but with an external Python script. It should give you an idea about interacting with devices which are exposing a RESTful API.
The example is doing the same as the [aREST sensor](/components/sensor.arest/) but with an external Python script. It should give you an idea about interacting with devices which are exposing a RESTful API.
The one-line script to retrieve a value is shown below. Of course would it be possible to use this directly in the `configuration.yaml` file but need extra care about the quotation marks.
```python
python3 -c "import requests; print(requests.get('http://10.0.0.48/analog/2').json()['return_value'])"
```bash
$ python3 -c "import requests; print(requests.get('http://10.0.0.48/analog/2').json()['return_value'])"
```
The script (saved as `arest-value.py`) that is used looks like the example below.
```python
#!/usr/bin/python3
#
from requests import get
response = get('http://10.0.0.48/analog/2')
print(response.json()['return_value'])

View File

@ -14,7 +14,7 @@ featured: true
The forecast platform uses the [Forecast.io](https://forecast.io/) web service as a source for meteorological data for your location. The location is based on the Longitude and Latitude cooridinates configured in `configuration.yaml`. The cooridinates are auto detected but to take advantage of the hyper-local weather reported by forecast.io, you can refine them down to your exact home address. GPS cooridinates can be found by using Google Maps and clicking on your home.
You need an API key which is free but requires a [registration](https://developer.forecast.io/register). You can make 1000 requests per day. This means that you could create approximately every 1.4 minute one.
You need an API key which is free but requires a [registration](https://developer.forecast.io/register). You can make 1000 requests per day. This means that you could create one approximately every 1.4 minutes.
To add Forecast.io to your installation, add the following to your `configuration.yaml` file:
@ -59,7 +59,7 @@ Configuration variables:
- **pressure**: The sea-level air pressure in millibars.
- **visibility**: The average visibility.
- **ozone**: The columnar density of total atmospheric ozone in Dobson.
- **units** (*Optional*): Specify the unit system. Default to `si` or `us` based on the temperature preference in Home Assistant. Other options are auto, us, si, ca, and uk2.
- **units** (*Optional*): Specify the unit system. Default to `si` or `us` based on the temperature preference in Home Assistant. Other options are `auto`, `us`, `si`, `ca`, and `uk2`.
`auto` will let forecast.io decide the unit system based on location.
Details about the API are available in the [Forecast.io documentation](https://developer.forecast.io/docs/v2).

View File

@ -35,6 +35,6 @@ Configuration variables:
If you are using an original Arduino the port will be named `ttyACM*`. The exact number can be determined with the command shown below.
```bash
ls /dev/ttyACM*
$ ls /dev/ttyACM*
```

View File

@ -86,7 +86,7 @@ To display the IP address, the entry for a sensor in the `configuration.yaml` fi
### {% linkable_title Single value from a local Glances instance %}
The [glances](/components/sensor.glances.html) sensor is doing the exact same thing for all exposed values.
The [glances](/components/sensor.glances/) sensor is doing the exact same thing for all exposed values.
Add something similar to the entry below to your `configuration.yaml` file:

View File

@ -14,5 +14,5 @@ ha_category: Sensor
The wink sensor platform allows you to get data from your [Wink](http://www.wink.com/) sensors.
The requirement is that you have setup your [Wink hub](/components/light.wink.html).
The requirement is that you have setup your [Wink hub](/components/light.wink/).

View File

@ -10,9 +10,7 @@ footer: true
ha_category: Automation
---
This component can expose regular shell commands as services. Services can be called from a script
or in automation.
This component can expose regular shell commands as services. Services can be called from a script or in automation.
```yaml
# Example configuration.yaml entry

View File

@ -11,9 +11,9 @@ ha_category: Alarm
---
The component `simple_alarm` is capable of detecting intruders. It does so by checking if lights are being turned on while there is no one at home. When this happens it will turn the lights red, flash them for 30 seconds and send a message via [the notifiy component]({{site_root}}/components/notify.html). It will also flash a specific light when a known person comes home.
The component `simple_alarm` is capable of detecting intruders. It does so by checking if lights are being turned on while there is no one at home. When this happens it will turn the lights red, flash them for 30 seconds and send a message via [the notifiy component]({{site_root}}/components/notify/). It will also flash a specific light when a known person comes home.
This component depends on the components [device_tracker]({{site_root}}/components/device_tracker.html) and [light]({{site_root}}/components/light.html) being setup.
This component depends on the components [device_tracker]({{site_root}}/components/device_tracker/) and [light]({{site_root}}/components/light/) being setup.
To set it up, add the following lines to your `configuration.yaml` file:

View File

@ -10,11 +10,9 @@ footer: true
ha_category: Weather
---
The sun component will use your current location to track if the sun is above or below the horizon.The sun can be used within automation as [a trigger with an optional offset to simulate dawn/dusk][automation-trigger].
The `sun` component will use your current location to track if the sun is above or below the horizon.
The sun can be used within automation as [a trigger with an optional offset to simulate dawn/dusk][automation-trigger].
[automation-trigger]: /components/automation.html#sun-trigger
[automation-trigger]: /components/automation/#sun-trigger
```yaml
# Example configuration.yaml entry

View File

@ -38,7 +38,7 @@ In this section you find some real life examples of how to use this switch.
### {% linkable_title aREST device %}
The example below is doing the same as the [aREST switch](/components/switch.arest.html). The commandline tool `[curl](http://curl.haxx.se/)` is used to toogle a pin which is controllable through REST.
The example below is doing the same as the [aREST switch](/components/switch.arest/). The commandline tool [`curl`](http://curl.haxx.se/) is used to toogle a pin which is controllable through REST.
```yaml
# Example configuration.yaml entry

View File

@ -12,11 +12,9 @@ ha_category: Switch
---
In an ideal scenario, the MQTT device will have a state topic to publish state changes. If these messages are published with RETAIN flag, the MQTT switch will receive an instant state update after subscription and will
start with correct state. Otherwise, the initial state of the switch will be false/off.
In an ideal scenario, the MQTT device will have a state topic to publish state changes. If these messages are published with RETAIN flag, the MQTT switch will receive an instant state update after subscription and will start with correct state. Otherwise, the initial state of the switch will be false/off.
When a state topic is not available, the switch will work in optimistic mode. In this mode, the switch will immediately change state after every command. Otherwise, the switch will wait for state confirmation from device
(message from `state_topic`).
When a state topic is not available, the switch will work in optimistic mode. In this mode, the switch will immediately change state after every command. Otherwise, the switch will wait for state confirmation from device (message from `state_topic`).
Optimistic mode can be forced, even if state topic is available. Try to enable it, if experiencing incorrect switch operation.
@ -44,5 +42,5 @@ Configuration variables:
- **optimistic** (*Optional*): Flag that defines if switch works in optimistic mode. Default is true if no state topic defined, else false.
<p class='note warning'>
Make sure that your topics match exact. <code>some-topic/</code> and <code>some-topic</code> are different topics.
Make sure that your topics match exact. `some-topic/` and `some-topic` are different topics.
</p>

View File

@ -14,5 +14,5 @@ ha_category: Switch
The wink switch platform allows you to control your [Wink](http://www.wink.com/) switches.
The requirement is that you have setup your [Wink hub](/components/light.wink.html).
The requirement is that you have setup your [Wink hub](/components/light.wink/).

View File

@ -12,8 +12,7 @@ ha_category: Hub
---
The tellstick component integrates [TellStick](http://www.telldus.se/products/tellstick) devices into Home Assistant. This integration allows users to add switches, lights, and sensors which are communicating with 433 Mhz. There are couple of vendors (Capidi
Elro, Intertechno, Nexa, Proove, Sartano, and Viking) how are selling products which works with TellStick. For more details, please check the TellStick [compatibility list](http://telldus.se/products/compability).
The tellstick component integrates [TellStick](http://www.telldus.se/products/tellstick) devices into Home Assistant. This integration allows users to add switches, lights, and sensors which are communicating with 433 Mhz. There are couple of vendors (Capidi Elro, Intertechno, Nexa, Proove, Sartano, and Viking) how are selling products which works with TellStick. For more details, please check the TellStick [compatibility list](http://telldus.se/products/compability).
To get started, add the devices to your `configuration.yaml` file.
@ -28,6 +27,5 @@ sensor:
# All dimmers will be picked up as lights.
light:
platform: tellstick
```

View File

@ -16,6 +16,6 @@ The [Vera](http://getvera.com) ecosystem is using Z-Wave for communication betwe
## {% linkable_title Building on top of Vera %}
- [Vera Sensor](/components/sensor.vera.html)
- [Vera Switch](/components/switch.vera.html)
- [Vera Light](/components/light.vera.html)
- [Vera Sensor](/components/sensor.vera/)
- [Vera Switch](/components/switch.vera/)
- [Vera Light](/components/light.vera/)

View File

@ -12,10 +12,11 @@ ha_category: Hub
featured: true
---
[Wink](http://www.wink.com/) is a home automation hub that can control a whole wide range of devices on the market. Or, as they say in their own words:
<blockquote>Wink offers one, quick and simple way to connect people with the products they rely on every day in their home.</blockquote>
<blockquote>
Wink offers one, quick and simple way to connect people with the products they rely on every day in their home.
</blockquote>
Home Assistant integrates the Wink hub and allows you to get the status and control connected switches, lights and sensors.

View File

@ -10,10 +10,7 @@ footer: true
ha_category: Organization
---
Zones allow you to specify certain regions on earth (for now). When a device tracker sees a device
to be within a zone, the state will take the name from the zone. Zones can also be used as a
[trigger](/components/automation.html#zone-trigger) or [condition](/components/automation.html#zone-condition)
inside automation setups.
Zones allow you to specify certain regions on earth (for now). When a device tracker sees a device to be within a zone, the state will take the name from the zone. Zones can also be used as a [trigger](/components/automation/#zone-trigger) or [condition](/components/automation/#zone-condition) inside automation setups.
Zones support the usual method to specify multiple zones, use keys `zone:`, `zone 2:` etc.
@ -44,18 +41,12 @@ zone 3:
#### {% linkable_title Home zone %}
If no configuration is given, the zone component will create a zone for home. This zone will use
location given in the `configuration.yaml` file and have a radius of 100 meters. To override this,
create a zone configuration and name it 'Home'.
If no configuration is given, the zone component will create a zone for home. This zone will use location given in the `configuration.yaml` file and have a radius of 100 meters. To override this, create a zone configuration and name it 'Home'.
#### {% linkable_title Icons %}
It is preferred to pick an icon to use for your zone. By default, Home Assistant includes most of the
[material icons](https://www.google.com/design/icons/). See [the source][icon-source] for a specific list which
categories are included.
It is preferred to pick an icon to use for your zone. By default, Home Assistant includes most of the [material icons](https://www.google.com/design/icons/). See [the source][icon-source] for a specific list which categories are included.
For all but the action category you will need to prefix the icon name with its category. For example
`social:people` or `av:radio`. For the action category, you will not need to do this, examples are
`home`, `work,`, `group-work` and `shopping-cart`.
For all but the action category you will need to prefix the icon name with its category. For example `social:people` or `av:radio`. For the action category, you will not need to do this, examples are `home`, `work,`, `group-work` and `shopping-cart`.
[icon-source]: https://github.com/balloob/home-assistant-polymer/blob/master/src/resources/home-assistant-icons.html#L3

View File

@ -19,9 +19,9 @@ To allow Home Assistant to talk to your Z-Wave USB stick you will have to compil
Please make sure you have the correct dependencies installed:
```
apt-get install cython3 libudev-dev python-sphinx python3-setuptools
pip3 install "cython<0.23"
```bash
$ apt-get install cython3 libudev-dev python-sphinx python3-setuptools
$ pip3 install "cython<0.23"
```
As an alternative, the Home Assistant docker image has support for Z-Wave built-in.
@ -36,6 +36,8 @@ Configuration variables:
- **usb_path** (*Required*): The port where your device is connected to your Home Assistant host.
To find the path of your Z-Wave stick, run:
```bash
ls /dev/ttyUSB*
$ ls /dev/ttyUSB*
```

View File

@ -11,7 +11,7 @@ footer: true
### Rainy Day Light ###
This requires a [forecast.io](components/sensor.forecast.html) sensor with the condition `weather_precip` that tells if it's raining or not.
This requires a [forecast.io](components/sensor.forecast/) sensor with the condition `weather_precip` that tells if it's raining or not.
Turn on a light in the living room when it starts raining, someone is home, and it's afternoon or later.
@ -40,6 +40,7 @@ automation:
And then of course turn off the lamp when it stops raining but only if it's within an hour before sunset.
```yaml
automation 2:
alias: 'Rain is over'
trigger:
- platform: state

View File

@ -27,7 +27,9 @@ automation:
```
#### Natural wake up light
_Note, Philips Hue is currently the only light platform that support transitions._
```yaml
automation:
trigger:

View File

@ -17,9 +17,15 @@
</header>
{% endunless %}
{% if index %}
<div class="entry-content">{{ content | excerpt }}</div>
{% capture excerpted %}{{ content | has_excerpt }}{% endcapture %}
{% if excerpted == 'true' %}
<div class="entry-content">
{% if post.excerpted %}
{{ post.excerpt }}
<a href="{{ post.url }}"Continue reading </a>
{% else %}
{{ post.content }}
{% endif %}
</div>
{% if post.excerpted %}
<footer>
<a rel="full-article" href="{{ root_url }}{{ post.url }}">{{ site.excerpt_link }}</a>
</footer>

View File

@ -7,11 +7,12 @@
</div>
{% assign file_parts = page.url | split: '/' | last | split: '.' %}
{% if file_parts.size == 3 %}
{% if file_parts.size == 2 %}
{% assign is_platform = true %}
{% assign imp_name = file_parts[1] %}
{% assign parent_name = file_parts[0] %}
{% assign parent_url = parent_name | prepend: '/components/' | append: '.html' %}
{% assign parent_url = parent_name | prepend: '/components/' | append: '/' %}
{% assign parent_component = components | where: 'url', parent_url | first %}
{% else %}
{% assign is_platform = false %}
@ -54,8 +55,8 @@
{% for component in components %}
{% if component.url != page.url %}
{% assign comp_file_parts = component.url | split: '/' | last | split: '.' %}
{% if comp_file_parts.size == 3 %}
{% assign comp_imp_name = comp_file_parts[1] %}
{% if comp_file_parts.size == 2 %}
{% assign comp_imp_name = comp_file_parts | last %}
{% else %}
{% assign comp_imp_name = comp_file_parts | first %}
{% endif %}

View File

@ -22,13 +22,13 @@
{% endunless %}
</header>
{% capture excerpted %}{{ content | has_excerpt }}{% endcapture %}
{% if excerpted == 'true' and index %}
{% if index %}
<div class="entry-content clearfix">
{{ content | excerpt }}
<a class="btn pull-right" href="{{ root_url }}{{ post.url }}#read-more">{{ site.excerpt_link }}</a>
{{ post.excerpt }}
{% if post.content contains site.excerpt_separator %}
<a class="btn pull-right" href="{{ post.url }}#read-more">{{ site.excerpt_link }}</a>
{% endif %}
</div>
{% else %}
{{ content | replace: site.excerpt_separator, '<a name="read-more"></a>' }}
{{ post.content | replace: site.excerpt_separator, '<a name="read-more"></a>' }}
{% endif %}

View File

@ -1,5 +1,5 @@
{% capture date %}{{ page.date }}{{ post.date }}{% endcapture %}
{% capture date_formatted %}{{ page.date_formatted }}{{ post.date_formatted }}{% endcapture %}
{% capture date_formatted %}{{ post.date_formatted }}{% endcapture %}
{% capture has_date %}{{ date | size }}{% endcapture %}
{% capture updated %}{{ page.updated }}{{ post.updated }}{% endcapture %}

Some files were not shown because too many files have changed in this diff Show More