diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..cd38bcca2 --- /dev/null +++ b/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": [ + ["env", {"modules": false}] + ] +} diff --git a/.gitignore b/.gitignore index 0bcbabb8c..709f78cf2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ web/bundles/* !web/bundles/wallabagcore /web/assets/images/* !web/assets/images/.gitkeep +web/bundles/wallabagcore/*.dev.js # Build /app/build diff --git a/.travis.yml b/.travis.yml index 77872f493..8d900d27a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,4 +74,4 @@ script: - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml src/Wallabag/CoreBundle/Resources/translations -v ; fi; - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml app/Resources/CraueConfigBundle/translations -v ; fi; - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml src/Wallabag/UserBundle/Resources/translations -v ; fi; - - if [[ $ASSETS = build ]]; then ./node_modules/grunt-cli/bin/grunt tests; fi; + - if [[ $ASSETS = build ]]; then ./node_modules/webpack/bin/webpack.js; fi; diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 72473b21c..000000000 --- a/Gruntfile.js +++ /dev/null @@ -1,230 +0,0 @@ -module.exports = function (grunt) { - require('load-grunt-tasks')(grunt); - - grunt.initConfig({ - appDir: 'app/Resources/static', - buildDir: 'app/Resources/build', - modulesDir: 'node_modules', - releaseDir: 'web/bundles/wallabagcore', - - postcss: { - material: { - options: { - processors: [ - require('pixrem')(), - require('autoprefixer')({ browsers: 'last 2 versions' }), - require('cssnano')(), - ], - }, - src: '<%= buildDir %>/material.css', - dest: '<%= releaseDir %>/themes/material/css/style.min.css', - }, - baggy: { - options: { - processors: [ - require('pixrem')(), - require('autoprefixer')({ browsers: 'last 2 versions' }), - require('cssnano')(), - ], - }, - src: '<%= buildDir %>/baggy.css', - dest: '<%= releaseDir %>/themes/baggy/css/style.min.css', - }, - }, - concat: { - options: { - separator: ';', - }, - cssMaterial: { - src: [ - 'node_modules/materialize-css/bin/materialize.css', - '<%= appDir %>/themes/material/css/*.css', - ], - dest: '<%= buildDir %>/material.css', - }, - cssBaggy: { - src: [ - '<%= appDir %>/themes/baggy/css/*.css', - ], - dest: '<%= buildDir %>/baggy.css', - }, - }, - browserify: { - dist: { - files: { - '<%= buildDir %>/material.browser.js': ['<%= appDir %>/themes/material/js/init.js'], - '<%= buildDir %>/baggy.browser.js': ['<%= appDir %>/themes/baggy/js/init.js'] - } - }, - options: { - sourceType: "module", - transform: [ - ["babelify", { - presets: ["es2015"] - }], ["browserify-shim", { - "jquery": { - "exports": "$" - }, - "materialize": "materialize", - "jquery-ui": { - "depends": "jquery", - "exports": null - } - }] - ], - browserifyOptions: { - browser: { - "jQuery": "./node_modules/jquery/dist/jquery.js", - "jquery.tinydot": "./node_modules/jquery.tinydot/src/jquery.tinydot.js", - "jquery.ui": "./node_modules/jquery-ui-browserify/dist/jquery-ui.js" - } - } - } - - }, - uglify: { - material: { - files: { - '<%= releaseDir %>/themes/material/js/material.min.js': - ['<%= buildDir %>/material.browser.js'], - } - }, - baggy: { - files: { - '<%= releaseDir %>/themes/baggy/js/baggy.min.js': - ['<%= buildDir %>/baggy.browser.js'], - } - }, - }, - copy: { - pickerjs: { - expand: true, - cwd: '<%= modulesDir %>/pickadate/lib', - src: 'picker.js', - dest: '<%= buildDir %>', - }, - annotator: { - expand: true, - cwd: '<%= modulesDir %>/annotator/pkg', - src: 'annotator.min.js', - dest: '<%= buildDir %>/themes/_global/js/', - }, - baggyfonts: { - files: [ - { - expand: true, - cwd: '<%= modulesDir %>/icomoon-free-npm/Font', - src: 'IcoMoon-Free.ttf', - dest: '<%= releaseDir %>/themes/baggy/fonts/', - }, - { - expand: true, - cwd: '<%= modulesDir %>/ptsans-npm-webfont/fonts', - src: 'ptsansbold.woff', - dest: '<%= releaseDir %>/themes/baggy/fonts/', - }, - { - expand: true, - cwd: '<%= modulesDir %>/material-design-icons-iconfont/dist/fonts/', - src: ['MaterialIcons-Regular.eot', 'MaterialIcons-Regular.woff2', 'MaterialIcons-Regular.woff', 'MaterialIcons-Regular.ttf'], - dest: '<%= releaseDir %>/themes/baggy/fonts/', - }, - ], - }, - materialfonts: { - files: [ - { - expand: true, - overwrite: true, - cwd: '<%= modulesDir %>/icomoon-free-npm/Font', - src: 'IcoMoon-Free.ttf', - dest: '<%= releaseDir %>/themes/material/fonts', - }, - { - expand: true, - overwrite: true, - cwd: '<%= modulesDir %>/roboto-fontface/fonts/Roboto', - src: '*', - dest: '<%= releaseDir %>/themes/material/font/roboto', - }, - { - expand: true, - overwrite: true, - cwd: '<%= modulesDir %>/material-design-icons-iconfont/dist/fonts/', - src: ['MaterialIcons-Regular.eot', 'MaterialIcons-Regular.woff2', 'MaterialIcons-Regular.woff', 'MaterialIcons-Regular.ttf'], - dest: '<%= releaseDir %>/themes/material/fonts/', - }, - ], - }, - }, - symlink: { - pics: { - files: [ - { - expand: true, - overwrite: true, - cwd: '<%= appDir %>/themes/_global/', - src: 'img', - dest: '<%= releaseDir %>/themes/_global/', - }, - ], - }, - }, - clean: { - css: { - src: ['<%= buildDir %>/**/*.css'], - }, - js: { - src: ['<%= buildDir %>/**/*.js', '<%= buildDir %>/**/*.map'], - }, - all: { - src: ['./<%= buildDir %>'], - }, - release: { - src: ['./<%= releaseDir %>/*'], - } - }, - eslint: { - target: ['<%= appDir %>/themes/material/js/init.js', '<%= appDir %>/themes/baggy/js/init.js'] - }, - stylelint: { - target: ['<%= appDir %>/themes/material/css/*.css', '<%= appDir %>/themes/baggy/css/*.css'] - }, - watch: { - files: ['<%= appDir %>/**/*.css', '<%= appDir %>/**/*.js'], - tasks: ['css', 'js'] - } - }); - - grunt.registerTask( - 'fonts', - 'Install fonts', - ['copy:baggyfonts', 'copy:materialfonts'] - ); - - grunt.registerTask( - 'js', - 'Build and install js files', - ['clean:js', 'copy:pickerjs', 'browserify', 'uglify'] - ); - - grunt.registerTask( - 'default', - 'Build and install everything', - ['clean', 'copy:pickerjs', 'concat', 'browserify', 'uglify', 'postcss', 'copy', 'symlink'] - ); - - grunt.registerTask( - 'css', - 'Compiles the stylesheets.', - ['clean:css', 'concat:cssMaterial', 'concat:cssBaggy', 'postcss'] - ); - - grunt.registerTask( - 'tests', - 'Test css and js style conformity', - ['eslint', 'stylelint', 'default'] - ), - - grunt.loadNpmTasks('grunt-contrib-watch'); -}; diff --git a/app/AppKernel.php b/app/AppKernel.php index c8382d5f6..b9293498f 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -71,5 +71,14 @@ class AppKernel extends Kernel public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml'); + $loader->load(function ($container) { + if ($container->getParameter('use_webpack_dev_server')) { + $container->loadFromExtension('framework', [ + 'assets' => [ + 'base_url' => 'http://localhost:8080/', + ], + ]); + } + }); } } diff --git a/app/Resources/static/themes/_global/global.scss b/app/Resources/static/themes/_global/global.scss new file mode 100644 index 000000000..0e877efba --- /dev/null +++ b/app/Resources/static/themes/_global/global.scss @@ -0,0 +1,13 @@ +/* Rules for sizing the icon. */ +.material-icons.md-18 { font-size: 18px; } +.material-icons.md-24 { font-size: 24px; } +.material-icons.md-36 { font-size: 36px; } +.material-icons.md-48 { font-size: 48px; } + +/* Rules for using icons as black on a light background. */ +.material-icons.md-dark { color: rgba(0, 0, 0, 0.54); } +.material-icons.md-dark.md-inactive { color: rgba(0, 0, 0, 0.26); } + +/* Rules for using icons as white on a dark background. */ +.material-icons.md-light { color: rgba(255, 255, 255, 1); } +.material-icons.md-light.md-inactive { color: rgba(255, 255, 255, 0.3); } diff --git a/app/Resources/static/themes/_global/img/icons/Diaspora-asterisk.svg b/app/Resources/static/themes/_global/img/icons/Diaspora-asterisk.svg new file mode 100644 index 000000000..91764b605 --- /dev/null +++ b/app/Resources/static/themes/_global/img/icons/Diaspora-asterisk.svg @@ -0,0 +1,334 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/Resources/static/themes/_global/index.js b/app/Resources/static/themes/_global/index.js new file mode 100644 index 000000000..00410754a --- /dev/null +++ b/app/Resources/static/themes/_global/index.js @@ -0,0 +1,52 @@ +/* jQuery */ +import $ from 'jquery'; + +/* Annotations */ +import annotator from 'annotator'; + +/* Fonts */ +import 'material-design-icons-iconfont/dist/material-design-icons.css'; +import 'lato-font/css/lato-font.css'; +import './global.scss'; + +/* Shortcuts*/ +import './js/shortcuts/entry'; +import './js/shortcuts/main'; + +import { savePercent, retrievePercent } from './js/tools'; + + +/* ========================================================================== + Annotations & Remember position + ========================================================================== */ + +$(document).ready(() => { + if ($('article').length) { + const app = new annotator.App(); + + app.include(annotator.ui.main, { + element: document.querySelector('article'), + }); + + const x = JSON.parse($('#annotationroutes').html()); + app.include(annotator.storage.http, x); + + app.start().then(() => { + app.annotations.load({ entry: x.entryId }); + }); + + $(window).scroll(() => { + const scrollTop = $(window).scrollTop(); + const docHeight = $(document).height(); + const scrollPercent = (scrollTop) / (docHeight); + const scrollPercentRounded = Math.round(scrollPercent * 100) / 100; + savePercent(x.entryId, scrollPercentRounded); + }); + + retrievePercent(x.entryId); + + $(window).resize(() => { + retrievePercent(x.entryId); + }); + } +}); diff --git a/app/Resources/static/themes/_global/js/tools.js b/app/Resources/static/themes/_global/js/tools.js index cee84fa80..774f45399 100644 --- a/app/Resources/static/themes/_global/js/tools.js +++ b/app/Resources/static/themes/_global/js/tools.js @@ -31,25 +31,4 @@ function retrievePercent(id) { return true; } -function initFilters() { - // no display if filters not available - if ($('div').is('#filters')) { - $('#button_filters').show(); - $('.js-filters-action').sideNav({ edge: 'right' }); - $('#clear_form_filters').on('click', () => { - $('#filters input').val(''); - $('#filters :checked').removeAttr('checked'); - return false; - }); - } -} - -function initExport() { - // no display if export not available - if ($('div').is('#export')) { - $('#button_export').show(); - $('.js-export-action').sideNav({ edge: 'right' }); - } -} - -export { savePercent, retrievePercent, initFilters, initExport }; +export { savePercent, retrievePercent }; diff --git a/app/Resources/static/themes/baggy/css/article.scss b/app/Resources/static/themes/baggy/css/article.scss new file mode 100644 index 000000000..9094ad550 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/article.scss @@ -0,0 +1,165 @@ + +#article { + width: 70%; + margin-bottom: 3em; + text-align: justify; + + .tags { + margin-bottom: 1em; + } + + i { + font-style: normal; + } + + h1 { + text-align: left; + } + + h2::after { + content: none; + } + + h2, + h3, + h4 { + text-transform: none; + } +} + +blockquote { + border: 1px solid #999; + background-color: #fff; + padding: 1em; + margin: 0; +} + +.topPosF { + position: fixed; + right: 20%; + bottom: 2em; + font-size: 1.5em; +} + +#article_toolbar { + margin-bottom: 1em; + + li { + display: inline-block; + margin: 3px auto; + } + + a { + background-color: #000; + padding: 0.3em 0.5em 0.2em; + color: #fff; + text-decoration: none; + + &:hover, + &:focus { + background-color: #999; + } + } +} + +#nav-btn-add-tag { + cursor: pointer; +} + +.shaarli::before { + content: "*"; +} + +.return { + text-decoration: none; + margin-top: 1em; + display: block; +} + +.return::before { + margin-right: 0.5em; +} + +.notags { + font-style: italic; + color: #999; +} + +.icon-rss { + background-color: #000; + color: #fff; + padding: 0.2em 0.5em; + + &::before { + position: relative; + top: 2px; + } +} + +.list-tags { + li { + margin-bottom: 0.5em; + } + + .icon-rss:hover, + .icon-rss:focus { + background-color: #fff; + color: #000; + text-decoration: none; + } + + a { + text-decoration: none; + + &:hover, + &:focus { + text-decoration: underline; + } + } +} + +pre code { + font-family: "Courier New", Courier, monospace; +} + +#filters { + position: fixed; + width: 20%; + height: 100%; + top: 0; + right: 0; + background-color: #fff; + padding: 30px 30px 15px 15px; + border-left: 1px #333 solid; + z-index: 12; + min-width: 300px; + + form .filter-group { + margin: 5px; + } +} + +#download-form { + position: fixed; + width: 10%; + height: 100%; + top: 0; + right: 0; + background-color: #fff; + padding: 30px 30px 15px 15px; + border-left: 1px #333 solid; + z-index: 12; + min-width: 200px; + + li { + display: block; + padding: 0.5em 2em 0.5em 1em; + color: #fff; + position: relative; + text-transform: uppercase; + text-decoration: none; + font-weight: 400; + font-family: PT Sans, sans-serif; + transition: all 0.5s ease; + } +} diff --git a/app/Resources/static/themes/baggy/css/font.css b/app/Resources/static/themes/baggy/css/font.css deleted file mode 100755 index 47edcb838..000000000 --- a/app/Resources/static/themes/baggy/css/font.css +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - font-family: "PT Sans"; - font-style: normal; - font-weight: 700; - src: local("PT Sans Bold"), local("PTSans-Bold"), url("../fonts/ptsansbold.woff") format("woff"); -} diff --git a/app/Resources/static/themes/baggy/css/guide.scss b/app/Resources/static/themes/baggy/css/guide.scss new file mode 100644 index 000000000..afb47c4a9 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/guide.scss @@ -0,0 +1,263 @@ + +::selection { + color: #fff; + background-color: #000; +} + +.desktopHide { + display: none; +} + +.logo { + position: fixed; + z-index: 20; + top: 0.4em; + left: 0.6em; +} + +h2, +h3, +h4 { + font-family: "PT Sans", sans-serif; + text-transform: uppercase; +} + +p, +li, +label { + color: #666; +} + +a { + color: #000; + font-weight: bold; + + &.nostyle { + text-decoration: none; + } + + &:hover, + &:focus { + text-decoration: none; + } +} + +form fieldset { + border: 0; + padding: 0; + margin: 0; +} + +form input[type="text"], +form input[type="number"], +select, +form input[type="password"], +form input[type="url"], +form input[type="email"] { + border: 1px solid #999; + padding: 0.5em 1em; + min-width: 12em; + color: #666; +} + +@media screen and (-webkit-min-device-pixel-ratio: 0) { + select { + -webkit-appearance: none; + border-radius: 0; + background: #fff url("../../_global/img/bg-select.png") no-repeat right center; + } +} + +.inline { + .row { + display: inline-block; + margin-right: 0.5em; + } + + label { + min-width: 6em; + } +} + +fieldset label { + display: inline-block; + min-width: 12.5em; + color: #666; +} + +label { + margin-right: 0.5em; +} + +form .row { + margin-bottom: 0.5em; +} + +form button, +input[type="submit"] { + cursor: pointer; + background-color: #000; + color: #fff; + padding: 0.5em 1em; + display: inline-block; + border: 1px solid #000; +} + +form button:hover, +form button:focus, +input[type="submit"]:hover, +input[type="submit"]:focus { + background-color: #fff; + color: #000; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; +} + +#bookmarklet { + cursor: move; +} + +h2::after { + content: ""; + height: 4px; + width: 20%; + background-color: #000; + display: block; +} + +.links { + padding: 0; + margin: 0; + + li { + list-style: none; + margin: 0; + padding: 0; + } +} + +#links { + position: fixed; + top: 0; + width: 10em; + left: 0; + text-align: right; + background-color: #333; + padding-top: 9.5em; + height: 100%; + box-shadow: inset -4px 0 20px rgba(0, 0, 0, 0.6); + z-index: 15; + + > li > a { + display: block; + padding: 0.5em 2em 0.5em 1em; + color: #fff; + position: relative; + text-transform: uppercase; + text-decoration: none; + font-weight: normal; + font-family: "PT Sans", sans-serif; + transition: all 0.5s ease; + + &:hover, + &:focus { + background-color: #999; + color: #000; + } + } + + .current::after { + content: ""; + width: 0; + height: 0; + position: absolute; + border: 10px solid transparent; + border-right-color: #eee; + right: 0; + top: 50%; + margin-top: -10px; + } + + li:last-child { + position: fixed; + bottom: 1em; + width: 10em; + + a::before { + font-size: 1.2em; + position: relative; + top: 2px; + } + } +} + +#main { + margin-left: 12em; + position: relative; + z-index: 10; + padding-right: 5%; + padding-bottom: 1em; +} + +#sort { + padding: 0; + list-style-type: none; + opacity: 0.5; + display: inline-block; + + li { + display: inline; + font-size: 0.9em; + + & + li { + margin-left: 10px; + } + } + + a { + padding: 2px 2px 0; + vertical-align: middle; + } + + img { + vertical-align: baseline; + + :hover { + cursor: pointer; + } + } +} + +#display-mode { + float: right; + margin-top: 10px; + margin-bottom: 10px; + opacity: 0.5; +} + +#listmode { + width: 16px; + display: inline-block; + text-decoration: none; + + &.tablemode { + background: url("../../_global/img/table.png") no-repeat bottom; + } + + .listmode { + background: url("../../_global/img/list.png") no-repeat bottom; + } +} + +#warning_message { + position: fixed; + background-color: #ff6347; + z-index: 1000; + bottom: 0; + left: 0; + width: 100%; + color: #000; +} diff --git a/app/Resources/static/themes/baggy/css/index.scss b/app/Resources/static/themes/baggy/css/index.scss new file mode 100644 index 000000000..e7a119631 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/index.scss @@ -0,0 +1,13 @@ +/* Style */ +@import 'guide'; +@import 'layout'; +@import 'article'; +@import 'pictos'; +@import 'login'; +@import 'save'; +@import 'messages'; + +/* Tools */ +@import 'media_queries'; +@import 'print'; +@import 'ratatouille'; diff --git a/app/Resources/static/themes/baggy/css/layout.scss b/app/Resources/static/themes/baggy/css/layout.scss new file mode 100644 index 000000000..cb14e62d4 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/layout.scss @@ -0,0 +1,300 @@ +#content { + margin-top: 2em; + min-height: 30em; +} + +footer { + text-align: right; + position: relative; + bottom: 0; + right: 5em; + color: #999; + font-size: 0.8em; + font-style: italic; + z-index: 20; + + a { + color: #999; + font-weight: normal; + } +} + +.list-entries { + letter-spacing: -5px; +} + +.listmode.entry { + width: 100%; + height: inherit; +} + +.card-entry-tags { + max-height: 2em; + overflow-y: hidden; + padding: 0; + margin: 0; +} + +.card-entry-tags li, +.card-entry-tags span { + display: inline-block; + margin: 0 5px; + padding: 5px 12px; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 3px; + max-height: 2em; + overflow: hidden; + text-overflow: ellipsis; +} + +.card-entry-tags a, +.card-entry-labels a { + text-decoration: none; + font-weight: normal; + color: #fff; +} + +.nav-panel-add-tag { + margin-top: 10px; +} + +.list-entries + .results { + margin-bottom: 2em; +} + +.reading-time, +.created-at { + color: #999; + font-style: italic; + font-weight: normal; + font-size: 0.9em; +} + +.estimatedTime small { + position: relative; + top: -1px; +} + +.entry { + background-color: #fff; + letter-spacing: normal; + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + display: inline-block; + width: 32%; + margin-bottom: 1.5em; + vertical-align: top; + margin-right: 1%; + position: relative; + overflow: hidden; + padding: 1.5em 0 3em; + height: 440px; + + img.preview { + width: 100%; + object-fit: cover; + height: 100%; + } + + &::before { + content: ""; + width: 0; + height: 0; + border: 10px solid transparent; + border-bottom-color: #000; + position: absolute; + bottom: 0.7em; + z-index: 10; + right: 1.5em; + transition: all 0.5s ease; + } + + &::after { + content: ""; + position: absolute; + height: 7px; + width: 100%; + bottom: 0; + left: 0; + background-color: #000; + transition: all 0.5s ease; + } + + &:hover { + box-shadow: 0 3px 10px rgba(0, 0, 0, 1); + + &::after { + height: 40px; + } + + &::before { + bottom: 2.3em; + } + + h2 a { + color: #666; + } + + .tools { + bottom: 0; + } + } + + h2 { + text-transform: none; + margin-bottom: 0; + line-height: 1.2; + margin-left: 5px; + } + + &::after { + content: none; + } + + a { + display: block; + text-decoration: none; + color: #000; + word-wrap: break-word; + transition: all 0.5s ease; + } + + p { + color: #666; + font-size: 0.9em; + line-height: 1.7; + margin: 5px 5px auto; + } + + h2 a::first-letter { + text-transform: uppercase; + } + + .tools { + position: absolute; + bottom: -40px; + left: 0; + background: #000; + width: 100%; + z-index: 10; + padding-right: 0.5em; + text-align: right; + transition: all 0.5s ease; + + a { + color: #666; + text-decoration: none; + display: block; + padding: 0.4em; + + &:hover { + color: #fff; + } + } + + li { + display: inline-block; + margin-top: 10px; + } + + li:first-child { + float: left; + font-size: 0.9em; + max-width: calc(100% - 40px * 4); + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + max-height: 2em; + margin-left: 10px; + } + } + + .card-entry-labels { + position: absolute; + top: 100px; + left: -1em; + z-index: 90; + max-width: 50%; + padding-left: 0; + + li { + margin: 10px 10px 10px auto; + padding: 5px 12px 5px 25px; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 0 3px 3px 0; + color: #fff; + cursor: default; + max-height: 2em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + a { + color: #fff; + } + } + } +} + +.entry:nth-child(3n+1) { + margin-left: 0; +} + +.results { + letter-spacing: -5px; + padding: 0 0 0.5em; + + > * { + display: inline-block; + vertical-align: top; + letter-spacing: normal; + width: 50%; + text-align: right; + } +} + +div.pagination ul { + text-align: right; +} + +.nb-results { + text-align: left; + font-style: italic; + color: #999; + display: inline-flex; +} + +div.pagination ul { + a { + color: #999; + text-decoration: none; + + &:hover, + &:focus { + text-decoration: underline; + } + } + + > * { + display: inline-block; + margin-left: 0.5em; + } + + .prev.disabled, + .next.disabled { + display: none; + } + + .current { + height: 25px; + padding: 4px 8px; + border: 1px solid #d5d5d5; + text-decoration: none; + font-weight: bold; + color: #000; + background-color: #ccc; + } +} + +.hide { + display: none; +} diff --git a/app/Resources/static/themes/baggy/css/login.scss b/app/Resources/static/themes/baggy/css/login.scss new file mode 100644 index 000000000..312df670b --- /dev/null +++ b/app/Resources/static/themes/baggy/css/login.scss @@ -0,0 +1,26 @@ +.login { + background-color: #333; + + #main { + padding: 0; + margin: 0; + } + + form { + background-color: #fff; + padding: 1.5em; + box-shadow: 0 1px 8px rgba(0, 0, 0, 0.9); + width: 20em; + position: absolute; + top: 8em; + left: 50%; + margin-left: -10em; + } + + .logo { + position: absolute; + top: 2em; + left: 50%; + margin-left: -55px; + } +} diff --git a/app/Resources/static/themes/baggy/css/media_queries.scss b/app/Resources/static/themes/baggy/css/media_queries.scss new file mode 100755 index 000000000..c33db0b36 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/media_queries.scss @@ -0,0 +1,172 @@ + +@media screen and (max-width: 1050px) { + .entry { + width: 49%; + } + + .entry:nth-child(3n+1) { + margin-left: 1.5%; + } + + .entry:nth-child(2n+1) { + margin-left: 0; + } +} + +@media screen and (max-width: 900px) { + #article { + width: 80%; + } + + .topPosF { + right: 2.5em; + } +} + +@media screen and (max-width: 700px) { + .entry { + width: 100%; + margin-left: 0; + } + + #display-mode { + display: none; + } +} + +@media screen and (max-height: 770px) { + .menu.users, + .menu.internal, + .menu.developer { + display: none; + } +} + +@media screen and (max-width: 500px) { + .entry { + width: 100%; + margin-left: 0; + } + + body > header { + background-color: #333; + position: fixed; + top: 0; + width: 100%; + height: 3em; + z-index: 11; + } + + #links li:last-child { + position: static; + width: auto; + } + + #links li:last-child a::before { + content: none; + } + + .logo { + width: 1.25em; + height: 1.25em; + left: 0; + top: 0; + } + + .login > header { + position: static; + } + + .login form { + width: 100%; + position: static; + margin-left: 0; + } + + .login .logo { + height: auto; + top: 0.5em; + width: 75px; + margin-left: -37.5px; + } + + .desktopHide { + display: block; + position: fixed; + z-index: 20; + top: 0; + right: 0; + border: 0; + width: 2.5em; + height: 2.5em; + cursor: pointer; + background-color: #999; + font-size: 1.2em; + } + + .desktopHide:hover, + .desktopHide:focus { + background-color: #fff; + } + + #links { + display: none; + width: 100%; + height: auto; + padding-top: 3em; + } + + #links.menu--open { + display: block; + } + + footer { + position: static; + margin-right: 3em; + } + + #main { + margin-left: 1.5em; + padding-right: 1.5em; + position: static; + margin-top: 3em; + } + + .card-entry-labels { + display: none; + } + + #article_toolbar .topPosF { + display: none; + } + + #article { + width: 100%; + } + + #article h1 { + font-size: 1.5em; + } + + #article_toolbar a { + padding: 0.3em 0.4em 0.2em; + } + + #display-mode { + display: none; + } + + .popup-form, + #bagit-form, + #search-form { + left: 0; + width: 100%; + border-left: none; + } + + .popup-form form, + #bagit-form form, + #search-form form { + width: 100%; + } +} diff --git a/app/Resources/static/themes/baggy/css/messages.css b/app/Resources/static/themes/baggy/css/messages.css deleted file mode 100755 index bfaf14488..000000000 --- a/app/Resources/static/themes/baggy/css/messages.css +++ /dev/null @@ -1,19 +0,0 @@ -.messages.error.install { - border: 1px solid #c42608; - color: #c00 !important; - background: #fff0ef; - text-align: left; -} - -.messages.notice.install { - border: 1px solid #ebcd41; - color: #000; - background: #fffcd3; - text-align: left; -} - -.messages.success.install { - border: 1px solid #6dc70c; - background: #e0fbcc !important; - text-align: left; -} diff --git a/app/Resources/static/themes/baggy/css/messages.scss b/app/Resources/static/themes/baggy/css/messages.scss new file mode 100755 index 000000000..a388419eb --- /dev/null +++ b/app/Resources/static/themes/baggy/css/messages.scss @@ -0,0 +1,50 @@ +/* ========================================================================== + Messages + ========================================================================== */ + +.messages { + text-align: left; + width: 60%; + margin: auto 17%; + + > * { + display: inline-block; + } + + .install { + text-align: left; + + &.error { + border: 1px solid #c42608; + color: #c00 !important; + background: #fff0ef; + } + + &.notice { + border: 1px solid #ebcd41; + color: #000; + background: #fffcd3; + } + + &.success { + border: 1px solid #6dc70c; + background: #e0fbcc !important; + } + } +} + +.warning { + font-weight: bold; + display: block; + width: 100%; +} + +.more-info { + font-size: 0.85em; + line-height: 1.5; + color: #aaa; + + a { + color: #aaa; + } +} diff --git a/app/Resources/static/themes/baggy/css/pictos.scss b/app/Resources/static/themes/baggy/css/pictos.scss new file mode 100644 index 000000000..2ff019375 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/pictos.scss @@ -0,0 +1,210 @@ +/* ========================================================================== + Pictos + ========================================================================== */ + +@font-face { + font-family: icomoon; + src: url('~icomoon-free-npm/Font/IcoMoon-Free.ttf'); + font-weight: normal; + font-style: normal; +} + +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 1em; /* Preferred icon size */ + width: 1em; + height: 1em; + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + + /* Support for all WebKit browsers. */ + -webkit-font-smoothing: antialiased; + + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Support for Firefox. */ + -moz-osx-font-smoothing: grayscale; + + /* Support for IE. */ + font-feature-settings: 'liga'; + + .md-18 { font-size: 18px; } + .md-24 { font-size: 24px; } + .md-36 { font-size: 36px; } + .md-48 { font-size: 48px; } + + .vertical-align-middle { + vertical-align: middle !important; + } +} + +.icon span, +.icon-image span { + position: absolute; + top: -9999px; +} + +[class^="icon-"]::before, +[class*=" icon-"]::before { + font-family: icomoon; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Enable Ligatures ================ */ + letter-spacing: 0; + -webkit-font-feature-settings: "liga"; + -moz-font-feature-settings: "liga=1"; + -moz-font-feature-settings: "liga"; + -ms-font-feature-settings: "liga" 1; + -o-font-feature-settings: "liga"; + font-feature-settings: "liga"; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-flattr::before { + content: "\ead4"; +} + +.icon-mail::before { + content: "\ea86"; +} + +.icon-up-open::before { + content: "\e80b"; +} + +.icon-star::before { + content: "\e9d9"; +} + +.icon-check::before { + content: "\ea10"; +} + +.icon-link::before { + content: "\e9cb"; +} + +.icon-reply::before { + content: "\e806"; +} + +.icon-menu::before { + content: "\e9bd"; +} + +.icon-clock::before { + content: "\e803"; +} + +.icon-twitter::before { + content: "\ea96"; +} + +.icon-down-open::before { + content: "\e809"; +} + +.icon-trash::before { + content: "\e9ac"; +} + +.icon-delete::before { + content: "\ea0d"; +} + +.icon-power::before { + content: "\ea14"; +} + +.icon-arrow-up-thick::before { + content: "\ea3a"; +} + +.icon-rss::before { + content: "\e808"; +} + +.icon-print::before { + content: "\e954"; +} + +.icon-reload::before { + content: "\ea2e"; +} + +.icon-price-tags::before { + content: "\e936"; +} + +.icon-eye::before { + content: "\e9ce"; +} + +.icon-no-eye::before { + content: "\e9d1"; +} + +.icon-calendar::before { + content: "\e953"; +} + +.icon-time::before { + content: "\e952"; +} + +/* .icon-image class, for image-based icons + ========================================================================== */ + +.icon-image { + background: no-repeat center/80%; + padding-right: 1em !important; + padding-left: 1em !important; +} + +/* Carrot (http://carrot.org) */ +.icon-image--carrot { + background-image: url("../../_global/img/icons/carrot-icon--white.png"); +} + +/* Diaspora */ +.icon-image--diaspora { + background-image: url("../../_global/img/icons/Diaspora-asterisk.svg"); +} + +/* Unmark.it */ +.icon-image--unmark { + background-image: url("../../_global/img/icons/unmark-icon--black.png"); +} + +/* shaarli */ +.icon-image--shaarli { + background-image: url("../../_global/img/icons/shaarli.png"); +} + +/* ========================================================================== + Icon selected + ========================================================================== */ + +.icon-star.fav::before { + color: #fff; +} + +.icon-check.archive::before { + color: #fff; +} diff --git a/app/Resources/static/themes/baggy/css/print.css b/app/Resources/static/themes/baggy/css/print.scss similarity index 91% rename from app/Resources/static/themes/baggy/css/print.css rename to app/Resources/static/themes/baggy/css/print.scss index f7f6a8ad3..a63f62e9e 100755 --- a/app/Resources/static/themes/baggy/css/print.css +++ b/app/Resources/static/themes/baggy/css/print.scss @@ -17,7 +17,7 @@ /* ### Content ### */ /* Hide useless blocks */ - body > header, + body > .logo, #article_toolbar, #links, #sort, @@ -53,11 +53,8 @@ #main { width: 100%; - padding: 0; margin: 0; - margin-left: 0; - padding-right: 0; - padding-bottom: 0; + padding: 0; } #article { diff --git a/app/Resources/static/themes/baggy/css/ratatouille.css b/app/Resources/static/themes/baggy/css/ratatouille.scss similarity index 100% rename from app/Resources/static/themes/baggy/css/ratatouille.css rename to app/Resources/static/themes/baggy/css/ratatouille.scss diff --git a/app/Resources/static/themes/baggy/css/save.scss b/app/Resources/static/themes/baggy/css/save.scss new file mode 100644 index 000000000..ade77b401 --- /dev/null +++ b/app/Resources/static/themes/baggy/css/save.scss @@ -0,0 +1,115 @@ +/* ========================================================================== + "save a link" related styles + ========================================================================== */ + +.popup-form { + background: rgba(0, 0, 0, 0.5); + position: absolute; + top: 0; + left: 10em; + z-index: 20; + height: 100%; + width: 100%; + margin: 0; + margin-top: -30% !important; + padding: 2em; + display: none; + border-left: 1px #eee solid; + + form { + background-color: #fff; + position: absolute; + top: 0; + left: 0; + z-index: 20; + border: 10px solid #000; + width: 400px; + height: 200px; + padding: 2em; + } +} + +#bagit-form-form .addurl { + margin-left: 0; +} + +.closeMessage, +.close-button { + background-color: #000; + color: #fff; + font-size: 1.2em; + line-height: 1.6; + width: 1.6em; + height: 1.6em; + text-align: center; + text-decoration: none; + + &:hover, + &:focus { + background-color: #999; + color: #000; + } +} + +.close-button--popup { + display: inline-block; + position: absolute; + top: 0; + right: 0; + font-size: 1.4em; +} + +.active-current { + background-color: #999; + + &::after { + content: ""; + width: 0; + height: 0; + position: absolute; + border: 10px solid transparent; + border-right-color: #eee; + right: 0; + top: 50%; + margin-top: -10px; + } +} + +.opacity03 { + opacity: 0.3; +} + +.add-to-wallabag-link-after { + background-color: #000; + color: #fff; + padding: 0 3px 2px; +} + +a.add-to-wallabag-link-after { + visibility: hidden; + position: absolute; + opacity: 0; + transition-duration: 2s; + transition-timing-function: ease-out; +} + +#article article a:hover + a.add-to-wallabag-link-after, +a.add-to-wallabag-link-after:hover { + opacity: 1; + visibility: visible; + transition-duration: 0.3s; + transition-timing-function: ease-in; +} + +a.add-to-wallabag-link-after::after { + content: "w"; +} + +#add-link-result { + font-weight: bold; + font-size: 0.9em; +} + +.btn-clickable { + cursor: pointer; +} diff --git a/app/Resources/static/themes/baggy/font/icomoon.eot b/app/Resources/static/themes/baggy/font/icomoon.eot deleted file mode 100644 index 248758fbd..000000000 Binary files a/app/Resources/static/themes/baggy/font/icomoon.eot and /dev/null differ diff --git a/app/Resources/static/themes/baggy/font/icomoon.svg b/app/Resources/static/themes/baggy/font/icomoon.svg deleted file mode 100644 index b1b9c92ac..000000000 --- a/app/Resources/static/themes/baggy/font/icomoon.svg +++ /dev/null @@ -1,501 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/Resources/static/themes/baggy/font/icomoon.ttf b/app/Resources/static/themes/baggy/font/icomoon.ttf deleted file mode 100644 index c03770c6c..000000000 Binary files a/app/Resources/static/themes/baggy/font/icomoon.ttf and /dev/null differ diff --git a/app/Resources/static/themes/baggy/font/icomoon.woff b/app/Resources/static/themes/baggy/font/icomoon.woff deleted file mode 100644 index 121e0bddb..000000000 Binary files a/app/Resources/static/themes/baggy/font/icomoon.woff and /dev/null differ diff --git a/app/Resources/static/themes/baggy/js/init.js b/app/Resources/static/themes/baggy/index.js similarity index 69% rename from app/Resources/static/themes/baggy/js/init.js rename to app/Resources/static/themes/baggy/index.js index 05360a287..5d4480183 100755 --- a/app/Resources/static/themes/baggy/js/init.js +++ b/app/Resources/static/themes/baggy/index.js @@ -1,31 +1,19 @@ -/* jQuery */ import $ from 'jquery'; -/* eslint-disable no-unused-vars */ -/* jquery has default scope */ -import cookie from 'jquery.cookie'; -import ui from 'jquery-ui-browserify'; -/* eslint-enable no-unused-vars */ - -/* Annotations */ -import annotator from 'annotator'; +/* Global imports */ +import '../_global/index'; /* Shortcuts */ -import './shortcuts/main'; -import './shortcuts/entry'; -import '../../_global/js/shortcuts/main'; -import '../../_global/js/shortcuts/entry'; +import './js/shortcuts/main'; +import './js/shortcuts/entry'; /* Tools */ -import { savePercent, retrievePercent } from '../../_global/js/tools'; -import toggleSaveLinkForm from './uiTools'; +import toggleSaveLinkForm from './js/uiTools'; -global.jquery = $; - -$.fn.ready(() => { - const $listmode = $('#listmode'); - const $listentries = $('#list-entries'); +/* Theme style */ +import './css/index.scss'; +$(document).ready(() => { /* ========================================================================== Menu ========================================================================== */ @@ -38,45 +26,12 @@ $.fn.ready(() => { } }); - /* ========================================================================== - List mode or Table Mode - ========================================================================== */ - - $listmode.click(() => { - if ($.cookie('listmode') === 1) { - // Cookie - $.removeCookie('listmode'); - - $listentries.removeClass('listmode'); - $listmode.removeClass('tablemode'); - $listmode.addClass('listmode'); - } else { - // Cookie - $.cookie('listmode', 1, { expires: 365 }); - - $listentries.addClass('listmode'); - $listmode.removeClass('listmode'); - $listmode.addClass('tablemode'); - } - }); - - /* ========================================================================== - Cookie listmode - ========================================================================== */ - - if ($.cookie('listmode') === 1) { - $listentries.addClass('listmode'); - $listmode.removeClass('listmode'); - $listmode.addClass('tablemode'); - } - /* ========================================================================== Add tag panel ========================================================================== */ - $('#nav-btn-add-tag').on('click', () => { - $('.nav-panel-add-tag').toggle(100); + $('.baggy-add-tag').toggle(100); $('.nav-panel-menu').addClass('hidden'); $('#tag_label').focus(); return false; @@ -95,39 +50,6 @@ $.fn.ready(() => { }); } - /* ========================================================================== - Annotations & Remember position - ========================================================================== */ - - if ($('article').length) { - const app = new annotator.App(); - - app.include(annotator.ui.main, { - element: document.querySelector('article'), - }); - - const x = JSON.parse($('#annotationroutes').html()); - app.include(annotator.storage.http, x); - - app.start().then(() => { - app.annotations.load({ entry: x.entryId }); - }); - - $(window).scroll(() => { - const scrollTop = $(window).scrollTop(); - const docHeight = $(document).height(); - const scrollPercent = (scrollTop) / (docHeight); - const scrollPercentRounded = Math.round(scrollPercent * 100) / 100; - savePercent(x.entryId, scrollPercentRounded); - }); - - retrievePercent(x.entryId); - - $(window).resize(() => { - retrievePercent(x.entryId); - }); - } - /** * Close window after adding entry if popup */ @@ -136,6 +58,23 @@ $.fn.ready(() => { window.close(); } + /** + if ($('article').size() > 0) { + const waypoint = new Waypoint({ + element: $('.wallabag-title').get(0), + handler: (direction) => { + console.log(direction); + if (direction === 'down') { + $('aside.tags').fadeIn('slow'); + } else { + $('aside.tags').fadeOut('slow'); + } + }, + offset: 250, + }); + } + */ + /** * Tags autocomplete */ @@ -283,25 +222,24 @@ $.fn.ready(() => { toggleBagit(); }); - const $bagitFormForm = $('#bagit-form-form'); + const bagitFormForm = $('#bagit-form-form'); /* ========================================================================== bag it link and close button ========================================================================== */ // send 'bag it link' form request via ajax - $bagitFormForm.submit((event) => { + bagitFormForm.submit((event) => { $('body').css('cursor', 'wait'); $('#add-link-result').empty(); $.ajax({ - type: $bagitFormForm.attr('method'), - url: $bagitFormForm.attr('action'), - data: $bagitFormForm.serialize(), + type: bagitFormForm.attr('method'), + url: bagitFormForm.attr('action'), + data: bagitFormForm.serialize(), success: function success() { $('#add-link-result').html('Done!'); - $('#plainurl').val(''); - $('#plainurl').blur(''); + $('#plainurl').val('').blur(''); $('body').css('cursor', 'auto'); }, error: function error() { @@ -319,7 +257,7 @@ $.fn.ready(() => { $('article a[href^="http"]').after( () => `' + 'title="add to wallabag">', ); $('.add-to-wallabag-link-after').click((event) => { diff --git a/app/Resources/static/themes/baggy/js/shortcuts/main.js b/app/Resources/static/themes/baggy/js/shortcuts/main.js index aed09aeee..43ebf3be8 100644 --- a/app/Resources/static/themes/baggy/js/shortcuts/main.js +++ b/app/Resources/static/themes/baggy/js/shortcuts/main.js @@ -1,3 +1,6 @@ +import $ from 'jquery'; +import Mousetrap from 'mousetrap'; + $(document).ready(() => { Mousetrap.bind('s', () => { $('#search').trigger('click'); diff --git a/app/Resources/static/themes/material/css/article.scss b/app/Resources/static/themes/material/css/article.scss new file mode 100644 index 000000000..7d0bdac76 --- /dev/null +++ b/app/Resources/static/themes/material/css/article.scss @@ -0,0 +1,174 @@ +/* ========================================================================== + Article + ========================================================================== */ + +#article { + font-size: 20px; + margin: 0 auto; + max-width: 45em; + + article { + color: #424242; + font-size: 18px; + line-height: 1.7em; + + h1, + h2, + h3, + h4, + h5, + h6 { + color: #212121; + + strong { + font-weight: 500; + } + } + + h6 { + font-size: 1.2rem; + } + + h5 { + font-size: 1.6rem; + } + + h4 { + font-size: 1.9rem; + } + + h3 { + font-size: 2.2rem; + } + + h2 { + font-size: 2.5rem; + } + + h1 { + font-size: 2.7rem; + } + + a { + border-bottom: 1px dotted #03a9f4; + text-decoration: none; + } + + a:hover { + border-bottom-style: solid; + } + + ul { + padding-left: 30px; + } + + ul, + ul li { + list-style-type: disc; + } + + blockquote { + font-style: italic; + } + + strong { + font-weight: bold; + } + } + + img, + figure { + max-width: 100%; + height: auto; + } + + pre { + box-sizing: border-box; + margin: 0 0 1.75em; + border: #e3f2fd 1px solid; + width: 100%; + padding: 10px; + font-family: monospace; + font-size: 0.8em; + white-space: pre; + overflow: auto; + background: #f5f5f5; + border-radius: 3px; + } + + > header > h1 { + font-size: 2em; + margin: 2.1rem 0 0.68rem; + } + + aside { + .tools { + font-size: 0.8em; + display: flex; + flex-flow: row wrap; + margin: 0 auto; + + li { + display: inline-flex; + vertical-align: middle; + } + + a { + color: #000; + text-decoration: none; + } + } + + #list { + float: right; + margin: 0 15px 10px; + } + + .chip { + background-color: $blueAccentColor; + padding: 0 15px 0 10px; + margin: auto 2px; + + a, + i { + color: #fff; + } + } + } +} + +.reader-mode { + width: 95px !important; + transition: width 0.2s ease; + + .collapsible-body { + height: 0; + overflow: hidden; + } + + span { + opacity: 0; + transition: opacity 0.2s ease; + } +} + +.reader-mode:hover { + width: 240px !important; + + .collapsible-body { + height: auto; + } + + span { + opacity: 1; + } +} + +.progress { + position: fixed; + top: 0; + width: 100%; + height: 3px; + margin: 0; + z-index: 9999; +} diff --git a/app/Resources/static/themes/material/css/cards.scss b/app/Resources/static/themes/material/css/cards.scss new file mode 100644 index 000000000..18ef6e602 --- /dev/null +++ b/app/Resources/static/themes/material/css/cards.scss @@ -0,0 +1,186 @@ +/* ========================================================================== + Cards + ========================================================================== */ + +main { + #content { + padding: 0 0.5rem; + } + + ul.row { + padding: 0 0.75rem; + } +} + +.data .card .card-body { + height: 19em; + overflow: hidden; +} + +.card { + .card-content .card-title, + .card-reveal .card-title { + line-height: 22.8px; + max-height: 80px; + font-size: 19px; + font-family: roberto, "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #313131; + } + + .card-content .activator, + .card-reveal .activator { + cursor: pointer; + font-family: "Material Icons"; + } + + .card-content i.right, + .card-reveal i.right { + margin-left: 0; + } + + .card-content .original { + line-height: 24px; + font-size: 15px; + } + + .card-entry-labels { + position: absolute; + top: 10px; + z-index: 90; + max-width: 50%; + } + + .card-entry-labels-hidden { + margin: 2.5px auto; + } + + .card-entry-labels-hidden li { + display: inline-block; + background-color: $blueAccentColor; + margin: 0 5px; + padding: 5px 12px; + border-radius: 3px; + color: #fff; + max-height: 2em; + max-width: calc(100% - 15px); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .card-entry-labels-hidden li { + display: inline-block; + background-color: $blueAccentColor; + margin: 0 5px; + padding: 5px 12px; + border-radius: 3px; + color: #fff; + max-height: 2em; + max-width: calc(100% - 15px); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .card-content .estimatedTime { + margin-bottom: 10px; + } + + .card-action { + padding: 10px 5px 10px 15px; + + ul.links { + margin: 0; + font-size: 24px; + line-height: 24px; + } + + a { + color: #fff; + margin: 0; + } + + a:hover { + color: #fff; + } + + ul.tools li a.tool { + margin-right: 5px !important; + } + + .reading-time { + display: inline-flex; + vertical-align: middle; + } + } + + .card-entry-labels li, + .card-tag-labels li { + margin: 10px 10px 10px auto; + padding: 5px 12px 5px 16px !important; + background-color: $blueAccentColor; + border-radius: 0 3px 3px 0; + color: #fff; + cursor: default; + max-height: 2em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .card-image { + height: 10em; + } + + .card-fullimage { + height: 13.5em; + } + + .card-image .preview, + .card-fullimage .preview { + height: 14em; + background: no-repeat 50%/cover; + } + + &.sw { + max-width: 370px; + margin-left: auto; + margin-right: auto; + } +} + +a.original { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; +} + +.card-entry-tags a, +.card-entry-labels a, +.card-tag-labels a, +.card-entry-labels-hidden a, +#list .chip a { + text-decoration: none; + font-weight: normal; + color: #fff; +} + +.card-stacked { + &:hover ul.tools-list { + display: block; + } + + ul.tools-list { + display: none; + } +} + +.quickstart .card .card-action a, +.quickstart .card .card-action a:hover { + color: #fff !important; +} + +.settings .div_tabs { + padding-bottom: 15px; +} diff --git a/app/Resources/static/themes/material/css/entries.scss b/app/Resources/static/themes/material/css/entries.scss new file mode 100644 index 000000000..b6a46a9e1 --- /dev/null +++ b/app/Resources/static/themes/material/css/entries.scss @@ -0,0 +1,87 @@ +/* ========================================================================== + * Entries + * ========================================================================== */ + +.results { + height: 1em; + + .nb-results, + .pagination { + margin: 15px 15px 0; + } + + .nb-results { + display: inline-flex; + } + + a { + color: #444; + } +} + +.pagination { + float: right; + + ul { + margin: 0 !important; + + .prev.disabled, + .next.disabled { + display: none; + } + } + + li { + padding: 0; + } + + a { + padding: 0 10px; + height: 30px; + display: block; + } + + .disabled { + margin-right: 10px; + margin-left: 10px; + } + + li.active span { + padding: 0 10px; + height: 30px; + display: block; + color: #fff; + } +} + +.page-footer .footer-copyright { + min-width: 50px; + height: auto !important; + line-height: 1em !important; + + p { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; + } +} + +.hidden { + display: none; +} + +.picker__date-display { + display: none; +} + +footer { + &.page-footer { + margin-top: 10px; + padding-top: 0; + } + + .row { + margin-bottom: 10px; + } +} diff --git a/app/Resources/static/themes/material/css/filters.scss b/app/Resources/static/themes/material/css/filters.scss new file mode 100644 index 000000000..299dad3d4 --- /dev/null +++ b/app/Resources/static/themes/material/css/filters.scss @@ -0,0 +1,15 @@ +/* ========================================================================== + * Filters slider + * ========================================================================== */ + +#filters { + button { + padding: 0; + width: 100%; + } + + div.with-checkbox { + height: 3rem; + margin-top: 0; + } +} diff --git a/app/Resources/static/themes/material/css/fonts.scss b/app/Resources/static/themes/material/css/fonts.scss new file mode 100644 index 000000000..743f1a841 --- /dev/null +++ b/app/Resources/static/themes/material/css/fonts.scss @@ -0,0 +1,13 @@ +/* ========================================================================== + * Fonts + * ========================================================================== */ + +/** + * Icomoon + */ +@font-face { + font-family: icomoon; + src: url("~icomoon-free-npm/Font/IcoMoon-Free.ttf"); + font-weight: normal; + font-style: normal; +} diff --git a/app/Resources/static/themes/material/css/icons.scss b/app/Resources/static/themes/material/css/icons.scss new file mode 100644 index 000000000..268e6dca4 --- /dev/null +++ b/app/Resources/static/themes/material/css/icons.scss @@ -0,0 +1,185 @@ +/* ========================================================================== + * Icons + * ========================================================================== */ + +/** + * + * Material icons + * + */ +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; /* Preferred icon size */ + width: 1em; + height: 1em; + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + + /* Support for all WebKit browsers. */ + -webkit-font-smoothing: antialiased; + + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Support for Firefox. */ + -moz-osx-font-smoothing: grayscale; + + /* Support for IE. */ + font-feature-settings: 'liga'; + + .md-18 { + font-size: 18px; + } + + .md-24 { + font-size: 24px; + } + + .md-36 { + font-size: 36px; + } + + .md-48 { + font-size: 48px; + } + + .md-dark { + color: rgba(0, 0, 0, 0.54); + + .md-inactive { + color: rgba(0, 0, 0, 0.26); + } + } + + .md-light { + color: rgba(255, 255, 255, 1); + + .md-inactive { + color: rgba(255, 255, 255, 0.3); + } + } +} + +/** + * + * Icomoon icons + * + */ +[class^="icon-"]::before, +[class*=" icon-"]::before { + font-family: icomoon; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + background-size: 24px; + + /* Enable Ligatures ================ */ + letter-spacing: 0; + font-feature-settings: "liga"; +} + +.icon-eye::before { + content: "\e9ce"; +} + +.icon-no-eye::before { + content: "\e9d1"; +} + +.icon-calendar::before { + content: "\e953"; +} + +.icon-mail::before { + content: "\ea86"; +} + +.icon-time::before { + content: "\e952"; +} + +a.icon-image { + background-repeat: no-repeat; + padding-right: 0.4em !important; + padding-left: 1em !important; + margin-left: 25px; + + &::before { + content: ""; + display: block; + width: 24px; + height: 24px; + float: left; + margin: 0 6px 0 0; + } + + &.carrot::before { + background: url("../../_global/img/icons/carrot-icon--black.png") no-repeat center/90%; + } + + &.diaspora::before { + background: url("../../_global/img/icons/diaspora-icon--black.png") no-repeat center/80%; + } + + &.unmark::before { + background: url("../../_global/img/icons/unmark-icon--black.png") no-repeat center/80%; + } + + &.shaarli::before { + background: url("../../_global/img/icons/shaarli.png") no-repeat center/80%; + } +} + +.icon-google-plus2::before { + content: "\ea89"; +} + +.icon-facebook2::before { + content: "\ea8d"; +} + +.icon-twitter::before { + content: "\ea96"; +} + +.icon-apple::before { + content: "\eabf"; +} + +.icon-android::before { + content: "\eac1"; +} + +.icon-chrome::before { + content: "\eae5"; +} + +.icon-firefox::before { + content: "\eae6"; +} + +.icon-link::before { + content: "\e9cb"; +} + +footer [class^="icon-"], +footer [class*=" icon-"] { + font-size: 2em; + transition: text-shadow 0.2s ease; + padding-right: 10px; +} + +footer [class^="icon-"]:hover, +footer [class*=" icon-"]:hover { + text-shadow: 0 0 10px rgba(0, 0, 0, 0.3); +} diff --git a/app/Resources/static/themes/material/css/index.scss b/app/Resources/static/themes/material/css/index.scss new file mode 100644 index 000000000..285a6504d --- /dev/null +++ b/app/Resources/static/themes/material/css/index.scss @@ -0,0 +1,17 @@ +@import 'variables'; + +/* Style */ +@import 'article'; +@import 'cards'; +@import 'entries'; +@import 'filters'; +@import 'layout'; +@import 'nav'; +@import 'sidenav'; +@import 'various'; + +/* Tools */ +@import 'fonts'; +@import 'icons'; +@import 'print'; +@import 'media_queries'; diff --git a/app/Resources/static/themes/material/css/layout.scss b/app/Resources/static/themes/material/css/layout.scss new file mode 100755 index 000000000..8b8b06e60 --- /dev/null +++ b/app/Resources/static/themes/material/css/layout.scss @@ -0,0 +1,50 @@ +/* ========================================================================== + Layout + ========================================================================== */ + +body { + display: flex; + min-height: 100vh; + flex-direction: column; + background: #fafafa; + + &.login main { + padding: 0; + min-height: 100vh; + } +} + +.border-bottom { + border-bottom: 1px solid #ddd; +} + +nav, +main, +footer { + padding-left: 240px; +} + +main, +#content, +.valign-wrapper { + height: 100%; +} + +#main { + flex: 1 0 auto; + + .logo { + a { + height: 100pt; + } + + img { + height: 100pt; + width: 100pt; + } + + &:hover { + background: transparent; + } + } +} diff --git a/app/Resources/static/themes/material/css/media_queries.scss b/app/Resources/static/themes/material/css/media_queries.scss new file mode 100644 index 000000000..96f344943 --- /dev/null +++ b/app/Resources/static/themes/material/css/media_queries.scss @@ -0,0 +1,149 @@ +/* ========================================================================== + Media queries + ========================================================================== */ + +@media only screen and (max-width: 992px) { + header, + main, + footer { + padding-left: 0; + } + + nav, + main, + footer { + padding-left: 0; + } + + .pagination { + width: auto; + } + + .nav-panels .action { + padding-right: 0.75rem; + } + + .nav-panel-buttom { + justify-content: space-around; + } + + #article { + max-width: 35em; + margin-left: auto; + margin-right: auto; + font-size: 18px; + + > header > h1 { + font-size: 1.33em; + } + } + + .reader-mode { + width: 240px !important; + + span { + opacity: 1; + } + } + + .tabs { + display: inline-block; + height: auto; + } + + .tab { + min-width: 100%; + } + + .indicator { + display: none; + } + + .pagination li.prev, + .pagination li.next { + width: auto; + } + + .drag-target + .drag-target { + height: 50%; + } + + .drag-target + .drag-target + .drag-target { + top: 50%; + } +} + +@media only screen and (min-width: 1200px) and (max-width: 1650px) { + .row .col.l3 { + width: 33.33333%; + margin-left: 0; + } +} + +@media only screen and (min-width: 993px) and (max-width: 1200px) { + .row { + .col.l1 { + width: 25%; + margin-left: 0; + } + + .col.l2 { + width: 33.33333%; + margin-left: 0; + } + + .col.l3 { + width: 41.66667%; + margin-left: 0; + } + + .col.l4 { + width: 50%; + margin-left: 0; + } + + .col.l5 { + width: 58.33333%; + margin-left: 0; + } + + .col.l6 { + width: 66.66667%; + margin-left: 0; + } + + .col.l7 { + width: 75%; + margin-left: 0; + } + + .col.l8 { + width: 83.33333%; + margin-left: 0; + } + + .col.l9 { + width: 91.66667%; + margin-left: 0; + } + + .col.l10 { + width: 100%; + margin-left: 0; + } + } +} + +@media only screen and (max-width: 350px) { + .nb-results { + display: none; + } + + main ul.row { + padding: 0; + } + + .row .col { + padding: 0; + } +} diff --git a/app/Resources/static/themes/material/css/nav.scss b/app/Resources/static/themes/material/css/nav.scss new file mode 100644 index 000000000..1a25a5beb --- /dev/null +++ b/app/Resources/static/themes/material/css/nav.scss @@ -0,0 +1,106 @@ + +/* ========================================================================== + Nav + ========================================================================== */ + +nav { + height: auto; + + input { + color: #aaa; + } + + ul a:hover { + background-color: initial; + } +} + +.nav-wrapper { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + min-height: 64px; + + .button-collapse { + padding: 0 15px; + } +} + +.nav-input { + display: none; +} + +.nav-panel-buttom { + display: flex; + flex-grow: 1; + justify-content: flex-end; + + li { + max-height: 64px; + } +} + +.nav-panel-add .add, +.nav-panel-search .search, +.nav-panels .close { + color: #444 !important; +} + +.nav-panels { + transition: background 0.2s ease; + + .action { + padding-left: 0.75rem; + font-size: 2.1rem; + white-space: nowrap; + } + + .input-field input { + display: block; + line-height: inherit; + padding-left: 4rem !important; + width: calc(100% - 8rem); + height: 4.1rem; + } + + .input-field input:focus { + background-color: #fff; + border: 0; + box-shadow: none; + color: #444; + } +} + +.input-field { + &.nav-panel-add label, + &.nav-panel-search label { + left: 1rem; + } + + &.nav-panel-add .close, + &.nav-panel-search .close { + position: absolute; + top: 0; + right: 1rem; + color: transparent; + cursor: pointer; + font-size: 2rem; + transition: 0.3s color; + } + + &.nav-panel-add, + &.nav-panel-add form, + &.nav-panel-search, + &.nav-panel-search form { + display: flex; + flex: 1; + } +} + +#button_filters { + display: none; +} + +#button_export { + display: none; +} diff --git a/app/Resources/static/themes/material/css/print.css b/app/Resources/static/themes/material/css/print.scss similarity index 94% rename from app/Resources/static/themes/material/css/print.css rename to app/Resources/static/themes/material/css/print.scss index 98505aae0..967a8c2b8 100755 --- a/app/Resources/static/themes/material/css/print.css +++ b/app/Resources/static/themes/material/css/print.scss @@ -64,11 +64,8 @@ #main { width: 100%; - padding: 0; margin: 0; - margin-left: 0; - padding-right: 0; - padding-bottom: 0; + padding: 0; } #article { diff --git a/app/Resources/static/themes/material/css/sidenav.scss b/app/Resources/static/themes/material/css/sidenav.scss new file mode 100644 index 000000000..b430077e5 --- /dev/null +++ b/app/Resources/static/themes/material/css/sidenav.scss @@ -0,0 +1,41 @@ +/* ========================================================================== + Side-nav + ========================================================================== */ + +.side-nav { + width: 240px; + + li { + padding: 0; + } + + a { + margin: 0 1rem; + } + + &.fixed a { + font-size: 13px; + line-height: 44px; + height: 44px; + } + + .collapsible-header, + &.fixed .collapsible-header { + height: 45px; + line-height: 44px; + padding: 0 20px; + } + + > li.logo { + line-height: 0; + text-align: center; + } +} + +.bold > a { + font-weight: bold; +} + +span.numberItems { + float: right; +} diff --git a/app/Resources/static/themes/material/css/variables.scss b/app/Resources/static/themes/material/css/variables.scss new file mode 100644 index 000000000..25e22aca0 --- /dev/null +++ b/app/Resources/static/themes/material/css/variables.scss @@ -0,0 +1,5 @@ +/* ========================================================================== + Variables + ========================================================================== */ + +$blueAccentColor: rgba(0, 151, 167, 0.85); diff --git a/app/Resources/static/themes/material/css/various.scss b/app/Resources/static/themes/material/css/various.scss new file mode 100644 index 000000000..6a6f52f9d --- /dev/null +++ b/app/Resources/static/themes/material/css/various.scss @@ -0,0 +1,24 @@ +/* ========================================================================== + * Various + * ========================================================================== */ + +div.settings div.file-field { + /* force height on non-input field in the settings page */ + div, + ul { + margin-top: 40px; + } + + /* but avoid to kill all file input */ + div { + margin-top: inherit; + } +} + +.input-field label.active { + font-size: 1rem; +} + +nav .input-field input { + margin: 0; +} diff --git a/app/Resources/static/themes/material/js/init.js b/app/Resources/static/themes/material/index.js similarity index 57% rename from app/Resources/static/themes/material/js/init.js rename to app/Resources/static/themes/material/index.js index 0b2832c06..d6afbb8a3 100755 --- a/app/Resources/static/themes/material/js/init.js +++ b/app/Resources/static/themes/material/index.js @@ -1,21 +1,21 @@ -/* jQuery */ import $ from 'jquery'; -/* Annotations */ -import annotator from 'annotator'; +/* Materialize imports */ +import 'materialize-css/dist/css/materialize.css'; +import 'materialize-css/dist/js/materialize'; + +/* Global imports */ +import '../_global/index'; /* Tools */ -import { savePercent, retrievePercent, initFilters, initExport } from '../../_global/js/tools'; +import { initExport, initFilters } from './js/tools'; /* Import shortcuts */ -import './shortcuts/main'; -import './shortcuts/entry'; -import '../../_global/js/shortcuts/main'; -import '../../_global/js/shortcuts/entry'; +import './js/shortcuts/main'; +import './js/shortcuts/entry'; -require('materialize'); // eslint-disable-line - -global.jQuery = $; +/* Theme style */ +import './css/index.scss'; $(document).ready(() => { // sideNav @@ -30,6 +30,7 @@ $(document).ready(() => { formatSubmit: 'dd/mm/yyyy', hiddenName: true, format: 'dd/mm/yyyy', + container: 'body', }); initFilters(); initExport(); @@ -74,37 +75,4 @@ $(document).ready(() => { const scrollPercent = (s / (d - c)) * 100; $('.progress .determinate').css('width', `${scrollPercent}%`); }); - -/* ========================================================================== - Annotations & Remember position - ========================================================================== */ - - if ($('article').length) { - const app = new annotator.App(); - const x = JSON.parse($('#annotationroutes').html()); - - app.include(annotator.ui.main, { - element: document.querySelector('article'), - }); - - app.include(annotator.storage.http, x); - - app.start().then(() => { - app.annotations.load({ entry: x.entryId }); - }); - - $(window).scroll(() => { - const scrollTop = $(window).scrollTop(); - const docHeight = $(document).height(); - const scrollPercent = (scrollTop) / (docHeight); - const scrollPercentRounded = Math.round(scrollPercent * 100) / 100; - savePercent(x.entryId, scrollPercentRounded); - }); - - retrievePercent(x.entryId); - - $(window).resize(() => { - retrievePercent(x.entryId); - }); - } }); diff --git a/app/Resources/static/themes/material/js/tools.js b/app/Resources/static/themes/material/js/tools.js new file mode 100644 index 000000000..39398fd8a --- /dev/null +++ b/app/Resources/static/themes/material/js/tools.js @@ -0,0 +1,24 @@ +import $ from 'jquery'; + +function initFilters() { + // no display if filters not available + if ($('div').is('#filters')) { + $('#button_filters').show(); + $('.js-filters-action').sideNav({ edge: 'right' }); + $('#clear_form_filters').on('click', () => { + $('#filters input').val(''); + $('#filters :checked').removeAttr('checked'); + return false; + }); + } +} + +function initExport() { + // no display if export not available + if ($('div').is('#export')) { + $('#button_export').show(); + $('.js-export-action').sideNav({ edge: 'right' }); + } +} + +export { initExport, initFilters }; diff --git a/app/config/config.yml b/app/config/config.yml index 4f4fb900e..e0d6b860b 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -3,6 +3,9 @@ imports: - { resource: security.yml } - { resource: services.yml } +parameters: + use_webpack_dev_server: true + framework: #esi: ~ translator: diff --git a/app/config/config_prod.yml b/app/config/config_prod.yml index 5a4dd69e2..65b02d660 100644 --- a/app/config/config_prod.yml +++ b/app/config/config_prod.yml @@ -1,9 +1,9 @@ imports: - { resource: config.yml } -#framework: -# cache: -# system: cache.adapter.apcu +framework: + assets: + # json_manifest_path: '%kernel.root_dir%/../web/bundles/wallabagcore/manifest.json' #doctrine: # orm: diff --git a/app/config/webpack/common.js b/app/config/webpack/common.js new file mode 100644 index 000000000..4f5739f01 --- /dev/null +++ b/app/config/webpack/common.js @@ -0,0 +1,40 @@ +const path = require('path'); +const webpack = require('webpack'); +const StyleLintPlugin = require('stylelint-webpack-plugin'); + +const rootDir = path.resolve(__dirname, '../../../'); + +module.exports = function() { + return { + entry: { + material: path.join(rootDir, './app/Resources/static/themes/material/index.js'), + baggy: path.join(rootDir, './app/Resources/static/themes/baggy/index.js'), + }, + + output: { + filename: '[name].js', + path: path.resolve(rootDir, 'web/bundles/wallabagcore'), + publicPath: '/bundles/wallabagcore/', + }, + plugins: [ + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery', + 'window.$': 'jquery', + 'window.jQuery': 'jquery' + }), + new StyleLintPlugin({ + configFile: '.stylelintrc', + failOnError: false, + quiet: false, + context: 'app/Resources/static/themes', + files: '**/*.scss', + }), + ], + resolve: { + alias: { + jquery: path.join(rootDir, 'node_modules/jquery/dist/jquery.js') + } + }, + }; +}; diff --git a/app/config/webpack/dev.js b/app/config/webpack/dev.js new file mode 100644 index 000000000..771df65bd --- /dev/null +++ b/app/config/webpack/dev.js @@ -0,0 +1,62 @@ +const webpackMerge = require('webpack-merge'); +const webpack = require('webpack'); +const path = require('path'); +const commonConfig = require('./common.js'); + +module.exports = function () { + return webpackMerge(commonConfig(), { + devtool: 'eval-source-map', + output: { + filename: '[name].dev.js' + }, + + devServer: { + hot: true, + // enable HMR on the server + + contentBase: './web', + // match the output path + }, + plugins: [ + new webpack.HotModuleReplacementPlugin(), + ], + module: { + rules: [ + { + enforce: 'pre', + test: /\.js$/, + loader: 'eslint-loader', + exclude: /node_modules/, + }, + { + test: /\.js$/, + exclude: /(node_modules)/, + use: { + loader: 'babel-loader', + options: { + presets: ['env'] + } + } + }, + { + test: /\.(s)?css$/, + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { + importLoaders: 1, + } + }, + 'postcss-loader', + 'sass-loader' + ] + }, + { + test: /\.(jpg|png|gif|svg|eot|ttf|woff|woff2)$/, + use: 'url-loader' + }, + ] + }, + }) +}; diff --git a/app/config/webpack/prod.js b/app/config/webpack/prod.js new file mode 100644 index 000000000..ef41ab990 --- /dev/null +++ b/app/config/webpack/prod.js @@ -0,0 +1,99 @@ +const webpack = require('webpack'); +const webpackMerge = require('webpack-merge'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const ManifestPlugin = require('webpack-manifest-plugin'); + +const commonConfig = require('./common.js'); + +module.exports = function() { + return webpackMerge(commonConfig(), { + output: { + filename: '[name].js' + }, + devtool: 'source-map', + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify('production') + } + }), + new webpack.optimize.UglifyJsPlugin({ + beautify: false, + mangle: { + screw_ie8: true, + keep_fnames: true + }, + compress: { + screw_ie8: true, + warnings: false + }, + comments: false + }), + new ExtractTextPlugin('[name].css'), + new ManifestPlugin({ + fileName: 'manifest.json', + }) + ], + module: { + rules: [ + { + enforce: 'pre', + test: /\.js$/, + loader: 'eslint-loader', + exclude: /node_modules/, + }, + { + test: /\.js$/, + exclude: /(node_modules)/, + use: { + loader: 'babel-loader', + options: { + presets: ['env'] + } + } + }, + { + test: /\.(s)?css$/, + use: ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: [ + { + loader: 'css-loader', + options: { + importLoaders: 1, + minimize: { + discardComments: { + removeAll: true + }, + core: true, + minifyFontValues: true + } + } + }, + 'postcss-loader', + 'sass-loader' + ] + }) + }, + { + test: /\.(jpg|png|gif|svg)$/, + use: { + loader: 'file-loader', + options: { + name: 'img/[name].[ext]', + } + } + }, + { + test: /\.(eot|ttf|woff|woff2)$/, + use: { + loader: 'file-loader', + options: { + name: 'fonts/[name].[ext]', + } + } + } + ] + }, + }) +}; diff --git a/docs/en/developer/front_end.rst b/docs/en/developer/front_end.rst new file mode 100644 index 000000000..40f18a420 --- /dev/null +++ b/docs/en/developer/front_end.rst @@ -0,0 +1,33 @@ +Tips for front-end developers +============================= + +Starting from version 2.3, wallabag uses webpack to bundle its assets. + +Dev mode +-------- + +If the server runs in dev mode, you need to run ``yarn run build:dev`` to generate the outputted javascript files for each theme. These are named ``%theme%.dev.js`` and are ignored by git. You need to relaunch ``yarn run build:dev`` for each change made to one of the assets files (js, css, pictures, fonts,...). + +Live reload +----------- + +Webpack brings support for live reload, which means you don't need to regenerate the assets file for each change neither reload the page manually. Changes are applied automatically in the web page. Just set the ``use_webpack_dev_server`` setting to ``true`` in ``app/config/config.yml`` and run ``yarn run watch`` and you're good to go. + +.. note:: + + Don't forget to put back ``use_webpack_dev_server`` to ``false`` when not using the live reload feature. + +Production builds +----------------- + +When you want to commit your changes, build them in production environment by using ``yarn run build:prod``. This will build all the assets needed for wallabag. To test that it properly works, you'll need to have a server in production mode, for instance with ``bin/console server:run -e=prod``. + +.. note:: + + Don't forget to generate production builds before committing ! + + +Code style +---------- + +Code style is checked by two tools : stylelint for (S)CSS and eslint for JS. ESlint config is based on the Airbnb base preset. diff --git a/docs/fr/developer/front-end.rst b/docs/fr/developer/front-end.rst new file mode 100644 index 000000000..714df08b6 --- /dev/null +++ b/docs/fr/developer/front-end.rst @@ -0,0 +1,33 @@ +Conseils pour développeurs front-end +==================================== + +Depuis la version 2.3, wallabag utilise webpack pour générer ses assets. + +Mode développeur +---------------- + +Si le serveur fonctionne en mode dev, vous devez lancer la commande ``yarn run build:dev`` pour générer les fichiers de sortie javascript pour chaque thème. Ils sont nommés ``%theme%.dev.js`` et sont ignorés par git. Vous devez relancer la commande ``yarn run build:dev`` pour chaque changement que vous effectuez dans les fichiers assets (js, css, images, polices,...). + +Live reload +----------- + +Webpack apporte le support pour la fonctionnalité de live reload, ce qui signifie que vous n'avez pas besoin de regénérer manuellement le fichier de sortie javascript ni de rafraichir la page dans votre navigateur. Les changements sont appliqués automatiquement. Vous avez juste besoin de mettre le paramètre ``use_webpack_dev_server`` à ``true`` dans ``app/config/config.yml`` et de lancer ``yarn run watch`` pour que cela soit actif. + +.. note:: + + N'oubliez pas de remettre ``use_webpack_dev_server`` à ``false`` lorsque vous n'utilisez pas la fonctionnalité de live reload. + +Production builds +----------------- + +Lorsque vous committez vos changements, vous devez les compiler dans un environnement de production en exécutant ``yarn run build:prod``. Cela compilera tous les assets nécessaires pour wallabag. Pour tester que cela fonctionne proprement, vous devrez avoir un serveur en mode de production, par exemple avec ``bin/console server:run -e=prod``. + +.. note:: + + N'oubliez pas de générer des fichiers en mode production avant de committer ! + + +Code style +---------- + +Le style de code est vérifié par deux outils : stylelint pour le (S)CSS et eslint pour le JS. La configuration ESlint config est basée sur le preset Airbnb base. diff --git a/package.json b/package.json index 209c46c6c..8b81f89bb 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,13 @@ { "name": "wallabag", - "version": "2.1.0", + "version": "2.2.2", "description": "wallabag is a self hostable application for saving web pages", - "main": "index.js", "private": true, "directories": { "doc": "docs" }, "engines": { - "node": ">0.12" - }, - "browser": { - "jquery": "./node_modules/jquery/dist/jquery.js", - "jQuery": "./node_modules/jquery/dist/jquery.js", - "materialize": "./node_modules/materialize-css/bin/materialize.js" - }, - "browserify-shim": { - "jquery": { - "exports": "$" - }, - "materialize": "materialize", - "jquery-ui": { - "depends": "jquery", - "exports": null - } - }, - "browserify": { - "transform": [ - "browserify-shim" - ] + "node": ">4.8" }, "repository": { "type": "git", @@ -57,52 +36,49 @@ "url": "https://github.com/wallabag/wallabag/issues" }, "devDependencies": { - "annotator": "git://github.com/wallabag/annotator.git#0f076c7d371ed25eb0793346f46982d90f2c4c85", - "autoprefixer": "^6.3.6", - "babel-eslint": "^6.1.2", - "babel-preset-es2015": "^6.14.0", - "babelify": "^7.3.0", - "browserify": "^13.0.0", - "browserify-shim": "^3.8.12", - "cssnano": "^3.5.2", - "es6-promise": "^3.2.1", - "eslint": "^3.7.1", - "eslint-config-airbnb-base": "^8.0.0", - "eslint-plugin-import": "^1.16.0", - "grunt": ">=0.4.0", - "grunt-browserify": "^5.0.0", - "grunt-cli": "^1.2.0", - "grunt-contrib-clean": "^1.0.0", - "grunt-contrib-concat": "^1.0.0", - "grunt-contrib-copy": "^1.0.0", - "grunt-contrib-symlink": "^1.0.0", - "grunt-contrib-uglify": "^1.0.0", - "grunt-contrib-watch": "^1.0.0", - "grunt-eslint": "^19.0.0", - "grunt-postcss": "^0.8.0", - "grunt-stylelint": "^0.6.0", - "hammerjs": "^2.0.6", - "icomoon-free-npm": "0.0.0", - "jquery": "^2.2.4", - "jquery-ui-browserify": "^1.11.0-pre-seelio", - "jquery.cookie": "^1.4.1", - "jquery.tinydot": "^0.2.1", - "load-grunt-tasks": "^3.4.1", - "material-design-icons-iconfont": "^3.0.0", - "materialize-css": "0.97.5", - "npm": "^3.8.3", - "pickadate": "^3.5.6", - "pixrem": "^3.0.0", - "postcss-cssnext": "^2.5.1", - "prismjs": "^1.4.1", - "ptsans-npm-webfont": "0.0.4", - "roboto-fontface": "^0.6.0", - "stylelint": "^7.3.1", - "stylelint-config-standard": "^13.0.2", - "through": "^2.3.8" + "autoprefixer": "^6.7.7", + "babel-core": "^6.24.1", + "babel-eslint": "^7.2.3", + "babel-loader": "^7.0.0", + "babel-preset-env": "^1.4.0", + "css-loader": "^0.28.0", + "eslint": "^3.19.0", + "eslint-config-airbnb-base": "^11.1.3", + "eslint-loader": "^1.7.1", + "eslint-plugin-import": "^2.2.0", + "extract-text-webpack-plugin": "^2.1.0", + "file-loader": "^0.11.0", + "lato-font": "^3.0.0", + "node-sass": "^4.5.2", + "postcss-loader": "^1.3.3", + "sass-loader": "^6.0.3", + "style-loader": "^0.16.1", + "stylelint": "^7.9.0", + "stylelint-config-standard": "^16.0.0", + "stylelint-webpack-plugin": "^0.7.0", + "url-loader": "^0.5.8", + "webpack": "^2.3.2", + "webpack-dev-server": "^2.4.4", + "webpack-manifest-plugin": "^1.1.0", + "webpack-merge": "^4.1.0" }, "dependencies": { - "jr-qrcode": "^1.0.5", - "mousetrap": "^1.6.0" + "annotator": "git://github.com/wallabag/annotator.git#0f076c7d371ed25eb0793346f46982d90f2c4c85", + "hammerjs": "^2.0.8", + "icomoon-free-npm": "^0.0.0", + "jquery": "^2.1.4", + "jquery.cookie": "^1.4.1", + "jr-qrcode": "^1.0.7", + "material-design-icons-iconfont": "^3.0.3", + "materialize-css": "^0.98.1", + "mousetrap": "^1.6.0", + "ptsans-npm-webfont": "^0.0.4", + "roboto-fontface": "^0.7.0", + "waypoints": "^4.0.1" + }, + "scripts": { + "watch": "./node_modules/.bin/webpack-dev-server --env=dev", + "build:dev": "./node_modules/.bin/webpack --env=dev", + "build:prod": "./node_modules/.bin/webpack --env=prod" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 000000000..5d1463143 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: function () { + return [ + require('autoprefixer'), + ]; + } +}; diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig index 859b166b1..bdd44b544 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig @@ -17,9 +17,9 @@
{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}
{% if (entry.previewPicture is null or listMode == 1) %}
-