') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - winton/stasis: Static sites made powerful · GitHub
Skip to content

Repository files navigation

Stasis

Stasis is a dynamic framework for static sites.

Build Status

Install

Install via RubyGems:

$ gem install stasis

Example

At its most essential, Stasis takes a directory tree with supported template files and renders them.

Example directory structure:

project/
index.html.haml
images/
image.png

Run stasis:

$ cd project
$ stasis

Stasis creates a public directory:

project/
index.html.haml
images/
image.png
public/
index.html
images/
image.png

index.html.haml becomes public/index.html.

Unrecognized extensions are copied as-is (image.png).

Controllers

Controllers contain Ruby code that executes once before all templates render.

Example directory structure:

project/
controller.rb
index.html.haml
styles/
controller.rb
style.css.sass

You may have a controller at any directory level.

Before

Use before blocks within controller.rb to execute code before a template renders.

controller.rb:

before 'index.html.haml' do
@something = true
end

@something is now available to the index.html.haml template.

The before method can take any number of paths and/or regular expressions:

before 'index.html.haml', /.*html\.erb/ do
@something = true
end

Layouts

layout.html.haml:

%html
%body= yield

In controller.rb, set the default layout:

layout 'layout.html.haml'

Set the layout for a particular template:

layout 'index.html.haml' => 'layout.html.haml'

Use a regular expression:

layout /.*html.haml/ => 'layout.html.haml'

Set the layout from a before block:

before 'index.html.haml' do
layout 'layout.html.haml'
end

Render

Within a template:

%html
%body= render '_partial.html.haml'

Within a before block:

before 'index.html.haml' do
@partial = render '_partial.html.haml'
end

Text:

render :text => 'Hello'

Local variables:

render 'index.html.haml', :locals => { :x => true }

Include a block for the template to yield to:

render 'index.html.haml' { 'Hello' }

Instead

The instead method changes the output of the template being rendered:

before 'index.html.haml' do
instead render('subdirectory/index.html.haml')
end

Helpers

controller.rb:

helpers do
def say_hello
'Hello'
end
end

The say_hello method is now available to all before blocks and templates.

Ignore

Use the ignore method in controller.rb to ignore certain paths.

Ignore filenames with an underscore at the beginning:

ignore /\/_.*/

Priority

Use the priority method in controller.rb to change the file process order.

Copy .txt files before rendering the index.html.erb template:

priority /.*txt/ => 2, 'index.html.erb' => 1

The default priority is 0 for all files.

Usage

Command Line

Always execute the stasis command in the root directory of your project.

Development mode (auto-regenerate on save):

$ stasis -d

Specify a port to start an HTTP server:

$ stasis -d 3000

Only render specific files or directories:

$ stasis -o index.html.haml,subdirectory

Change the public (destination) directory:

$ stasis -p ../public

Ruby Library

Instantiate a Stasis object:

stasis = Stasis.new('/path/to/project/root')

Optionally specify a destination directory:

stasis = Stasis.new('/project', '/html')

Render all templates:

stasis.render

Render a specific template or directory:

stasis.render('index.html.haml', 'subdirectory')

More

Supported Markup Languages

Stasis uses Tilt to support the following template engines:

ENGINE FILE EXTENSIONS
-------------------------- -----------------------
ERB .erb, .rhtml
Interpolated String .str
Erubis .erb, .rhtml, .erubis
Haml .haml
Sass .sass
Scss .scss
Less CSS .less
Builder .builder
Liquid .liquid
RDiscount .markdown, .mkd, .md
Redcarpet .markdown, .mkd, .md
BlueCloth .markdown, .mkd, .md
Kramdown .markdown, .mkd, .md
Maruku .markdown, .mkd, .md
RedCloth .textile
RDoc .rdoc
Radius .radius
Markaby .mab
Nokogiri .nokogiri
CoffeeScript .coffee
Creole (Wiki markup) .wiki, .creole
WikiCloth (Wiki markup) .wiki, .mediawiki, .mw
Yajl .yajl

This Web Site

Take a look at the Stasis project that automatically generated this web site from the project README.

About

Static sites made powerful

Resources

Stars

672 stars

Watchers

12 watching

Forks

Releases

Packages

Used by

Contributors

Languages