├── client ├── core │ ├── spin │ │ ├── spin.deps.yaml │ │ ├── spin_view.deps.yaml │ │ ├── images │ │ │ └── spin.gif │ │ ├── spin_default-large.styl │ │ ├── spin.bt.js │ │ ├── _skin │ │ │ ├── spin_skin_size-l.styl │ │ │ └── spin_skin_common.styl │ │ ├── spin.js │ │ └── spin.test.js │ ├── chitalka-ui │ │ ├── images │ │ │ ├── arrows.png │ │ │ ├── arrows.svg │ │ │ └── arrows.svg.base64 │ │ ├── chitalka-ui.deps.yaml │ │ ├── chitalka-ui.bt.js │ │ ├── chitalka-ui.styl │ │ └── chitalka-ui.js │ ├── chitalka-fb2 │ │ ├── chitalka-fb2.deps.yaml │ │ ├── chitalka-fb2.bt.js │ │ ├── chitalka-fb2.styl │ │ └── chitalka-fb2-parser.js │ ├── config │ │ ├── config.js │ │ └── config.bt.js │ ├── storage │ │ └── storage.js │ ├── file-drag │ │ └── file-drag.js │ ├── controls │ │ ├── controls.bt.js │ │ ├── controls.js │ │ └── controls.styl │ ├── chitalka │ │ ├── chitalka.test.js │ │ └── chitalka.js │ └── chitalka-design │ │ └── chitalka-design.styl └── islets │ ├── core │ ├── y-block │ │ ├── __auto-init │ │ │ ├── y-block__auto-init.deps.yaml │ │ │ ├── y-block__auto-init.js │ │ │ └── y-block__auto-init.md │ │ └── y-block.md │ ├── y-next-tick │ │ ├── y-next-tick.md │ │ └── y-next-tick.js │ ├── y-dom │ │ ├── y-dom.md │ │ └── y-dom.js │ ├── jquery │ │ ├── jquery-config.js │ │ └── jquery.js │ ├── y-event-emitter │ │ ├── y-event-emitter.md │ │ ├── y-event-emitter.js │ │ └── y-event-emitter.test.js │ ├── y-load-script │ │ ├── y-load-script.md │ │ └── y-load-script.js │ ├── y-debounce │ │ ├── y-debounce.md │ │ ├── y-debounce.js │ │ └── y-debounce.test.js │ ├── y-throttle │ │ ├── y-throttle.md │ │ ├── y-throttle.js │ │ └── y-throttle.test.js │ ├── y-event-manager │ │ ├── y-event-manager.md │ │ ├── y-event-manager.js │ │ └── y-event-manager.test.js │ ├── y-i18n │ │ ├── y-i18n.md │ │ └── y-i18n.js │ ├── y-focus-holder │ │ └── y-focus-holder.js │ ├── y-unique-id │ │ ├── y-unique-id.js │ │ └── y-unique-id.test.js │ ├── y-block-event │ │ ├── y-block-event.js │ │ └── y-block-event.test.js │ ├── y-block-mixin │ │ └── y-block-mixin.js │ ├── y-extend │ │ ├── y-extend.js │ │ └── y-extend.test.js │ └── y-design │ │ └── y-design.styl │ └── common │ ├── y-page │ ├── y-page.deps.yaml │ ├── y-page_islet.styl │ ├── y-page.md │ ├── y-page.test.js │ └── y-page.bt.js │ ├── y-ua │ └── y-ua.bt.js │ └── y-global │ └── y-global.bt.js ├── .travis.yml ├── .gitignore ├── README.md ├── .enb └── make.js ├── package.json ├── LICENSE ├── Makefile ├── test └── client │ └── test.html └── lib └── reader.xsl /client/core/spin/spin.deps.yaml: -------------------------------------------------------------------------------- 1 | - view: default 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | 5 | -------------------------------------------------------------------------------- /client/core/spin/spin_view.deps.yaml: -------------------------------------------------------------------------------- 1 | - skin: '*' 2 | required: true 3 | -------------------------------------------------------------------------------- /client/islets/core/y-block/__auto-init/y-block__auto-init.deps.yaml: -------------------------------------------------------------------------------- 1 | - jquery 2 | - y-block 3 | -------------------------------------------------------------------------------- /client/core/spin/images/spin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chitalka/reader/HEAD/client/core/spin/images/spin.gif -------------------------------------------------------------------------------- /client/islets/common/y-page/y-page.deps.yaml: -------------------------------------------------------------------------------- 1 | - y-global 2 | - block: y-design 3 | required: true 4 | - block: y-ua 5 | -------------------------------------------------------------------------------- /client/core/spin/spin_default-large.styl: -------------------------------------------------------------------------------- 1 | .spin_default-large { 2 | spin_skin_common(); 3 | spin_skin_size-l(); 4 | } 5 | -------------------------------------------------------------------------------- /client/core/chitalka-ui/images/arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chitalka/reader/HEAD/client/core/chitalka-ui/images/arrows.png -------------------------------------------------------------------------------- /client/islets/core/y-next-tick/y-next-tick.md: -------------------------------------------------------------------------------- 1 | # y-next-tick: 2 | 3 | Вызывает переданную функцию в следующем тике. 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .enb/tmp 3 | build/index/* 4 | !build/index/i 5 | !build/index/index.btjson.js 6 | test/client/* 7 | !test/client/test.html 8 | -------------------------------------------------------------------------------- /client/core/chitalka-fb2/chitalka-fb2.deps.yaml: -------------------------------------------------------------------------------- 1 | - hammer 2 | - chitalka 3 | - unzip 4 | - storage 5 | - block: chitalka-design 6 | required: true 7 | - gsap 8 | - chitalka-ui 9 | -------------------------------------------------------------------------------- /client/islets/core/y-dom/y-dom.md: -------------------------------------------------------------------------------- 1 | # y-dom: работа с DOM 2 | 3 | Модуль `y-dom` возвращает объект `yDom` для работы с DOM со следующими полями и методами: 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/islets/common/y-page/y-page_islet.styl: -------------------------------------------------------------------------------- 1 | .y-page_islet { 2 | margin: 0; 3 | padding: 0; 4 | 5 | background: #F6F5F3; 6 | 7 | font-family: $y-design.common['font-family']; 8 | } 9 | -------------------------------------------------------------------------------- /client/islets/core/jquery/jquery-config.js: -------------------------------------------------------------------------------- 1 | modules.define('jquery-config', function (provide) { 2 | provide({ 3 | url: '//yastatic.net/jquery/1.10.1/jquery.min.js' 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /client/core/config/config.js: -------------------------------------------------------------------------------- 1 | modules.define('config', function (provide) { 2 | var domNode = document.getElementById('config'); 3 | provide(domNode ? JSON.parse(domNode.innerHTML) : {}); 4 | }); 5 | -------------------------------------------------------------------------------- /client/islets/core/y-event-emitter/y-event-emitter.md: -------------------------------------------------------------------------------- 1 | # y-event-emitter: эмиттер 2 | 3 | Предоставляет базовый класс для сущностей, кидающих на себе события. 4 | 5 | ## API класса 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/islets/core/y-load-script/y-load-script.md: -------------------------------------------------------------------------------- 1 | # y-load-script: 2 | 3 | Модуль `y-load-script` возвращает функцию `loadScript`, которая загружает js-файлы добавляя тэг ` 9 | 10 | 11 | 12 | 13 | 14 | 15 | 46 | 47 | 48 |
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /client/islets/core/y-debounce/y-debounce.js: -------------------------------------------------------------------------------- 1 | modules.define('y-debounce', function (provide) { 2 | /** 3 | * Вернет версию функции, исполнение которой начнется не ранее, 4 | * чем истечет промежуток wait, после ее последнего вызова. 5 | * 6 | * Полезно для реализации логики, которая зависит от завершения 7 | * действий пользователя. Например, проверить орфографию комментария 8 | * пользователя лучше будет после того, как он его окончательно введет, 9 | * а динамечески перерассчитать разметку после того, как пользователь 10 | * закончит изменять размер окна. 11 | * 12 | * @name debounce 13 | * @param {Function} func 14 | * @param {Number} wait 15 | * @param {Boolean} [immediate=false] Если true, выполнит функцию в начале 16 | * интервала wait, иначе - в конце. 17 | * @returns {Function} 18 | * 19 | * @example 20 | * var calculateLayout = function() {}; 21 | * var lazyLayout = debounce(calculateLayout, 300); 22 | * $(window).resize(lazyLayout); 23 | */ 24 | provide(function (func, wait, immediate) { 25 | var result; 26 | var timeout = null; 27 | return function () { 28 | var context = this; 29 | var args = arguments; 30 | var later = function () { 31 | timeout = null; 32 | if (!immediate) { 33 | result = func.apply(context, args); 34 | } 35 | }; 36 | var callNow = immediate && !timeout; 37 | clearTimeout(timeout); 38 | timeout = setTimeout(later, wait); 39 | if (callNow) { 40 | result = func.apply(context, args); 41 | } 42 | return result; 43 | }; 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /client/islets/common/y-page/y-page.test.js: -------------------------------------------------------------------------------- 1 | modules.define( 2 | 'test', 3 | ['bt'], 4 | function (provide, bt) { 5 | 6 | describe('y-page', function () { 7 | describe('bt', function () { 8 | describe('doctype', function () { 9 | it('should should render HTML5 doctype by default', function () { 10 | bt.processBtJson({block: 'y-page'})[0].should.equal(''); 11 | }); 12 | it('should should render given doctype', function () { 13 | bt.processBtJson({block: 'y-page', doctype: ''})[0].should.equal(''); 14 | }); 15 | }); 16 | describe('layout', function () { 17 | it('should render html tag', function () { 18 | bt.processBtJson({block: 'y-page'})[1]._tag.should.equal('html'); 19 | }); 20 | it('should render head tag', function () { 21 | bt.processBtJson({block: 'y-page'})[1].content[0]._tag.should.equal('head'); 22 | }); 23 | it('should render body tag', function () { 24 | bt.processBtJson({block: 'y-page'})[1].content[1]._tag.should.equal('body'); 25 | }); 26 | }); 27 | describe('js', function () { 28 | bt.apply({ 29 | block: 'y-page', 30 | scripts: [{url: '1.js'}, {source: 'alert("Hello World!");'}] 31 | }).should.contain( 32 | '' + 33 | '' 34 | ); 35 | }); 36 | }); 37 | }); 38 | 39 | provide(); 40 | }); 41 | -------------------------------------------------------------------------------- /client/islets/core/y-block-event/y-block-event.js: -------------------------------------------------------------------------------- 1 | modules.define( 2 | 'y-block-event', 3 | [ 4 | 'inherit' 5 | ], 6 | function ( 7 | provide, 8 | inherit 9 | ) { 10 | 11 | /** 12 | * Класс, представляющий событие блока. 13 | */ 14 | var YBlockEvent = inherit({ 15 | /** 16 | * @param {String} type Тип события. 17 | * @param {Boolean} [isPropagationStopped=false] Запрещает распространение события. 18 | * @param {Boolean} [isDefaultPrevented=false] Запрещает действие по умолчанию. 19 | */ 20 | __constructor: function (type, isPropagationStopped, isDefaultPrevented) { 21 | this.type = type; 22 | this._isPropagationStopped = Boolean(isPropagationStopped); 23 | this._isDefaultPrevented = Boolean(isDefaultPrevented); 24 | }, 25 | 26 | /** 27 | * Определяет, прекращено ли распространение события. 28 | * 29 | * @returns {Boolean} 30 | */ 31 | isPropagationStopped: function () { 32 | return this._isPropagationStopped; 33 | }, 34 | 35 | /** 36 | * Проверяет, отменена ли реакция по умолчанию на событие. 37 | * 38 | * @returns {Boolean} 39 | */ 40 | isDefaultPrevented: function () { 41 | return this._isDefaultPrevented; 42 | }, 43 | 44 | /** 45 | * Прекращает распространение события. 46 | */ 47 | stopPropagation: function () { 48 | this._isPropagationStopped = true; 49 | }, 50 | 51 | /** 52 | * Отменяет реакцию по умолчанию на событие. 53 | */ 54 | preventDefault: function () { 55 | this._isDefaultPrevented = true; 56 | } 57 | }); 58 | 59 | provide(YBlockEvent); 60 | }); 61 | -------------------------------------------------------------------------------- /client/islets/common/y-global/y-global.bt.js: -------------------------------------------------------------------------------- 1 | module.exports = function (bt) { 2 | 3 | bt.lib.global = bt.lib.global || {}; 4 | bt.lib.global.lang = bt.lib.global.lang || 'ru'; 5 | bt.lib.global.tld = bt.lib.global.tld || 'ru'; 6 | bt.lib.global['content-region'] = bt.lib.global['content-region'] || 'ru'; 7 | bt.lib.global['click-host'] = bt.lib.global['click-host'] || '//clck.yandex.ru'; 8 | bt.lib.global['passport-host'] = bt.lib.global['passport-host'] || 'https://passport.yandex.ru'; 9 | bt.lib.global['pass-host'] = bt.lib.global['pass-host'] || '//pass.yandex.ru'; 10 | bt.lib.global['social-host'] = bt.lib.global['social-host'] || '//social.yandex.ru'; 11 | bt.lib.global['export-host'] = bt.lib.global['export-host'] || '//export.yandex.ru'; 12 | 13 | /** 14 | * Changes top level domain. 15 | * 16 | * @param {String} tld Top level domain. 17 | */ 18 | bt.lib.global.setTld = function (tld) { 19 | var xYaDomain = tld === 'tr' ? 'yandex.com.tr' : 'yandex.' + tld; 20 | var yaDomain = ['ua', 'by', 'kz'].indexOf(tld) !== -1 ? 'yandex.ru' : xYaDomain; 21 | var globalObj = bt.lib.global; 22 | globalObj['content-region'] = tld; 23 | globalObj['click-host'] = '//clck.' + yaDomain; 24 | globalObj['passport-host'] = 'https://passport.' + yaDomain; 25 | globalObj['pass-host'] = '//pass.' + xYaDomain; 26 | globalObj['social-host'] = '//social.' + xYaDomain; 27 | globalObj['export-host'] = '//export.' + xYaDomain; 28 | globalObj.tld = tld; 29 | }; 30 | 31 | /** 32 | * @returns {String} 33 | */ 34 | bt.lib.global.getTld = function () { 35 | return bt.lib.global.tld; 36 | }; 37 | 38 | if (bt.lib.i18n && bt.lib.i18n.getLanguage) { 39 | var tld = bt.lib.i18n.getLanguage(); 40 | if (tld === 'uk') { 41 | tld = 'ua'; 42 | } 43 | bt.lib.global.setTld(tld); 44 | } 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /client/islets/core/y-throttle/y-throttle.js: -------------------------------------------------------------------------------- 1 | modules.define('y-throttle', function (provide) { 2 | /** 3 | * Возвращает новую функцию, которая при повторных вызовах, 4 | * вызывает функцию func не чаще одного раза в заданный 5 | * промежуток wait. 6 | * 7 | * Полезна для использования при обработке событий, которые 8 | * происходят слишком часто. 9 | * 10 | * @name throttle 11 | * @param {Function} func 12 | * @param {Number} wait Минимальный промежуток времени в миллисекундах, 13 | * который должен пройти между вызовами func. 14 | * @param {Object} [options] 15 | * @param {Boolean} [options.leading=true] Включает исполнение функции вначале. 16 | * @param {Boolean} [options.trailing=true] Включает исполнение функции вконце. 17 | * @returns {Function} 18 | * 19 | * @example 20 | * var updatePosition = function () {}; 21 | * var throttled = throttle(updatePosition, 100); 22 | * $(window).scroll(throttled); 23 | */ 24 | provide(function (func, wait, options) { 25 | var context; 26 | var args; 27 | var result; 28 | var timeout = null; 29 | var previous = 0; 30 | options = options || {}; 31 | 32 | var later = function () { 33 | previous = options.leading === false ? 0 : Date.now(); 34 | timeout = null; 35 | result = func.apply(context, args); 36 | }; 37 | 38 | return function () { 39 | var now = Date.now(); 40 | if (!previous && options.leading === false) { 41 | previous = now; 42 | } 43 | var remaining = wait - (now - previous); 44 | context = this; 45 | args = arguments; 46 | if (remaining <= 0) { 47 | clearTimeout(timeout); 48 | timeout = null; 49 | previous = now; 50 | result = func.apply(context, args); 51 | } else if (!timeout && options.trailing !== false) { 52 | timeout = setTimeout(later, remaining); 53 | } 54 | return result; 55 | }; 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /client/islets/core/y-unique-id/y-unique-id.test.js: -------------------------------------------------------------------------------- 1 | modules.define( 2 | 'test', 3 | ['y-unique-id'], 4 | function (provide, uniqueId) { 5 | 6 | var should = chai.should(); 7 | 8 | describe('uniqueId', function () { 9 | describe('generate()', function () { 10 | it('should generate unique id on each call', function () { 11 | var id1 = uniqueId.generate(); 12 | var id2 = uniqueId.generate(); 13 | var id3 = uniqueId.generate(); 14 | 15 | should.exist(id1); 16 | should.exist(id2); 17 | should.exist(id3); 18 | 19 | id1.should.not.eq(id2); 20 | id1.should.not.eq(id3); 21 | id2.should.not.eq(id3); 22 | }); 23 | }); 24 | 25 | describe('identify()', function () { 26 | it('should generate different ids for different objects', function () { 27 | var obj1 = {}; 28 | var obj2 = {}; 29 | var id1 = uniqueId.identify(obj1); 30 | var id2 = uniqueId.identify(obj2); 31 | id1.should.not.eq(id2); 32 | }); 33 | 34 | it('should generate same id for same objects', function () { 35 | var obj = {}; 36 | var id1 = uniqueId.identify(obj); 37 | var id2 = uniqueId.identify(obj); 38 | id1.should.eq(id2); 39 | }); 40 | }); 41 | 42 | describe('isIdentified()', function () { 43 | it('should return true if object has unique id ', function () { 44 | var obj = {}; 45 | uniqueId.isIdentified(obj).should.be.false; 46 | uniqueId.identify(obj); 47 | uniqueId.isIdentified(obj).should.be.true; 48 | }); 49 | 50 | it('should check own object\'s property', function () { 51 | function Custom() {} 52 | uniqueId.identify(Custom.prototype); 53 | var custom = new Custom(); 54 | uniqueId.isIdentified(custom).should.be.false; 55 | }); 56 | }); 57 | }); 58 | 59 | provide(); 60 | }); 61 | -------------------------------------------------------------------------------- /client/islets/core/y-load-script/y-load-script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Загружает js-файлы добавляя тэг