initial commit
This commit is contained in:
commit
11348f2c42
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bower_components/
|
||||||
|
node_modules/
|
||||||
|
|
18
Gruntfile.coffee
Normal file
18
Gruntfile.coffee
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module.exports = (grunt) ->
|
||||||
|
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks)
|
||||||
|
|
||||||
|
grunt.initConfig {
|
||||||
|
coffee:
|
||||||
|
compile:
|
||||||
|
expand: true
|
||||||
|
cwd: 'src'
|
||||||
|
src: [ '*.coffee' ]
|
||||||
|
dest: 'dist'
|
||||||
|
ext: '.js'
|
||||||
|
watch:
|
||||||
|
coffee:
|
||||||
|
files: [ 'src/*.coffee' ]
|
||||||
|
tasks: [ 'coffee:compile' ]
|
||||||
|
}
|
||||||
|
|
||||||
|
grunt.registerTask 'default', 'watch:coffee'
|
18
bower.json
Normal file
18
bower.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "angular-presentation",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"jquery": "~2.1.0",
|
||||||
|
"angular": "~1.2.14-build.2273",
|
||||||
|
"js-beautify": "~1.4.2",
|
||||||
|
"solarized": "~0.1.2",
|
||||||
|
"angular-ui-utils": "bower-keypress"
|
||||||
|
}
|
||||||
|
}
|
292
dist/angular-presentation.js
vendored
Normal file
292
dist/angular-presentation.js
vendored
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
(function() {
|
||||||
|
var codeGrabber, presentation, processCodeBlock;
|
||||||
|
|
||||||
|
presentation = angular.module('presentation', ['ui.keypress']);
|
||||||
|
|
||||||
|
presentation.factory('boundScopeHelper', function() {
|
||||||
|
return function(directive) {
|
||||||
|
var originalCompile, originalLink;
|
||||||
|
originalCompile = directive.compile;
|
||||||
|
originalLink = directive.link;
|
||||||
|
directive.compile = function(tE, tA, transclude) {
|
||||||
|
var key, value, _ref;
|
||||||
|
_ref = directive.scope;
|
||||||
|
for (key in _ref) {
|
||||||
|
value = _ref[key];
|
||||||
|
tA[key] = key;
|
||||||
|
}
|
||||||
|
if (originalCompile != null) {
|
||||||
|
return originalCompile(tE, tA, transclude);
|
||||||
|
} else if (originalLink) {
|
||||||
|
return originalLink;
|
||||||
|
} else {
|
||||||
|
return function(scope, element, attrs) {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
delete directive.link;
|
||||||
|
return directive;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.factory('presentationOptions', function() {
|
||||||
|
var Options;
|
||||||
|
Options = (function() {
|
||||||
|
function Options() {}
|
||||||
|
|
||||||
|
Options.prototype.slides = [];
|
||||||
|
|
||||||
|
Options.prototype.currentSlide = null;
|
||||||
|
|
||||||
|
Options.prototype.addSlide = function(id) {
|
||||||
|
this.slides.push(id);
|
||||||
|
return this.currentSlide || (this.currentSlide = id);
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.currentSlideIndex = function() {
|
||||||
|
return this.slides.indexOf(this.currentSlide);
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.nextSlide = function() {
|
||||||
|
var index;
|
||||||
|
index = this.currentSlideIndex() + 1;
|
||||||
|
if (index < this.slides.length) {
|
||||||
|
return this.switchToSlide(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.previousSlide = function() {
|
||||||
|
var index;
|
||||||
|
index = this.currentSlideIndex() - 1;
|
||||||
|
if (index > -1) {
|
||||||
|
return this.switchToSlide(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.switchToSlide = function(index) {
|
||||||
|
return this.currentSlide = this.slides[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.hasPrevious = function() {
|
||||||
|
return this.currentSlideIndex() > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.hasNext = function() {
|
||||||
|
return this.currentSlideIndex() < this.slides.length - 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
Options.prototype.nextID = function() {
|
||||||
|
return "slide-" + this.slides.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Options;
|
||||||
|
|
||||||
|
})();
|
||||||
|
return new Options();
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.directive('presentation', function() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
transclude: true,
|
||||||
|
replace: true,
|
||||||
|
templateUrl: 'presentation.html',
|
||||||
|
controller: function($scope, presentationOptions) {
|
||||||
|
return $scope.options = presentationOptions;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.directive('slide', function(boundScopeHelper) {
|
||||||
|
return boundScopeHelper({
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
transclude: true,
|
||||||
|
templateUrl: 'slide.html',
|
||||||
|
scope: {
|
||||||
|
'options': '='
|
||||||
|
},
|
||||||
|
compile: function(tE, tA, transclude) {
|
||||||
|
var id;
|
||||||
|
id = tA.id;
|
||||||
|
return function(scope, element, attrs) {
|
||||||
|
scope.id = id || scope.options.nextID();
|
||||||
|
scope.options.addSlide(scope.id);
|
||||||
|
scope.state || (scope.state = {});
|
||||||
|
return scope.codeBlocks || (scope.codeBlocks = {});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.simpleDirective = function(name, options) {
|
||||||
|
if (options == null) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
return this.directive(name, function($sce) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
transclude: true,
|
||||||
|
scope: true,
|
||||||
|
templateUrl: name + '.html',
|
||||||
|
compile: function(tE, tA, transclude) {
|
||||||
|
return function(scope, element, attrs) {
|
||||||
|
return transclude(scope, function(clone, innerScope) {
|
||||||
|
clone = angular.element('<div />').append(clone);
|
||||||
|
if (options.postLink != null) {
|
||||||
|
options.postLink(scope, name, clone);
|
||||||
|
return scope[name] = $sce.trustAsHtml(scope[name]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
presentation.simpleDirective('title', {
|
||||||
|
postLink: function(scope, name, clone) {
|
||||||
|
return scope[name] = clone.text();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.simpleDirective('subtitle', {
|
||||||
|
postLink: function(scope, name, clone) {
|
||||||
|
return scope[name] = clone.html();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.directive('controls', function() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
templateUrl: 'controls.html'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
codeGrabber = function(scope, element, name) {
|
||||||
|
var html;
|
||||||
|
html = element.html();
|
||||||
|
scope.codeBlocks || (scope.codeBlocks = {});
|
||||||
|
return scope.codeBlocks[name] = html;
|
||||||
|
};
|
||||||
|
|
||||||
|
presentation.directive('script', function() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
if (attrs.type === 'text/code-grabber') {
|
||||||
|
return codeGrabber(scope, element, attrs["for"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.directive('codeGrabber', function() {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
return codeGrabber(scope, element, attrs.codeGrabber);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.directive('codeRunner', function($compile) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
var target;
|
||||||
|
element.after("<div class='code-runner' />");
|
||||||
|
target = element.next();
|
||||||
|
element.remove();
|
||||||
|
return scope.$watch('codeBlocks', function(codeBlocks) {
|
||||||
|
var content;
|
||||||
|
content = angular.element("<div />").append(codeBlocks[attrs["for"]]);
|
||||||
|
$compile(content)(scope);
|
||||||
|
target.html('');
|
||||||
|
return target.append(content);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
processCodeBlock = function(code, language, callback) {
|
||||||
|
var beautifier, length, line, lines, output, prismLanguage;
|
||||||
|
prismLanguage = null;
|
||||||
|
beautifier = (function() {
|
||||||
|
switch (language) {
|
||||||
|
case 'html':
|
||||||
|
prismLanguage = 'markup';
|
||||||
|
return window.html_beautify;
|
||||||
|
case 'javascript':
|
||||||
|
case 'json':
|
||||||
|
prismLanguage = 'javascript';
|
||||||
|
return window.js_beautify;
|
||||||
|
case 'css':
|
||||||
|
case 'scss':
|
||||||
|
case 'sass':
|
||||||
|
prismLanguage = 'css';
|
||||||
|
return window.css_beautify;
|
||||||
|
default:
|
||||||
|
prismLanguage = language;
|
||||||
|
return function(code, options) {
|
||||||
|
return code;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
output = beautifier(code, {
|
||||||
|
indent_size: 2
|
||||||
|
}).replace(/</g, "<");
|
||||||
|
lines = output.split("\n");
|
||||||
|
length = lines[0].length - lines[0].replace(/^ */, '').length;
|
||||||
|
output = ((function() {
|
||||||
|
var _i, _len, _results;
|
||||||
|
_results = [];
|
||||||
|
for (_i = 0, _len = lines.length; _i < _len; _i++) {
|
||||||
|
line = lines[_i];
|
||||||
|
_results.push(line.substr(length));
|
||||||
|
}
|
||||||
|
return _results;
|
||||||
|
})()).join("\n");
|
||||||
|
return callback(Prism.highlight(output, Prism.languages[prismLanguage]));
|
||||||
|
};
|
||||||
|
|
||||||
|
presentation.directive('codeDisplayer', function(boundScopeHelper) {
|
||||||
|
return boundScopeHelper({
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
scope: {
|
||||||
|
codeBlocks: '=',
|
||||||
|
state: '='
|
||||||
|
},
|
||||||
|
templateUrl: 'code_displayer.html',
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
return scope.$watch('codeBlocks', function(codeBlocks) {
|
||||||
|
if (codeBlocks && codeBlocks[attrs["for"]]) {
|
||||||
|
return processCodeBlock(codeBlocks[attrs["for"]], attrs.language, function(highlightedCode) {
|
||||||
|
return element.find('code').append(highlightedCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
presentation.directive('pre', function() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
if (attrs.language != null) {
|
||||||
|
return processCodeBlock(element.text(), attrs.language, function(highlightedCode) {
|
||||||
|
console.log(highlightedCode);
|
||||||
|
element.html('');
|
||||||
|
element.append('<code />');
|
||||||
|
return element.find('code').append(highlightedCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
17
package.json
Normal file
17
package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "angular-presentation",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "BSD",
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "~0.4.2",
|
||||||
|
"matchdep": "~0.3.0",
|
||||||
|
"grunt-contrib-coffee": "~0.10.0",
|
||||||
|
"grunt-contrib-watch": "~0.5.3"
|
||||||
|
}
|
||||||
|
}
|
203
src/angular-presentation.coffee
Normal file
203
src/angular-presentation.coffee
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
presentation = angular.module 'presentation', [ 'ui.keypress' ]
|
||||||
|
|
||||||
|
presentation.factory 'boundScopeHelper', ->
|
||||||
|
(directive) ->
|
||||||
|
originalCompile = directive.compile
|
||||||
|
originalLink = directive.link
|
||||||
|
|
||||||
|
directive.compile = (tE, tA, transclude) ->
|
||||||
|
tA[key] = key for key, value of directive.scope
|
||||||
|
|
||||||
|
if originalCompile?
|
||||||
|
originalCompile(tE, tA, transclude)
|
||||||
|
else if originalLink
|
||||||
|
originalLink
|
||||||
|
else
|
||||||
|
(scope, element, attrs) ->
|
||||||
|
|
||||||
|
delete directive.link
|
||||||
|
|
||||||
|
directive
|
||||||
|
|
||||||
|
presentation.factory 'presentationOptions', ->
|
||||||
|
class Options
|
||||||
|
slides: []
|
||||||
|
currentSlide: null
|
||||||
|
|
||||||
|
addSlide: (id) ->
|
||||||
|
@slides.push(id)
|
||||||
|
@currentSlide ||= id
|
||||||
|
|
||||||
|
currentSlideIndex: -> @slides.indexOf(@currentSlide)
|
||||||
|
|
||||||
|
nextSlide: ->
|
||||||
|
index = @currentSlideIndex() + 1
|
||||||
|
if index < @slides.length
|
||||||
|
@switchToSlide(index)
|
||||||
|
|
||||||
|
previousSlide: ->
|
||||||
|
index = @currentSlideIndex() - 1
|
||||||
|
if index > -1
|
||||||
|
@switchToSlide(index)
|
||||||
|
|
||||||
|
switchToSlide: (index) ->
|
||||||
|
@currentSlide = @slides[index]
|
||||||
|
|
||||||
|
hasPrevious: ->
|
||||||
|
@currentSlideIndex() > 0
|
||||||
|
|
||||||
|
hasNext: ->
|
||||||
|
@currentSlideIndex() < @slides.length - 1
|
||||||
|
|
||||||
|
nextID: ->
|
||||||
|
"slide-#{@slides.length}"
|
||||||
|
|
||||||
|
new Options()
|
||||||
|
|
||||||
|
presentation.directive 'presentation', ->
|
||||||
|
restrict: 'E'
|
||||||
|
transclude: true
|
||||||
|
replace: true
|
||||||
|
templateUrl: 'presentation.html'
|
||||||
|
controller: ($scope, presentationOptions) ->
|
||||||
|
$scope.options = presentationOptions
|
||||||
|
|
||||||
|
presentation.directive 'slide', (boundScopeHelper) ->
|
||||||
|
boundScopeHelper(
|
||||||
|
restrict: 'E'
|
||||||
|
replace: true
|
||||||
|
transclude: true
|
||||||
|
templateUrl: 'slide.html'
|
||||||
|
scope:
|
||||||
|
'options': '='
|
||||||
|
compile: (tE, tA, transclude) ->
|
||||||
|
id = tA.id
|
||||||
|
|
||||||
|
(scope, element, attrs) ->
|
||||||
|
scope.id = id || scope.options.nextID()
|
||||||
|
scope.options.addSlide(scope.id)
|
||||||
|
|
||||||
|
scope.state ||= {}
|
||||||
|
scope.codeBlocks ||= {}
|
||||||
|
)
|
||||||
|
|
||||||
|
presentation.simpleDirective = (name, options = {}) ->
|
||||||
|
@directive name, ($sce) ->
|
||||||
|
restrict: 'E'
|
||||||
|
replace: true
|
||||||
|
transclude: true
|
||||||
|
scope: true
|
||||||
|
templateUrl: name + '.html'
|
||||||
|
compile: (tE, tA, transclude) ->
|
||||||
|
(scope, element, attrs) ->
|
||||||
|
transclude scope, (clone, innerScope) ->
|
||||||
|
clone = angular.element('<div />').append(clone)
|
||||||
|
|
||||||
|
if options.postLink?
|
||||||
|
options.postLink(scope, name, clone)
|
||||||
|
scope[name] = $sce.trustAsHtml(scope[name])
|
||||||
|
|
||||||
|
presentation.simpleDirective 'title',
|
||||||
|
postLink: (scope, name, clone) ->
|
||||||
|
scope[name] = clone.text()
|
||||||
|
|
||||||
|
presentation.simpleDirective 'subtitle',
|
||||||
|
postLink: (scope, name, clone) ->
|
||||||
|
scope[name] = clone.html()
|
||||||
|
|
||||||
|
presentation.directive 'controls', ->
|
||||||
|
restrict: 'E'
|
||||||
|
replace: true
|
||||||
|
templateUrl: 'controls.html'
|
||||||
|
|
||||||
|
codeGrabber = (scope, element, name) ->
|
||||||
|
html = element.html()
|
||||||
|
|
||||||
|
scope.codeBlocks ||= {}
|
||||||
|
scope.codeBlocks[name] = html
|
||||||
|
|
||||||
|
presentation.directive 'script', ->
|
||||||
|
restrict: 'E'
|
||||||
|
link: (scope, element, attrs) ->
|
||||||
|
if attrs.type == 'text/code-grabber'
|
||||||
|
codeGrabber scope, element, attrs.for
|
||||||
|
|
||||||
|
presentation.directive 'codeGrabber', ->
|
||||||
|
restrict: 'A'
|
||||||
|
link: (scope, element, attrs) ->
|
||||||
|
codeGrabber scope, element, attrs.codeGrabber
|
||||||
|
|
||||||
|
presentation.directive 'codeRunner', ($compile) ->
|
||||||
|
restrict: 'E'
|
||||||
|
replace: true
|
||||||
|
link: (scope, element, attrs) ->
|
||||||
|
element.after "<div class='code-runner' />"
|
||||||
|
target = element.next()
|
||||||
|
element.remove()
|
||||||
|
|
||||||
|
scope.$watch(
|
||||||
|
'codeBlocks',
|
||||||
|
(codeBlocks) ->
|
||||||
|
content = angular.element("<div />").append(codeBlocks[attrs.for])
|
||||||
|
|
||||||
|
$compile(content)(scope)
|
||||||
|
|
||||||
|
target.html('')
|
||||||
|
target.append(content)
|
||||||
|
, true
|
||||||
|
)
|
||||||
|
|
||||||
|
processCodeBlock = (code, language, callback) ->
|
||||||
|
prismLanguage = null
|
||||||
|
|
||||||
|
beautifier = switch language
|
||||||
|
when 'html'
|
||||||
|
prismLanguage = 'markup'
|
||||||
|
window.html_beautify
|
||||||
|
when 'javascript', 'json'
|
||||||
|
prismLanguage = 'javascript'
|
||||||
|
window.js_beautify
|
||||||
|
when 'css', 'scss', 'sass'
|
||||||
|
prismLanguage = 'css'
|
||||||
|
window.css_beautify
|
||||||
|
else
|
||||||
|
prismLanguage = language
|
||||||
|
(code, options) -> code
|
||||||
|
|
||||||
|
output = beautifier(code, { indent_size: 2 }).replace(/</g, "<")
|
||||||
|
|
||||||
|
lines = output.split("\n")
|
||||||
|
length = lines[0].length - lines[0].replace(/^ */, '').length
|
||||||
|
|
||||||
|
output = (line.substr(length) for line in lines).join("\n")
|
||||||
|
|
||||||
|
callback(Prism.highlight(output, Prism.languages[prismLanguage]))
|
||||||
|
|
||||||
|
presentation.directive 'codeDisplayer', (boundScopeHelper) ->
|
||||||
|
boundScopeHelper {
|
||||||
|
restrict: 'E'
|
||||||
|
replace: true
|
||||||
|
scope: {
|
||||||
|
codeBlocks: '='
|
||||||
|
state: '='
|
||||||
|
}
|
||||||
|
templateUrl: 'code_displayer.html'
|
||||||
|
link: (scope, element, attrs) ->
|
||||||
|
scope.$watch(
|
||||||
|
'codeBlocks', (codeBlocks) ->
|
||||||
|
if codeBlocks && codeBlocks[attrs.for]
|
||||||
|
processCodeBlock codeBlocks[attrs.for], attrs.language, (highlightedCode) ->
|
||||||
|
element.find('code').append(highlightedCode)
|
||||||
|
, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
presentation.directive 'pre', ->
|
||||||
|
restrict: 'E'
|
||||||
|
link: (scope, element, attrs) ->
|
||||||
|
if attrs.language?
|
||||||
|
processCodeBlock element.text(), attrs.language, (highlightedCode) ->
|
||||||
|
console.log highlightedCode
|
||||||
|
|
||||||
|
element.html('')
|
||||||
|
element.append('<code />')
|
||||||
|
element.find('code').append(highlightedCode)
|
Loading…
Reference in New Issue
Block a user