Skip to content

Commit

Permalink
Ported sassdoc-theme-light source code to sassdoc-theme-default
Browse files Browse the repository at this point in the history
  • Loading branch information
KittyGiraudel committed Oct 11, 2014
1 parent e3e527c commit cd41e26
Show file tree
Hide file tree
Showing 53 changed files with 2,435 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.DS_Store
.sass-cache
npm-debug.log
assets/css/main.css.map
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
SASS = sass
UGLIFY = node_modules/uglify-js/bin/uglifyjs

all: sass min

min: assets/js/main.min.js

assets/js/main.min.js: \
assets/js/vendor/fuse.min.js \
assets/js/sidebar.js \
assets/js/search.js \
assets/js/main.js \
assets/js/vendor/prism.min.js
cat $^ | $(UGLIFY) > $@

sass:
$(SASS) --update scss:assets/css --style compressed

clean:
$(RM) -r assets/js/main.min.js assets/css
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# SassDoc Default Theme

This leads to [sassdoc-theme-light](https://github.com/SassDoc/sassdoc-theme-light).
This is [SassDoc](https://github.com/SassDoc/sassdoc)'s default theme which means this is the theme that will be used when running SassDoc without a custom theme.

This theme uses [Themeleon](https://github.com/themeleon/themeleon) as a theme engine, and [themeleon-swig](https://github.com/themeleon/themeleon-swig) as a template engine, directly plugged into Themeleon.

Because this is likely to be the most used theme of all, it is not as simple as a theme can get. For instance, there is quite a bit of logic in both `index.js` and the Swig templates. Fortunately, you don't have to deal with that at all.

## Customising the view

There are some possibilites to customise the theme's view. Essentially what's being displayed, what's not, and what are the project informations to be displayed in the header and footer.

To learn how to customise the theme's view, please read [the documentation on SassDoc's site](http://sassdoc.com/customising-the-view/). Fear not! It's all about creating a configuration file. No big deal.
2 changes: 2 additions & 0 deletions assets/css/main.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 56 additions & 0 deletions assets/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* global document */

(function ($, global) {
'use strict';

// Constructor
var App = function (conf) {
this.conf = $.extend({
// Search module
search: new global.Search(),

// Sidebar module
sidebar: new global.Sidebar(),

// Initialisation
init: true
}, conf || {});

// Launch the module
if (this.conf.init !== false) {
this.initialize();
}
};

// Initialisation method
App.prototype.initialize = function () {
this.codePreview();
};

// Toggle code preview collapsed/expanded modes
App.prototype.codePreview = function () {
var $item;
var $code;
var switchTo;

$('.item__code--togglable').on('click', function () {
$item = $(this);
$code = $item.find('code');
switchTo = $item.attr('data-current-state') === 'expanded' ? 'collapsed' : 'expanded';

$item.attr('data-current-state', switchTo);
$code.html($item.attr('data-' + switchTo));
Prism.highlightElement($code[0]);
});
};

global.App = App;
}(window.jQuery, window));

(function ($, global) {

$(document).ready(function () {
var app = new global.App();
});

}(window.jQuery, window));
1 change: 1 addition & 0 deletions assets/js/main.min.js

Large diffs are not rendered by default.

144 changes: 144 additions & 0 deletions assets/js/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
(function ($, global) {

var Search = function (conf) {
this.conf = $.extend({
// Search DOM
search: {
items: '.sassdoc__item',
input: '#js-search-input',
form: '#js-search',
suggestionsWrapper: '#js-search-suggestions'
},

// Fuse options
fuse: {
keys: ['name'],
threshold: 0.3
},

init: true
}, conf || {});

if (this.conf.init === true) {
this.initialize();
}
};

Search.prototype.initialize = function () {
// Fuse engine instanciation
this.index = new Fuse($.map($(this.conf.search.items), function (item) {
var $item = $(item);

return {
name: $item.data('name'),
type: $item.data('type'),
node: $item
};
}), this.conf.fuse);

this.initializeSearch();
};

// Fill DOM with search suggestions
Search.prototype.fillSuggestions = function (items) {
var searchSuggestions = $(this.conf.search.suggestionsWrapper);
searchSuggestions.html('');

var suggestions = $.map(items.slice(0, 10), function (item) {
var $li = $('<li />', {
'data-type': item.type,
'data-name': item.name,
'html': '<a href="#' + item.type + '-' + item.name + '"><code>' + item.type.slice(0, 3) + '</code> ' + item.name + '</a>'
});

searchSuggestions.append($li);
return $li;
});

return suggestions;
};

// Perform a search on a given term
Search.prototype.search = function (term) {
return this.fillSuggestions(this.index.search(term));
};

// Search logic
Search.prototype.initializeSearch = function () {
var searchForm = $(this.conf.search.form);
var searchInput = $(this.conf.search.input);
var searchSuggestions = $(this.conf.search.suggestionsWrapper);

var currentSelection = -1;
var suggestions = [];
var selected;

var self = this;

// Clicking on a suggestion
searchSuggestions.on('click', function (e) {
var target = $(event.target);

if (target.nodeName === 'A') {
searchInput.val(target.parent().data('name'));
suggestions = self.fillSuggestions([]);
}
});

// Filling the form
searchForm.on('keyup', function (e) {
e.preventDefault();

// Enter
if (e.keyCode === 13) {
if (selected) {
suggestions = self.fillSuggestions([]);
searchInput.val(selected.data('name'));
window.location = selected.children().first().attr('href');
}

e.stopPropagation();
}

// KeyDown
if (e.keyCode === 40) {
currentSelection = (currentSelection + 1) % suggestions.length;
}

// KeyUp
if (e.keyCode === 38) {
currentSelection = currentSelection - 1;

if (currentSelection < 0) {
currentSelection = suggestions.length - 1;
}
}

if (suggestions[currentSelection]) {
if (selected) {
selected.removeClass('selected');
}

selected = suggestions[currentSelection];
selected.addClass('selected');
}

});

searchInput.on('keyup', function (e) {
if (e.keyCode !== 40 && e.keyCode !== 38) {
currentSelection = -1;
suggestions = self.search($(this).val());
}

else {
e.preventDefault();
}
}).on('search', function () {
suggestions = self.search($(this).val());
});
};

global.Search = Search;

}(window.jQuery, window));
139 changes: 139 additions & 0 deletions assets/js/sidebar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
(function ($, global) {

var Sidebar = function (conf) {
this.conf = $.extend({

// Collapsed class
collapsedClass: 'is-collapsed',

// Storage key
storageKey: '_sassdoc_sidebar_index',

// Index attribute
indexAttribute: 'data-slug',

// Toggle button
toggleBtn: '.js-btn-toggle',

// Automatic initialization
init: true
}, conf || {});

if (this.conf.init === true) {
this.initialize();
}
};

/**
* Initialize module
*/
Sidebar.prototype.initialize = function () {
this.conf.nodes = $('[' + this.conf.indexAttribute + ']');

this.load();
this.updateDOM();
this.bind();
};

/**
* Load data from storage or create fresh index
*/
Sidebar.prototype.load = function () {
var index = 'localStorage' in global ?
global.localStorage.getItem(this.conf.storageKey) :
null;

this.index = index ? JSON.parse(index) : this.buildIndex();
};

/**
* Build a fresh index
*/
Sidebar.prototype.buildIndex = function () {
var index = {};
var $item;

this.conf.nodes.each($.proxy(function (index, item) {
$item = $(item);

index[$item.attr(this.conf.indexAttribute)] = !$item.hasClass(this.conf.collapsedClass);
}, this));

return index;
};

/**
* Update DOM based on index
*/
Sidebar.prototype.updateDOM = function () {
var item;

for (item in this.index) {
if (this.index[item] === false) {
$('[' + this.conf.indexAttribute + '="' + item + '"]').addClass(this.conf.collapsedClass);
}
}
};

/**
* Save index in storage
*/
Sidebar.prototype.save = function () {
if (!('localStorage' in global)) {
return;
}

global.localStorage.setItem(this.conf.storageKey, JSON.stringify(this.index));
};

/**
* Bind UI events
*/
Sidebar.prototype.bind = function () {
var $item, slug, fn, text;
var collapsed = false;

// Save index in localStorage
global.onbeforeunload = $.proxy(function () {
this.save();
}, this);

// Toggle all
$(this.conf.toggleBtn).on('click', $.proxy(function (event) {
$node = $(event.target);

text = $node.attr('data-alt');
$node.attr('data-alt', $node.text());
$node.text(text);

fn = collapsed === true ? 'removeClass' : 'addClass';

this.conf.nodes.each($.proxy(function (index, item) {
$item = $(item);
slug = $item.attr(this.conf.indexAttribute);

this.index[slug] = collapsed;

$('[' + this.conf.indexAttribute + '="' + slug + '"]')[fn](this.conf.collapsedClass);
}, this));

collapsed = !collapsed;
this.save();
}, this));

// Toggle item
this.conf.nodes.on('click', $.proxy(function (event) {
$item = $(event.target);
slug = $item.attr(this.conf.indexAttribute);

// Update index
this.index[slug] = !this.index[slug];

// Update DOM
$item.toggleClass(this.conf.collapsedClass);
}, this));
};

global.Sidebar = Sidebar;

}(window.jQuery, window));
Loading

0 comments on commit cd41e26

Please sign in to comment.