diff --git a/.dockerignore b/.dockerignore index cb7c59de7..ba55aea73 100644 --- a/.dockerignore +++ b/.dockerignore @@ -23,3 +23,4 @@ /uploads /vendor/ruby /vendor/bundle +/coverage diff --git a/.gitignore b/.gitignore index 2d5e10349..9ed0f7c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ /vendor/bundle /.env /docker-compose.*.yaml +.rubocop.yml +Guardfile +coverage diff --git a/Capfile b/Capfile deleted file mode 100644 index f3634e86a..000000000 --- a/Capfile +++ /dev/null @@ -1,2 +0,0 @@ -load 'deploy' -load 'config/deploy' diff --git a/Docker.md b/Container.md similarity index 57% rename from Docker.md rename to Container.md index 02234fe74..7bae0b621 100644 --- a/Docker.md +++ b/Container.md @@ -1,19 +1,47 @@ -LinuxFr on Docker ------------------ +LinuxFr with Containers +----------------------- -To simplify set up of a developement environment, LinuxFr.org can be -run on Docker with `docker compose up`. +To simplify set up of a development environment, LinuxFr.org can be +run with a container engine like Docker or Podman with the [`compose.yml`](./compose.yaml) +file which describes how to build all needed services. -To init the SQL database schema, you need to wait upto the `database` -container to be ready to listen MySQL connections. +By default, the LinuxFr.org services will be provided under the domain names +`dlfp.lo` and `image.dlfp.lo`. So you'll need to add the +following line into the `/etc/hosts` file of your machine: + + ``` + 127.0.0.1 dlfp.lo image.dlfp.lo + ``` + +Then, if you use the Docker engine, you can use the `docker compose up` +command to start the system (you need to install the +[Docker compose plugin](https://docs.docker.com/compose/) first). + +> Note: with the Docker engine, you need to enable the Docker BuildKit builder. +> Either you have a Docker version which uses it by default, or you set the +> environment variable `export DOCKER_BUILDKIT=1`. + +If you use the Podman engine, you can either use the same Docker compose plugin +or the [podman-compose](https://github.com/containers/podman-compose/) +tool. The podman cli itself provides a wrapper of one of these two tools +through the +[`podman compose` command](https://docs.podman.io/en/latest/markdown/podman-compose.1.html). +Thus you need to use the `podman compose up` command to start the system. + +At this point, this documentation will give you `docker compose` commands, +but you should be able to use `podman compose` without any issue. + +To setup the SQL database schema, you need to wait until the `database` +container becomes ready to listen MySQL connections. For example, you should see in the logs: -> database_1 | 2020-09-21 16:03:12 139820938893312 [Note] mysqld: ready for connections. +> database_1 | 2020-09-21 16:03:12 139820938893312 [Note] *mysqld: ready for connections.* > > database_1 | Version: '10.1.46-MariaDB-1\~bionic' socket: '/var/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution -Or you can check the `database` container status to be "healthy". +Or you can check the `database` container status to be *healthy* with the +`docker compose ps` command. Then, open a second terminal and run: @@ -21,16 +49,9 @@ Then, open a second terminal and run: docker compose exec linuxfr.org bin/rails db:setup ``` -Finally, the environment is ready and you can open [http://dlfp.lo](http://dlfp.lo) +Finally, the environment is ready and you can open [http://dlfp.lo:9000](http://dlfp.lo:9000) in your favorite browser. -Note: to be able to access this URL, you'll need to add the following line -into the `/etc/hosts` file of your machine: - -``` -127.0.0.1 dlfp.lo image.dlfp.lo -``` - Personalize configuration ========================= @@ -40,24 +61,22 @@ If you want, you can change the domain names used by the LinuxFr.org web application. To do this, you can setup `DOMAIN` and `IMAGE_DOMAIN` variables in the `deployment/default.env` file. -You can also configure your own Redis service and your own MySQL -service. - -If you want to change the application port and/or other configurations, you can -[override](https://docs.docker.com/compose/extends/) -the docker compose configuration (in particular the `nginx` service for -the port). +Within the same file, you can update the HTTP listening ports by updating the +`DOMAIN_HTTP_PORT` and `IMAGE_DOMAIN_HTTP_PORT` variables (both are set to +`9000` by default). If you modify them, don't forget to add the new values as +published ports for the `nginx` service in the `compose.yaml` file (they have +to target the `8080` container port). -Notice, that if LinuxFr.org doesn't run on port 80, the image cache -service won't work well and so you won't be able to see images in the news. +You can also configure your own Redis service and your own MySQL +service by updating environment variables in the same file. Test modifications ================== -The docker compose is currently configured to share `./app`, `./db` and -`./public` directories with the docker container. +The compose file currently shares `./app`, `./db` and +`./public` directories with the container. -So you can update files with your prefered IDE on your machine. Rails +So you can update files with your preferred IDE on your machine. Rails will directly detect changes and apply them on next page reload. Furthermore, if you need to access the Rails console, you need a second @@ -75,13 +94,13 @@ Run application tests ===================== To help maintainers, we are in the process of adding tests to check the -application has still the expected behaviour. +application has still the expected behavior. To get help about writing tests, see the [Ruby on Rails documentation](https://guides.rubyonrails.org/testing.html#the-rails-test-runner) . -To run tests with Docker environment, you need to use this command: +To run tests with containers, you need to use this command: ``` docker compose exec linuxfr.org bin/rails test -v @@ -114,10 +133,10 @@ use: docker compose exec linuxfr.org bin/rails db:reset ``` -Services provided by the docker compose +Services provided by the compose file ======================================= -Currently, these services are directly enabled by docker compose: +Currently, these services are directly enabled by compose: 1. The [LinuxFr.org](https://github.com/linuxfrorg/linuxfr.org) ruby on rails application itself diff --git a/Gemfile b/Gemfile index eee3e6c02..3a7e69cc2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,49 +1,50 @@ -source 'https://rubygems.org' +source "https://rubygems.org" git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{repo_name}.git" end -gem "rails", "~>5.2" -gem "nio4r", "2.5.2" # 2.5.3 is not compatible with ruby 2.3 +gem "rails", "~>8.1.0" -gem "actionpack-page_caching", github: "linuxfrorg/actionpack-page_caching" +# Latest 6.0.1 is not starting any tests +gem 'minitest', '< 6.0' + +gem "actionpack-page_caching" +gem "acts_as_list", "~>1.1" gem "ansi", "~>1.4", require: false -gem "acts_as_list", "~>0.4" gem "bitfields", "~>0.4" gem "bootsnap", "~>1.3", require: false gem "canable", "~>0.1" -gem "carrierwave", "~>1.1" +gem "carrierwave", "~>3.0" gem "devise", "~>4.3" gem "diff_match_patch", github: "nono/diff_match_patch-ruby", require: "diff_match_patch" -gem "doorkeeper", "~>4.2" +gem "doorkeeper" gem "ffi-hunspell", github: "postmodern/ffi-hunspell" -gem "french_rails", "~>0.4" +gem "french_rails", "~>0.7", github: "echarp/french-rails" gem "friendly_id", "~>5.1" -gem "haml", "~>5.0" -gem "html-pipeline-linuxfr", "~>0.15" +gem "haml", "~>6.3" +gem "htmlentities", "~>4.3" +gem "html-pipeline-linuxfr", "~>0.17", github: "echarp/html-pipeline-linuxfr" gem "html_spellchecker", "~>0.1" gem "html_truncator", "~>0.4" -gem "htmlentities", "~>4.3" gem "inherited_resources", "~>1.8" gem "kaminari", "~>1.2" gem "mini_magick", "~>4.9" gem "mysql2", "~>0.5.0" gem "nokogiri", "~>1.10" +gem "redis", "~>5.0" gem "rinku", "~>2.0" -gem "redis", "~>4.0" -gem "sitemap_generator", "~>2.1" -gem "state_machine", "~>1.2" +gem "sitemap_generator" +gem "state_machines-activerecord" # Gems used for assets assets = !%w(production alpha).include?(ENV['RAILS_ENV']) assets = true if ENV['RAILS_GROUPS'] == "assets" -gem "jquery-rails", "~>4.0", require: assets -gem "coffee-rails", "~>4.1", require: assets -gem "sass-rails", "~>5.0", require: assets -gem "rails-sass-images", require: assets -gem "uglifier", require: assets +gem "jquery-rails", "~>4.0", require: assets +gem "normalize-rails", "~>8.0", require: assets +gem "sassc-rails", require: assets +gem "terser", "~> 1.2", require: assets group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console @@ -54,25 +55,16 @@ group :development do gem "annotate" gem "better_errors" gem "binding_of_caller" - gem "capistrano", "~>2.15", github: 'capistrano', branch: 'legacy-v2' - gem "capistrano-maintenance" gem "letter_opener" gem "listen", github: "guard/listen" - gem "mo" - gem "pry-rails" - gem "spring" - gem "sushi" - gem "thin" + gem "puma" gem "web-console" end group :test do - # Adds support for Capybara system testing and selenium driver - gem "capybara", ">= 2.15" - gem "selenium-webdriver" + gem "simplecov" end group :production, :alpha do - gem "unicorn", "~>5.1" - gem "gctools", "~>0.2" + gem "unicorn", "~>6.1" end diff --git a/Gemfile.lock b/Gemfile.lock index e1732fcd3..567120651 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,31 @@ GIT - remote: https://github.com/capistrano/capistrano.git - revision: 08a82f3618425eae7539e2bbd34a87e35bac2800 - branch: legacy-v2 + remote: https://github.com/echarp/french-rails.git + revision: 6a839c8fe21417a8e335059925ea8b36535dbef9 specs: - capistrano (2.15.9) - highline - net-scp (>= 1.0.0) - net-sftp (>= 2.0.0) - net-ssh (>= 2.0.14) - net-ssh-gateway (>= 1.1.0) + french_rails (0.7.0) + rails (~> 8.0) GIT - remote: https://github.com/guard/listen.git - revision: 587f4a7edb75fac80faa3408c4513af715dace87 + remote: https://github.com/echarp/html-pipeline-linuxfr.git + revision: 33972788f2c7131b03c5a498d31fe3267dc3b6e4 specs: - listen (3.1.5) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) + html-pipeline-linuxfr (0.17.2) + activesupport (~> 8.0) + escape_utils (~> 1.2) + nokogiri (~> 1.6) + patron (~> 0.8) + pygments.rb (~> 1.1) + redcarpet (~> 3.4) + sanitize (~> 6.1) GIT - remote: https://github.com/linuxfrorg/actionpack-page_caching.git - revision: 13a51101deb396eeb089a0d36a06653bd0d046a9 + remote: https://github.com/guard/listen.git + revision: 7c6d39e17d4ca8aef8cf72890176cc56fa90b236 specs: - actionpack-page_caching (1.2.2) - actionpack (>= 5.0.0) + listen (3.9.0) + logger + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) GIT remote: https://github.com/nono/diff_match_patch-ruby.git @@ -33,309 +35,378 @@ GIT GIT remote: https://github.com/postmodern/ffi-hunspell.git - revision: e5dd37ea70f9dc73ab21b68fa20ad567e9ae9b18 + revision: c6161f5f84247e2bdb2f9ca161a096d632df0432 specs: - ffi-hunspell (0.4.0) + ffi-hunspell (0.6.1) ffi (~> 1.0) GEM remote: https://rubygems.org/ specs: - actioncable (5.2.5) - actionpack (= 5.2.5) + action_text-trix (2.1.16) + railties + actioncable (8.1.2) + actionpack (= 8.1.2) + activesupport (= 8.1.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.5) - actionpack (= 5.2.5) - actionview (= 5.2.5) - activejob (= 5.2.5) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.2.5) - actionview (= 5.2.5) - activesupport (= 5.2.5) - rack (~> 2.0, >= 2.0.8) + zeitwerk (~> 2.6) + actionmailbox (8.1.2) + actionpack (= 8.1.2) + activejob (= 8.1.2) + activerecord (= 8.1.2) + activestorage (= 8.1.2) + activesupport (= 8.1.2) + mail (>= 2.8.0) + actionmailer (8.1.2) + actionpack (= 8.1.2) + actionview (= 8.1.2) + activejob (= 8.1.2) + activesupport (= 8.1.2) + mail (>= 2.8.0) + rails-dom-testing (~> 2.2) + actionpack (8.1.2) + actionview (= 8.1.2) + activesupport (= 8.1.2) + nokogiri (>= 1.8.5) + rack (>= 2.2.4) + rack-session (>= 1.0.1) rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.5) - activesupport (= 5.2.5) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) + actionpack-page_caching (1.2.4) + actionpack (>= 4.0.0) + actiontext (8.1.2) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.2) + activerecord (= 8.1.2) + activestorage (= 8.1.2) + activesupport (= 8.1.2) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (8.1.2) + activesupport (= 8.1.2) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.5) - activesupport (= 5.2.5) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (8.1.2) + activesupport (= 8.1.2) globalid (>= 0.3.6) - activemodel (5.2.5) - activesupport (= 5.2.5) - activerecord (5.2.5) - activemodel (= 5.2.5) - activesupport (= 5.2.5) - arel (>= 9.0) - activestorage (5.2.5) - actionpack (= 5.2.5) - activerecord (= 5.2.5) - marcel (~> 1.0.0) - activesupport (5.2.5) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - acts_as_list (0.9.15) - activerecord (>= 3.0) - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) - annotate (2.7.4) - activerecord (>= 3.2, < 6.0) - rake (>= 10.4, < 13.0) + activemodel (8.1.2) + activesupport (= 8.1.2) + activerecord (8.1.2) + activemodel (= 8.1.2) + activesupport (= 8.1.2) + timeout (>= 0.4.0) + activestorage (8.1.2) + actionpack (= 8.1.2) + activejob (= 8.1.2) + activerecord (= 8.1.2) + activesupport (= 8.1.2) + marcel (~> 1.0) + activesupport (8.1.2) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + acts_as_list (1.2.6) + activerecord (>= 6.1) + activesupport (>= 6.1) + addressable (2.8.8) + public_suffix (>= 2.0.2, < 8.0) + annotate (2.6.5) + activerecord (>= 2.3.0) + rake (>= 0.8.7) ansi (1.5.0) - arel (9.0.0) - bcrypt (3.1.12) - better_errors (2.5.0) - coderay (>= 1.0.0) + base64 (0.3.0) + bcrypt (3.1.21) + better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) - bindex (0.5.0) - binding_of_caller (0.8.0) - debug_inspector (>= 0.0.1) - bitfields (0.8.0) - bootsnap (1.4.6) - msgpack (~> 1.0) - boson (1.3.0) - builder (3.2.4) - byebug (10.0.2) + rouge (>= 1.0.0) + bigdecimal (4.0.1) + bindex (0.8.1) + binding_of_caller (1.0.1) + debug_inspector (>= 1.2.0) + bitfields (0.14.0) + activerecord (>= 5.1) + bootsnap (1.20.1) + msgpack (~> 1.2) + builder (3.3.0) + byebug (12.0.0) canable (0.3.0) - capistrano-maintenance (0.0.5) - capistrano (~> 2.0) - carrierwave (1.2.3) - activemodel (>= 4.0.0) - activesupport (>= 4.0.0) - mime-types (>= 1.16) - coderay (1.1.2) - coffee-rails (4.2.2) - coffee-script (>= 2.2.0) - railties (>= 4.0.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) - concurrent-ruby (1.1.8) + carrierwave (3.1.2) + activemodel (>= 6.0.0) + activesupport (>= 6.0.0) + addressable (~> 2.6) + image_processing (~> 1.1) + marcel (~> 1.0.0) + ssrf_filter (~> 1.0) + childprocess (5.1.0) + logger (~> 1.5) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) crass (1.0.6) - daemons (1.2.6) - debug_inspector (0.0.3) - devise (4.6.2) + date (3.5.1) + debug_inspector (1.2.0) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 6.0) + railties (>= 4.1.0) responders warden (~> 1.2.3) - dimensions (1.3.0) - doorkeeper (4.4.2) - railties (>= 4.2) - erubi (1.9.0) - escape_utils (1.2.1) - eventmachine (1.2.7) - execjs (2.7.0) - ffi (1.12.2) - french_rails (0.4.0) - rails (~> 5.0) - friendly_id (5.2.4) + docile (1.4.1) + doorkeeper (5.8.2) + railties (>= 5) + drb (2.2.3) + erb (6.0.1) + erubi (1.13.1) + escape_utils (1.3.0) + execjs (2.10.0) + ffi (1.17.3-x86_64-linux-gnu) + friendly_id (5.6.0) activerecord (>= 4.0.0) - gctools (0.2.4) - globalid (0.4.2) - activesupport (>= 4.2.0) - haml (5.0.4) - temple (>= 0.8.0) + globalid (1.3.0) + activesupport (>= 6.1) + haml (6.4.0) + temple (>= 0.8.2) + thor tilt - has_scope (0.7.2) - actionpack (>= 4.1) - activesupport (>= 4.1) - highline (2.0.0) - html-pipeline-linuxfr (0.15.7) - activesupport (~> 5.0) - escape_utils (~> 1.2) - nokogiri (~> 1.6) - patron (~> 0.8) - pygments.rb (~> 1.1) - redcarpet (~> 3.4) - sanitize (~> 4.0) + has_scope (0.9.0) + actionpack (>= 7.0) + activesupport (>= 7.0) html_spellchecker (0.1.9) ffi-hunspell (~> 0.4) nokogiri (~> 1.4) html_truncator (0.4.2) nokogiri (~> 1.5) - htmlentities (4.3.4) - i18n (1.8.10) + htmlentities (4.4.2) + i18n (1.14.8) concurrent-ruby (~> 1.0) - inherited_resources (1.9.0) - actionpack (>= 4.2, < 5.3) - has_scope (~> 0.6) - railties (>= 4.2, < 5.3) - responders - jquery-rails (4.3.3) + image_processing (1.14.0) + mini_magick (>= 4.9.5, < 6) + ruby-vips (>= 2.0.17, < 3) + inherited_resources (1.14.0) + actionpack (>= 6.0) + has_scope (>= 0.6) + railties (>= 6.0) + responders (>= 2) + io-console (0.8.2) + irb (1.16.0) + pp (>= 0.6.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jquery-rails (4.6.1) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - kaminari (1.2.1) + json (2.18.0) + kaminari (1.2.2) activesupport (>= 4.1.0) - kaminari-actionview (= 1.2.1) - kaminari-activerecord (= 1.2.1) - kaminari-core (= 1.2.1) - kaminari-actionview (1.2.1) + kaminari-actionview (= 1.2.2) + kaminari-activerecord (= 1.2.2) + kaminari-core (= 1.2.2) + kaminari-actionview (1.2.2) actionview - kaminari-core (= 1.2.1) - kaminari-activerecord (1.2.1) + kaminari-core (= 1.2.2) + kaminari-activerecord (1.2.2) activerecord - kaminari-core (= 1.2.1) - kaminari-core (1.2.1) - kgio (2.11.2) - launchy (2.4.3) - addressable (~> 2.3) - letter_opener (1.6.0) - launchy (~> 2.2) - loofah (2.7.0) + kaminari-core (= 1.2.2) + kaminari-core (1.2.2) + kgio (2.11.4) + launchy (3.1.1) + addressable (~> 2.8) + childprocess (~> 5.0) + logger (~> 1.6) + letter_opener (1.10.0) + launchy (>= 2.2, < 4) + logger (1.7.0) + loofah (2.25.0) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.9.0) + logger mini_mime (>= 0.1.1) - marcel (1.0.1) - method_source (0.9.2) - mime-types (3.2.2) - mime-types-data (~> 3.2015) - mime-types-data (3.2018.0812) - mini_magick (4.9.4) - mini_mime (1.0.3) - mini_portile2 (2.4.0) - minitest (5.14.4) - mo (1.4.0) - boson - msgpack (1.3.3) - multi_json (1.13.1) - mysql2 (0.5.2) - net-scp (1.2.1) - net-ssh (>= 2.6.5) - net-sftp (2.1.2) - net-ssh (>= 2.6.5) - net-ssh (5.0.2) - net-ssh-gateway (2.0.0) - net-ssh (>= 4.0.0) - nio4r (2.5.2) - nokogiri (1.10.10) - mini_portile2 (~> 2.4.0) - nokogumbo (1.5.0) - nokogiri + net-imap + net-pop + net-smtp + marcel (1.0.4) + mini_magick (4.13.2) + mini_mime (1.1.5) + minitest (5.27.0) + msgpack (1.8.0) + multi_json (1.19.1) + mysql2 (0.5.7) + bigdecimal + net-imap (0.6.2) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.5) + nokogiri (1.19.0-x86_64-linux-gnu) + racc (~> 1.4) + normalize-rails (8.0.1) orm_adapter (0.5.0) - patron (0.13.1) - pry (0.11.3) - coderay (~> 1.1.0) - method_source (~> 0.9.0) - pry-rails (0.3.6) - pry (>= 0.10.4) - public_suffix (3.0.3) + patron (0.13.4) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + psych (5.3.1) + date + stringio + public_suffix (7.0.2) + puma (7.1.0) + nio4r (~> 2.0) pygments.rb (1.2.1) multi_json (>= 1.0.0) - rack (2.2.3) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.2.5) - actioncable (= 5.2.5) - actionmailer (= 5.2.5) - actionpack (= 5.2.5) - actionview (= 5.2.5) - activejob (= 5.2.5) - activemodel (= 5.2.5) - activerecord (= 5.2.5) - activestorage (= 5.2.5) - activesupport (= 5.2.5) - bundler (>= 1.3.0) - railties (= 5.2.5) - sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + racc (1.8.1) + rack (3.2.4) + rack-session (2.1.1) + base64 (>= 0.1.0) + rack (>= 3.0.0) + rack-test (2.2.0) + rack (>= 1.3) + rackup (2.3.1) + rack (>= 3) + rails (8.1.2) + actioncable (= 8.1.2) + actionmailbox (= 8.1.2) + actionmailer (= 8.1.2) + actionpack (= 8.1.2) + actiontext (= 8.1.2) + actionview (= 8.1.2) + activejob (= 8.1.2) + activemodel (= 8.1.2) + activerecord (= 8.1.2) + activestorage (= 8.1.2) + activesupport (= 8.1.2) + bundler (>= 1.15.0) + railties (= 8.1.2) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) - loofah (~> 2.3) - rails-sass-images (1.0.3) - dimensions (> 0) - mime-types (> 0) - sass (> 0) - railties (5.2.5) - actionpack (= 5.2.5) - activesupport (= 5.2.5) - method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) - raindrops (0.19.0) - rake (12.3.3) - rb-fsevent (0.10.3) - rb-inotify (0.10.0) + rails-html-sanitizer (1.6.2) + loofah (~> 2.21) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + railties (8.1.2) + actionpack (= 8.1.2) + activesupport (= 8.1.2) + irb (~> 1.13) + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) + zeitwerk (~> 2.6) + raindrops (0.20.1) + rake (13.3.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) ffi (~> 1.0) - redcarpet (3.4.0) - redis (4.0.2) - responders (2.4.1) - actionpack (>= 4.2.0, < 6.0) - railties (>= 4.2.0, < 6.0) - rinku (2.0.4) - sanitize (4.6.6) + rdoc (7.0.3) + erb + psych (>= 4.0.0) + tsort + redcarpet (3.6.1) + redis (5.4.1) + redis-client (>= 0.22.0) + redis-client (0.26.3) + connection_pool + reline (0.6.3) + io-console (~> 0.5) + responders (3.2.0) + actionpack (>= 7.0) + railties (>= 7.0) + rinku (2.0.6) + rouge (4.7.0) + ruby-vips (2.3.0) + ffi (~> 1.12) + logger + sanitize (6.1.3) crass (~> 1.0.2) - nokogiri (>= 1.4.4) - nokogumbo (~> 1.4) - sass (3.5.7) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sitemap_generator (2.2.1) - spring (2.0.2) - activesupport (>= 4.2) - sprockets (3.7.2) + nokogiri (>= 1.12.0) + sassc (2.4.0) + ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt + securerandom (0.4.1) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.13.2) + simplecov_json_formatter (0.1.4) + sitemap_generator (6.3.0) + builder (~> 3.0) + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + logger + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) - state_machine (1.2.0) - sushi (0.0.4) - temple (0.8.0) - thin (1.7.2) - daemons (~> 1.0, >= 1.0.9) - eventmachine (~> 1.0, >= 1.0.4) - rack (>= 1, < 3) - thor (1.0.1) - thread_safe (0.3.6) - tilt (2.0.8) - tzinfo (1.2.9) - thread_safe (~> 0.1) - uglifier (4.1.18) + ssrf_filter (1.3.0) + state_machines (0.100.4) + state_machines-activemodel (0.101.0) + activemodel (>= 7.2) + state_machines (>= 0.100.4) + state_machines-activerecord (0.100.0) + activerecord (>= 7.2) + state_machines-activemodel (>= 0.100.0) + stringio (3.2.0) + temple (0.10.4) + terser (1.2.6) execjs (>= 0.3.0, < 3) - unicorn (5.4.1) + thor (1.5.0) + tilt (2.7.0) + timeout (0.6.0) + tsort (0.2.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicorn (6.1.0) kgio (~> 2.6) raindrops (~> 0.7) - warden (1.2.8) - rack (>= 2.0.6) - web-console (3.6.2) - actionview (>= 5.0) - activemodel (>= 5.0) + uri (1.1.1) + useragent (0.16.11) + warden (1.2.9) + rack (>= 2.0.9) + web-console (4.2.1) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) bindex (>= 0.4.0) - railties (>= 5.0) - websocket-driver (0.7.3) + railties (>= 6.0.0) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + zeitwerk (2.7.4) PLATFORMS - ruby + x86_64-linux DEPENDENCIES - actionpack-page_caching! - acts_as_list (~> 0.4) + actionpack-page_caching + acts_as_list (~> 1.1) annotate ansi (~> 1.4) better_errors @@ -344,19 +415,15 @@ DEPENDENCIES bootsnap (~> 1.3) byebug canable (~> 0.1) - capistrano (~> 2.15)! - capistrano-maintenance - carrierwave (~> 1.1) - coffee-rails (~> 4.1) + carrierwave (~> 3.0) devise (~> 4.3) diff_match_patch! - doorkeeper (~> 4.2) + doorkeeper ffi-hunspell! - french_rails (~> 0.4) + french_rails (~> 0.7)! friendly_id (~> 5.1) - gctools (~> 0.2) - haml (~> 5.0) - html-pipeline-linuxfr (~> 0.15) + haml (~> 6.3) + html-pipeline-linuxfr (~> 0.17)! html_spellchecker (~> 0.1) html_truncator (~> 0.4) htmlentities (~> 4.3) @@ -366,24 +433,21 @@ DEPENDENCIES letter_opener listen! mini_magick (~> 4.9) - mo + minitest (< 6.0) mysql2 (~> 0.5.0) - nio4r (= 2.5.2) nokogiri (~> 1.10) - pry-rails - rails (~> 5.2) - rails-sass-images - redis (~> 4.0) + normalize-rails (~> 8.0) + puma + rails (~> 8.1.0) + redis (~> 5.0) rinku (~> 2.0) - sass-rails (~> 5.0) - sitemap_generator (~> 2.1) - spring - state_machine (~> 1.2) - sushi - thin - uglifier - unicorn (~> 5.1) + sassc-rails + simplecov + sitemap_generator + state_machines-activerecord + terser (~> 1.2) + unicorn (~> 6.1) web-console BUNDLED WITH - 1.17.3 + 2.6.7 diff --git a/INSTALL.md b/INSTALL.md index 693d0e999..7b08cb521 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,67 +1,44 @@ -# Introduction +# LinuxFr.org installation + +## Introduction This document will give you steps to install LinuxFr.org website on your -Debian Stretch development machine. +Debian Trixie (stable) development machine. Note that all commands which require root access are prefixed by `sudo`. -# Use stretch-backports +## Install Debian packages -LinuxFr.org requires to add `stretch-backports` source package as it -needs the `npm`package. +Packages to install from main Debian source: -``` -~ $ sudo bash -c "echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/sources.list.d/linuxfr.list" -~ $ sudo apt update -``` - -# Install Debian packages - -Packages to install from main Stretch source: - -``` -~ $ sudo apt install mysql-server mysql-client libmysql++-dev git \ -build-essential openssl libreadline-dev curl libcurl4-openssl-dev zlib1g \ -zlib1g-dev libssl-dev libxml2-dev libxslt-dev autoconf libgmp-dev libyaml-dev \ -ncurses-dev bison automake libtool imagemagick libc6-dev hunspell \ -hunspell-fr-comprehensive redis-server ruby ruby-dev ruby-rack +```sh +~ $ sudo apt install default-mysql-server default-libmysqlclient-dev \ +libmysql++-dev git build-essential openssl libreadline-dev curl \ +libcurl4-openssl-dev zlib1g zlib1g-dev libssl-dev libxml2-dev libxslt-dev \ +autoconf libgmp-dev libyaml-dev ncurses-dev bison automake libtool \ +imagemagick libc6-dev hunspell hunspell-fr-comprehensive redis-server \ +ruby ruby-dev ``` Note: - * you can use libcurl4-gnutls-dev instead of libcurl4-openssl-dev. - * the `mysql` packages will install MariaDB on Debian Stretch -Packages to install from backports: +- you can use libcurl4-gnutls-dev instead of libcurl4-openssl-dev. +- the `default-mysql-server` package will install MariaDB on Debian -``` -~ $ sudo apt install -t stretch-backports nodejs npm -``` - -# Get LinuxFr.org code and external resources +## Get LinuxFr.org code and external resources Use git to get LinuxFr.org sources: -``` +```sh ~ $ git clone git://github.com/linuxfrorg/linuxfr.org.git ``` To be able to reach ruby external resources, you need the `bundler` packager. -The minimal required version is written at the end of the `Gemfile.lock` file. -Actually, Debian has the `1.13.6` version and the lock file requires already -the `1.16.4` version. - -So we first install the `bundler` packager directly from `rubygems.org`: - -``` -~ $ gem install --user-install bundler -``` - -Don't forget to update your PATH environment according to the warning message -shown during installation. +It is now installed by default with Ruby. Now, we can reach external Ruby resources: -``` +```sh ~ $ cd linuxfr.org ~/linuxfr.org $ bundle config set path 'vendor/bundle' ~/linuxfr.org $ bundle install @@ -70,12 +47,6 @@ Now, we can reach external Ruby resources: The `check` command above should say you there's no problem. -LinuxFr.org uses also some nodejs resources: - -``` -~/linuxfr.org $ npm install -``` - ## Install the LinuxFr.org board The `board-linuxfr` gem server is used to allow users chat on the `/boards` and @@ -83,11 +54,11 @@ the collaborative `redaction` space to work asynchronously. To install it, the simplest is to run `gem install --user-install board-linuxfr` -# Configure LinuxFr.org +## Configure LinuxFr.org To configure LinuxFr.org, you need to copy both sample configuration files: -``` +```sh ~/linuxfr.org $ cp config/database.yml{.sample,} ~/linuxfr.org $ cp config/secrets.yml{.sample,} ``` @@ -102,17 +73,17 @@ In this document we'll assume you took the default values for database names: Note that, on production, you'll need to customize secrets inside the `secrets.yml` file. -# Configure SQL data base +## Configure SQL data base Prepare time zones information inside the `mysql` database: -``` +```sh ~ $ mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql mysql ``` Create LinuxFr.org databases and MySQL users: -``` +```sql ~/linuxfr.org $ sudo mysql > CREATE DATABASE linuxfr_rails CHARACTER SET utf8mb4; > CREATE USER linuxfr_rails IDENTIFIED BY 'linuxfr_rails password'; @@ -128,15 +99,15 @@ Create LinuxFr.org databases and MySQL users: Now every thing is ready and we can ask `rails` to setup our databases with every structures needed: -``` +```sh ~/linuxfr.org $ bin/rails db:setup ``` -# Run LinuxFr.org +## Run LinuxFr.org Now, you can run LinuxFr.org server with: -``` +```sh ~/linuxfr.org $ bin/rails server ``` @@ -145,31 +116,40 @@ virtual machine using the `http://localhost:3000` URL. Additionally, you run the boards within another terminal: -``` +```sh ~/linuxfr.org $ board-linuxfr -s -a localhost -p 9000 ``` -# Configure redirection +## Configure redirection This extra step isn't really needed to be able to use LinuxFr.org. -In the `config/environments/development.rb` file, there are two domains set -inside variables `MY_DOMAIN` and `IMG_DOMAIN`. -By default both domains are `dlfp.lo`. +In the `config/environments/development.rb` file, there are these variables: + +1. `MY_DOMAIN` and `IMG_DOMAIN` which define the domain name for the LinuxFr + service and the image caching service. + By default both domain names are `dlfp.lo`. + +2. `MY_PUBLIC_URL` and `IMG_PUBLIC_PORT` which define the public HTTP port for + both services. + By default both ports are `80`. + +These two set of variables are used to build the public url of the two +services. By default both public urls are `http://dlfp.lo`. -You'll find this domain inside some documents like emails to confirm user +You'll find this public url inside some documents like emails to confirm user subscription. To simplify your usage of LinuxFr.org, you should consider install a website locally using this domain name. Set the domain `dlfp.lo` to target `localhost`: -``` +```sh ~ $ sudo bash -c 'echo "127.0.0.1 dlfp.lo" >> /etc/hosts' ``` For Nginx, create a new server configuration with content like: -``` +```nginx server { server_name dlfp.lo; access_log /var/log/nginx/dlfp.access.log; @@ -182,7 +162,7 @@ server { # Avatars files uploaded on linuxfr server are stored in partitions # with folder name containing 3 digits - location ~ ^/avatars/\d\d\d/ { + location ~ ^/avatars/\d\d\d/ { root /home/linuxfr/linuxfr.org/uploads; } @@ -216,14 +196,14 @@ server { and restart the web server: -``` +```sh ~ $ sudo systemctl restart nginx ``` Now, on the virtual machine, you can access LinuxFr.org with the `http://dlfp.lo` URL. -# Create administrator +## Create administrator To create new users, you can use directly the website. @@ -232,7 +212,7 @@ in the database. For example, to set as admin the user with login `admin_login`: -``` +```sql $ sudo mysql linuxfr_rails > update accounts set role = 'admin' where login = 'admin_login' ; ``` diff --git a/README.md b/README.md index ed27f6db9..159336532 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Install See [INSTALL.md](INSTALL.md) to set up LinuxFr.org on a Debian environment. -Alternatively, you can read [Docker.md](Docker.md) to setup easily -LinuxFr.org development environment with the Docker engine and -[docker-compose](https://docs.docker.com/compose/). +Alternatively, you can read [Container.md](Container.md) to setup easily +LinuxFr.org development environment with a container engine like Docker or +Podman and use the [container composer](https://docs.docker.com/compose/). See also -------- diff --git a/app/assets/javascripts/application.coffee b/app/assets/javascripts/application.coffee deleted file mode 100644 index 4e724e8bc..000000000 --- a/app/assets/javascripts/application.coffee +++ /dev/null @@ -1,148 +0,0 @@ -#= require jquery2 -#= require jquery_ujs -#= require jquery.autocomplete -#= require jquery.caret-range -#= require jquery.cookie -#= require jquery.hotkeys -#= require jquery.notice -#= require jquery.markitup -#= require markitup-markdown -#= require_tree . - -$ = window.jQuery - -$("body").on "ajax:success", "form[data-remote]", (e, data) -> - $.noticeAdd text: data.notice if data and data.notice - $("#nb_votes").text data.nb_votes if data and data.nb_votes - $(@).parent().hide() unless $(@).data("hidden") - -$(".markItUp").markItUp window.markItUpSettings - -$("a.hit_counter[data-hit]").each -> - @href = "/redirect/" + $(@).data("hit") - -# Ready to moule -$("input[autofocus=autofocus]").focus() -$(".board").chat() -$("#news_revisions").redaction() - -# Force people to preview their modified contents -$("textarea, #form_answers input").keypress (event) -> - $(@).parents("form").find("input[value=Prévisualiser]").next("input[type=submit]").hide() - $(@).off event - -# Add/Remove dynamically links in the news form -langs = - xx: "!? hmmm ?!" - fr: "Français" - de: "Allemand" - en: "Anglais" - eu: "Basque" - ct: "Catalan" - cn: "Chinois" - wq: "Code/binaire" - ko: "Coréen" - da: "Danois" - es: "Espagnol" - ee: "Estonien" - fi: "Finnois" - el: "Grec" - it: "Italien" - ja: "Japonais" - nl: "Néerlandais" - no: "Norvégien" - pl: "Polonais" - pt: "Portugais" - ru: "Russe" - sv: "Suédois" - -$("#form_links").nested_fields "news", "link", "lien", "fieldset", title: "text", url: "url", lang: langs -$("#form_answers").nested_fields "poll", "answer", "choix", "p", answer: "text" - -# Mask the contributors if they are too many -$("article.news .edited_by").each -> - field = $(@) - nb = field.find("a").length - if nb > 3 - was = field.html() - field.html "#{nb} personnes" - field.one "click", -> field.html was - -# Toolbar preferences -$("#account_visible_toolbar") - .prop("checked", Toolbar.storage.visible != "false") - .click -> - Toolbar.storage.visible = $(@).is(":checked") - true - -# Show the toolbar -$.fn.reverse = [].reverse -if $("body").hasClass("logged") - if $("#comments").length - $("#comments .new-comment") - .toolbar("Nouveaux commentaires", folding: "#comments .comment") - .additional $("#comments .comment").sort((a,b) -> a.id.localeCompare(b.id)), "Commentaires par ordre chronologique" - else if $("main .node").length - $("#phare .new-node, main .new-node:not(.ppp)") - .toolbar("Contenus jamais visités") - .additional $("#phare .new_comments, main .node:not(.ppp) .new_comments").parents("article").reverse(), "Contenus lus avec + de commentaires" - -# Redaction -$(".edition_in_place").editionInPlace() -$("#redaction .new_link").editionInPlace() -$("#redaction .new_paragraph").on "ajax:success", false -$("#redaction .link, #redaction .paragraph").lockableEditionInPlace() - -# Tags -$.fn.autocompleter = () -> - @each -> - input = $(@) - input.autocomplete input.data("url"), - multiple: true - multipleSeparator: " " - dataType: "text" - matchSubset: false - @ -$("input#tags").autocompleter() -$(".tag_in_place").on("in_place:form", -> - $("input.autocomplete").autocompleter().focus() -).on("in_place:success", -> - $.noticeAdd text: "Étiquettes ajoutées" -).editionInPlace() -$(".add_tag, .remove_tag").click( -> - $(@).blur().parents("form").data hidden: "true" -).parents("form").on "ajax:success", -> - $(@).find("input").attr disabled: "disabled" - -# Hotkeys -$(document).bind("keypress", "g", -> - $("html,body").animate scrollTop: 0, 500 - false -).bind("keypress", "shift+g", -> - $("html,body").animate scrollTop: $("body").attr("scrollHeight"), 500 - false -).bind "keypress", "shift+?", -> - $.noticeAdd - text: """ - Raccourcis clavier :
Commentaires : - voir le flux Atom + voir le flux Atom ouvrir dans le navigateur
EOS diff --git a/app/helpers/board_helper.rb b/app/helpers/board_helper.rb index d07ac9016..b26b4a2da 100644 --- a/app/helpers/board_helper.rb +++ b/app/helpers/board_helper.rb @@ -1,11 +1,9 @@ # encoding: utf-8 module BoardHelper - def norloge(board, box) format = :norloge2 format = :norloge if board.object_type == Board.free format = :norloge if box - board.created_at.to_s format + board.created_at.to_fs format end - end diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index cc0581864..e0218843b 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -6,8 +6,8 @@ def messages_on_error(object) content_tag(:div, class: "errors") do content_tag(:h2, pluralize(object.errors.count, "erreur") + ' : ') + content_tag(:ul) do - object.errors.values.flatten.map do |err| - content_tag(:li, err) + object.errors.map do |err| + content_tag(:li, err.message) end.join.html_safe end end diff --git a/app/helpers/node_helper.rb b/app/helpers/node_helper.rb index eb6a2f889..c2c84aca3 100644 --- a/app/helpers/node_helper.rb +++ b/app/helpers/node_helper.rb @@ -1,6 +1,5 @@ # encoding: utf-8 module NodeHelper - ContentPresenter = Struct.new(:record, :title, :meta, :tags, :notice, :image, :body, :actions, :css_class, :hidden) do def to_hash attrs = members.map(&:to_sym) @@ -117,7 +116,7 @@ def posted_by(content, user_link='Anonyme') end date_time = content.is_a?(Comment) ? content.created_at : content.node.try(:created_at) date_time ||= Time.now - published_at = content_tag(:time, "le #{date_time.to_s(:posted)}", datetime: date_time.iso8601, class: "updated") + published_at = content_tag(:time, "le #{date_time.to_fs(:posted)}", datetime: date_time.iso8601, class: "updated") caption = content_tag(:span, "", class: "floating_spacer") + content_tag(:span, "Posté par #{ user_link } #{ published_at }.".html_safe, class: "posted_by_spanblock") caption.html_safe diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 000000000..94e073dcc --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,3 @@ +# Top mailer class, from which all others are inheritors +class ApplicationMailer < ActionMailer::Base +end diff --git a/app/mailers/news_notifications.rb b/app/mailers/news_notifications.rb index 8bfb45aed..4afd5d807 100644 --- a/app/mailers/news_notifications.rb +++ b/app/mailers/news_notifications.rb @@ -2,7 +2,7 @@ # # This mailer is used to notify news writers when their news are accepted or refused. # -class NewsNotifications < ActionMailer::Base +class NewsNotifications < ApplicationMailer MODERATORS = "Équipe de modération de LinuxFr.orgN. D. M. : ».
@@ -68,7 +68,7 @@
L’icône
= image_tag "/images/icones/edit-cut.png", alt: "Suggestion de découpe"
sert à suggérer où découper entre les première et seconde parties de la dépêche.
- = render 'wiki_help'
+ = render 'redaction/news/wiki_help'
.popup-event{"data-popup-id": "toolpanel"}
- = image_tag("icones/arrow-right.svg", alt: "Afficher les détails", title: "Afficher les détails")
+ = image_tag("/images/icones/arrow-right.svg", alt: "Afficher les détails", title: "Afficher les détails")
diff --git a/app/views/redaction/news/_topbar.html.haml b/app/views/redaction/news/_topbar.html.haml
index 2f364d3c1..cd6935259 100644
--- a/app/views/redaction/news/_topbar.html.haml
+++ b/app/views/redaction/news/_topbar.html.haml
@@ -13,4 +13,4 @@
%br
%span.revision-date
= "le #{I18n.l(revision.created_at, :format => '%d %B %Y à %H:%M:%S')}"
- = render 'attendees', attendees: news.attendees, enable_reassign: false
+ = render 'redaction/news/attendees', attendees: news.attendees, enable_reassign: false
diff --git a/app/views/redaction/news/show.md.erb b/app/views/redaction/news/show.md.erb
new file mode 100644
index 000000000..99cbd8ef1
--- /dev/null
+++ b/app/views/redaction/news/show.md.erb
@@ -0,0 +1 @@
+<%= render template: 'news/show', :content => @news %>
diff --git a/app/views/statistics/contents.html.haml b/app/views/statistics/contents.html.haml
index 2d685abcf..cc1cbdce4 100644
--- a/app/views/statistics/contents.html.haml
+++ b/app/views/statistics/contents.html.haml
@@ -22,16 +22,16 @@
- else
%h2#type Répartition par type
%ul
- %li #{pluralize @stats.contents["Diary"], "journal", "journaux"}
- %li #{pluralize @stats.contents["Post"], "entrée"} de forums
+ %li #{pluralize @stats.contents["Diary"] || 0, "journal", "journaux"}
+ %li #{pluralize @stats.contents["Post"] || 0, "entrée"} de forums
%li
- #{pluralize @stats.contents["News"], "dépêche"}, plus #{@stats.news["draft"]} en rédaction, #{@stats.news["candidate"]} en modération, #{pluralize @stats.news["refused"], "refusée"} (et encore en base de données).
+ #{pluralize @stats.contents["News"] || 0, "dépêche"}, plus #{@stats.news["draft"]} en rédaction, #{@stats.news["candidate"]} en modération, #{pluralize @stats.news["refused"] || 0, "refusée"} (et encore en base de données).
- if @stats.contents["News"].to_i > 0
- = "Publication sous #{pluralize @stats.nb_news_authors, "nom"} par #{pluralize @stats.nb_news_accounts, "utilisateur"}."
- %li #{pluralize @stats.contents["Tracker"], "entrée"} dans le système de suivi
- %li #{pluralize @stats.contents["Poll"], "sondage"}
- %li #{pluralize @stats.contents["WikiPage"], "page"} de wiki
- %li #{pluralize @stats.contents["Bookmark"], "lien"}
+ = "Publication sous #{pluralize @stats.nb_news_authors || 0, "nom"} par #{pluralize @stats.nb_news_accounts || 0, "utilisateur"}."
+ %li #{pluralize @stats.contents["Tracker"] || 0, "entrée"} dans le système de suivi
+ %li #{pluralize @stats.contents["Poll"] || 0, "sondage"}
+ %li #{pluralize @stats.contents["WikiPage"] || 0, "page"} de wiki
+ %li #{pluralize @stats.contents["Bookmark"] || 0, "lien"}
- if @stats.contents["Total"] > 1
%h2#annee Répartition annuelle des #{@stats.contents["Total"]} contenus
@@ -72,7 +72,7 @@
- content.each do |type,cnt|
%tr
-if newyear
- %td{'class' => 'stat','rowspan' => content.count}= month.sub(/(\d{4})(\d{2})/, '\2 \1')
+ %td{'class' => 'stat','rowspan' => content.count}= month&.sub(/(\d{4})(\d{2})/, '\2 \1')
- newyear = false
%td
.stat.stats100px(class="content#{type.downcase()}") #{translate_content_type(type)}
diff --git a/app/views/statistics/tags.html.haml b/app/views/statistics/tags.html.haml
index 19e11646a..0100346b5 100644
--- a/app/views/statistics/tags.html.haml
+++ b/app/views/statistics/tags.html.haml
@@ -30,31 +30,31 @@
%h2#type Répartition par type
%ul
%li
- #{pluralize @stats.taggings["Diary"].to_i, "étiquette"} dans #{pluralize @contents.contents["Diary"], "journal", "journaux"}
+ #{pluralize @stats.taggings["Diary"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["Diary"] || 0, "journal", "journaux"}
-if @contents.contents["Diary"].to_i > 0
= "soit #{pluralize (@stats.taggings["Diary"].to_f/@contents.contents["Diary"]).round(2), "étiquette"} par journal publié"
%li
- #{pluralize @stats.taggings["Post"].to_i, "étiquette"} dans #{pluralize @contents.contents["Post"], "entrée"} de forums
+ #{pluralize @stats.taggings["Post"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["Post"] || 0, "entrée"} de forums
-if @contents.contents["Post"].to_i > 0
= "soit #{pluralize (@stats.taggings["Post"].to_f/@contents.contents["Post"]).round(2), "étiquette"} par entrée publiée"
%li
- #{pluralize @stats.taggings["News"].to_i, "étiquette"} dans #{pluralize @contents.contents["News"], "dépêche"}
+ #{pluralize @stats.taggings["News"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["News"] || 0, "dépêche"}
-if @contents.contents["News"].to_i > 0
= "soit #{pluralize (@stats.taggings["News"].to_f/@contents.contents["News"]).round(2), "étiquette"} par dépêche publiée"
%li
- #{pluralize @stats.taggings["Tracker"].to_i, "étiquette"} dans #{pluralize @contents.contents["Tracker"], "entrée"} dans le système de suivi
+ #{pluralize @stats.taggings["Tracker"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["Tracker"] || 0, "entrée"} dans le système de suivi
-if @contents.contents["Tracker"].to_i > 0
= "soit #{pluralize (@stats.taggings["Tracker"].to_f/@contents.contents["Tracker"]).round(2), "étiquette"} par entrée publiée"
%li
- #{pluralize @stats.taggings["Poll"].to_i, "étiquette"} dans #{pluralize @contents.contents["Poll"], "sondage"}
+ #{pluralize @stats.taggings["Poll"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["Poll"] || 0, "sondage"}
-if @contents.contents["Poll"].to_i > 0
= "soit #{pluralize (@stats.taggings["Poll"].to_f/@contents.contents["Poll"]).round(2), "étiquette"} par sondage publié"
%li
- #{pluralize @stats.taggings["WikiPage"].to_i, "étiquette"} dans #{pluralize @contents.contents["WikiPage"], "page"} de wiki
+ #{pluralize @stats.taggings["WikiPage"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["WikiPage"] || 0, "page"} de wiki
-if @contents.contents["WikiPage"].to_i > 0
= "soit #{pluralize (@stats.taggings["WikiPage"].to_f/@contents.contents["WikiPage"]).round(2), "étiquette"} par page publiée"
%li
- #{pluralize @stats.taggings["Bookmark"].to_i, "étiquette"} dans #{pluralize @contents.contents["Bookmark"], "lien"}
+ #{pluralize @stats.taggings["Bookmark"].to_i || 0, "étiquette"} dans #{pluralize @contents.contents["Bookmark"] || 0, "lien"}
-if @contents.contents["Bookmark"].to_i > 0
= "soit #{pluralize (@stats.taggings["Bookmark"].to_f/@contents.contents["Bookmark"]).round(2), "étiquette"} par lien publié"
@@ -97,7 +97,7 @@
- tag.each do |type,cnt|
%tr
-if newyear
- %td.stat{'rowspan' => tag.count}= month.sub(/(\d{4})(\d{2})/, '\2 \1')
+ %td.stat{'rowspan' => tag.count}= month&.sub(/(\d{4})(\d{2})/, '\2 \1')
- newyear = false
%td
.stat.stats100px(class="content#{type.downcase()}") #{translate_content_type(type)}
diff --git a/app/views/statistics/tracker.html.haml b/app/views/statistics/tracker.html.haml
index 5940a71f3..bcdec6e7b 100644
--- a/app/views/statistics/tracker.html.haml
+++ b/app/views/statistics/tracker.html.haml
@@ -86,7 +86,7 @@
- invalid = month[1]["invalid"] || 0
%tr
%td.stat
- = month[0].sub(/(\d{4})(\d{2})/, '\2 \1')
+ = month[0]&.sub(/(\d{4})(\d{2})/, '\2 \1')
%td
.stat.remaining(style="width:#{width_stats * total / maxval / 4}px;")= total
%td
diff --git a/app/views/stylesheets/edit.html.haml b/app/views/stylesheets/edit.html.haml
index 19fc17fe8..539c2a2d6 100644
--- a/app/views/stylesheets/edit.html.haml
+++ b/app/views/stylesheets/edit.html.haml
@@ -33,7 +33,7 @@
Pour cela, il vous suffit de commencer votre feuille de style par la déclaration suivante :
%pre
- @import url("//#{MY_DOMAIN}/assets/application.css");
+ @import url("#{MY_PUBLIC_URL}/assets/application.css");
%div.sideforms
= form_tag "/stylesheet", method: :put do
diff --git a/app/views/trackers/_form.html.haml b/app/views/trackers/_form.html.haml
index aac89aba8..4015bc3d8 100644
--- a/app/views/trackers/_form.html.haml
+++ b/app/views/trackers/_form.html.haml
@@ -5,7 +5,7 @@
= form.text_field :title, autocomplete: 'off', required: 'required', spellcheck: 'true', maxlength: 100
%p
= form.label :category_id, "Catégorie"
- = form.collection_select :category_id, Category.all, :id, :title
+ = form.collection_select :category_id, Category.all, :id, :title, { include_blank: true }, { required: "required" }
- if @tracker.new_record?
%p.pot_de_miel
= form.label :pot_de_miel, "Ne pas remplir ce champ"
@@ -23,4 +23,4 @@
= form.collection_select :assigned_to_user_id, Account.tracker_admin, :user_id, :login, include_blank: true
%p
= form.submit "Prévisualiser", id: "tracker_preview"
- = form.submit "Soumettre", 'data-disable-with' => "Enregistrement en cours" if @preview_mode || @tracker.persisted?
+ = form.submit "Soumettre", 'data-disable-with' => "Enregistrement en cours" if (@preview_mode || @tracker.persisted?) and @tracker.valid?
diff --git a/app/views/trackers/_tracker.atom.builder b/app/views/trackers/_tracker.atom.builder
index deffa237b..479e1ab88 100644
--- a/app/views/trackers/_tracker.atom.builder
+++ b/app/views/trackers/_tracker.atom.builder
@@ -8,5 +8,5 @@ feed.entry(tracker) do |entry|
tracker.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
- entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{tracker.node.id}/comments.atom"
+ entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{tracker.node.id}/comments.atom"
end
diff --git a/app/views/trackers/edit.html.haml b/app/views/trackers/edit.html.haml
index db7f0eebd..c131a4717 100644
--- a/app/views/trackers/edit.html.haml
+++ b/app/views/trackers/edit.html.haml
@@ -1,7 +1,7 @@
%main#contents(role="main")
=h1 "Modifier une entrée dans le suivi"
- = render "preview", preview: @tracker if @preview_mode
+ = render "preview", preview: @tracker if @preview_mode and @tracker.valid?
%h2 Édition
= form_for @tracker do |form|
diff --git a/app/views/trackers/index.html.haml b/app/views/trackers/index.html.haml
index d55f193f2..458287dd8 100644
--- a/app/views/trackers/index.html.haml
+++ b/app/views/trackers/index.html.haml
@@ -50,7 +50,7 @@
%tr{class: tracker.state}
%td= link_to tracker.id, tracker
%td= link_to tracker.title, tracker
- %td= tracker.created_at.to_s(:posted)
+ %td= tracker.created_at.to_fs(:posted)
%td= tracker.assigned_to
%td= tracker.user ? link_to(tracker.user.name, tracker.user) : "Anonyme"
%td= link_to tracker.category_title, "/suivi?tracker%5Bcategory_id%5D=#{tracker.category_id}"
diff --git a/app/views/trackers/new.html.haml b/app/views/trackers/new.html.haml
index d2e4a9325..7981dea75 100644
--- a/app/views/trackers/new.html.haml
+++ b/app/views/trackers/new.html.haml
@@ -4,7 +4,7 @@
%p
Il s’agit du suivi des suggestions et bogues concernant le site LinuxFr.org.
- - if @preview_mode
+ - if @preview_mode and @tracker.valid?
= render "preview", preview: @tracker
- else
= image_tag "/images/dessins/geekscottes_068.png", alt: "Tu coderas pour moi !", title: "Tu coderas pour moi ! — © Johann « nojhan » Dréo, 7 novembre 2007 — Licence CC‑By‑SA 2.5"
diff --git a/app/views/wiki_pages/_form.html.haml b/app/views/wiki_pages/_form.html.haml
index ef2144de2..c7ae7db63 100644
--- a/app/views/wiki_pages/_form.html.haml
+++ b/app/views/wiki_pages/_form.html.haml
@@ -6,4 +6,4 @@
= form.text_field :message, autocomplete: 'off', spellcheck: 'true', maxlength: 250, size: 80
%p
= form.submit "Prévisualiser", id: "wiki_preview"
- = form.submit (form.object.new_record? ? "Créer" : "Mettre à jour") if @preview_mode
+ = form.submit (form.object.new_record? ? "Créer" : "Mettre à jour") if @preview_mode and @wiki_page.valid?
diff --git a/app/views/wiki_pages/_wiki_page.atom.builder b/app/views/wiki_pages/_wiki_page.atom.builder
index 022a6e4ba..7cc4089a6 100644
--- a/app/views/wiki_pages/_wiki_page.atom.builder
+++ b/app/views/wiki_pages/_wiki_page.atom.builder
@@ -9,5 +9,5 @@ feed.entry(wiki_page) do |entry|
wiki_page.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
- entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{wiki_page.node.id}/comments.atom"
+ entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{wiki_page.node.id}/comments.atom"
end
diff --git a/app/views/wiki_pages/edit.html.haml b/app/views/wiki_pages/edit.html.haml
index 58eaeda01..ea741db14 100644
--- a/app/views/wiki_pages/edit.html.haml
+++ b/app/views/wiki_pages/edit.html.haml
@@ -1,7 +1,7 @@
%main#contents(role="main")
=h1 "Modifier une page de wiki"
- = render "preview", preview: @wiki_page if @preview_mode
+ = render "preview", preview: @wiki_page if @preview_mode and @wiki_page.valid?
= form_for @wiki_page do |form|
= messages_on_error @wiki_page
diff --git a/app/views/wiki_pages/new.html.haml b/app/views/wiki_pages/new.html.haml
index 1348cf479..7451d3b2e 100644
--- a/app/views/wiki_pages/new.html.haml
+++ b/app/views/wiki_pages/new.html.haml
@@ -4,7 +4,7 @@
%p
Des règles de modération sont applicables aux pages du wiki (et au reste du site).
- = render "preview", preview: @wiki_page if @preview_mode
+ = render "preview", preview: @wiki_page if @preview_mode and @wiki_page.valid?
= form_for @wiki_page do |form|
= messages_on_error @wiki_page
diff --git a/bin/cap b/bin/cap
deleted file mode 100755
index 30352d4d4..000000000
--- a/bin/cap
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env ruby
-#
-# This file was generated by Bundler.
-#
-# The application 'cap' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-require 'pathname'
-ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
- Pathname.new(__FILE__).realpath)
-
-require 'rubygems'
-require 'bundler/setup'
-
-load Gem.bin_path('capistrano', 'cap')
diff --git a/bin/ci b/bin/ci
new file mode 100755
index 000000000..4137ad5bb
--- /dev/null
+++ b/bin/ci
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+require_relative "../config/boot"
+require "active_support/continuous_integration"
+
+CI = ActiveSupport::ContinuousIntegration
+require_relative "../config/ci.rb"
diff --git a/bin/dev b/bin/dev
new file mode 100755
index 000000000..5f91c2054
--- /dev/null
+++ b/bin/dev
@@ -0,0 +1,2 @@
+#!/usr/bin/env ruby
+exec "./bin/rails", "server", *ARGV
diff --git a/bin/rails b/bin/rails
index 073966023..efc037749 100755
--- a/bin/rails
+++ b/bin/rails
@@ -1,4 +1,4 @@
#!/usr/bin/env ruby
-APP_PATH = File.expand_path('../config/application', __dir__)
-require_relative '../config/boot'
-require 'rails/commands'
+APP_PATH = File.expand_path("../config/application", __dir__)
+require_relative "../config/boot"
+require "rails/commands"
diff --git a/bin/rake b/bin/rake
index 17240489f..4fbf10b96 100755
--- a/bin/rake
+++ b/bin/rake
@@ -1,4 +1,4 @@
#!/usr/bin/env ruby
-require_relative '../config/boot'
-require 'rake'
+require_relative "../config/boot"
+require "rake"
Rake.application.run
diff --git a/bin/setup b/bin/setup
index 9d46d1931..00c69507f 100755
--- a/bin/setup
+++ b/bin/setup
@@ -1,33 +1,36 @@
#!/usr/bin/env ruby
-require 'fileutils'
-include FileUtils
+require "fileutils"
-# path to your application root.
-APP_ROOT = File.expand_path('..', __dir__)
+APP_ROOT = File.expand_path("..", __dir__)
def system!(*args)
- system(*args) || abort("\n== Command #{args} failed ==")
+ system(*args, exception: true)
end
-chdir APP_ROOT do
- # This script is a starting point to setup your application.
+FileUtils.chdir APP_ROOT do
+ # This script is a way to set up or update your development environment automatically.
+ # This script is idempotent, so that you can run it at any time and get an expectable outcome.
# Add necessary setup steps to this file.
- puts '== Installing dependencies =='
- system! 'gem install bundler --conservative'
- system('bundle check') || system!('bundle install')
+ puts "== Installing dependencies =="
+ system("bundle check") || system!("bundle install")
- puts "\n== Installing npm modules =="
- system! 'npm install'
-
- # puts "\n== Copying sample files =="
- unless File.exist?('config/database.yml')
- cp 'config/database.yml.sample', 'config/database.yml'
- end
- unless File.exist?('config/secrets.yml')
- cp 'config/secrets.yml.sample', 'config/secrets.yml'
+ puts "\n== Copying sample files =="
+ unless File.exist?("config/database.yml")
+ FileUtils.cp "config/database.yml.sample", "config/database.yml"
end
puts "\n== Preparing database =="
- system! 'bin/rails db:setup'
+ system! "bin/rails db:prepare"
+
+ system! "bin/rails db:reset" if ARGV.include?("--reset")
+
+ puts "\n== Removing old logs and tempfiles =="
+ system! "bin/rails log:clear tmp:clear"
+
+ unless ARGV.include?("--skip-server")
+ puts "\n== Starting development server =="
+ STDOUT.flush # flush the output before exec(2) so that it displays
+ exec "bin/dev"
+ end
end
diff --git a/bin/spring b/bin/spring
deleted file mode 100755
index 814ead74d..000000000
--- a/bin/spring
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env ruby
-
-# This file loads spring without using Bundler, in order to be fast.
-# It gets overwritten when you run the `spring binstub` command.
-
-unless defined?(Spring)
- require "rubygems"
- require "bundler"
-
- if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)
- Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
- gem "spring", match[1]
- require "spring/binstub"
- end
-end
diff --git a/bin/update b/bin/update
index 692cf21f2..0ecd84db4 100755
--- a/bin/update
+++ b/bin/update
@@ -1,9 +1,9 @@
#!/usr/bin/env ruby
-require 'fileutils'
+require "fileutils"
include FileUtils
# path to your application root.
-APP_ROOT = File.expand_path('..', __dir__)
+APP_ROOT = File.expand_path("..", __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
@@ -13,16 +13,13 @@ chdir APP_ROOT do
# This script is a way to update your development environment automatically.
# Add necessary update steps to this file.
- puts '== Installing dependencies =='
- system! 'gem install bundler --conservative'
- system('bundle check') || system!('bundle install')
-
- puts "\n== Installing npm modules =="
- system! 'npm install'
+ puts "== Installing dependencies =="
+ system! "gem install bundler --conservative"
+ system("bundle check") || system!("bundle install")
puts "\n== Updating database =="
- system! 'bin/rails db:migrate'
+ system! "bin/rails db:migrate"
puts "\n== Removing old logs and tempfiles =="
- system! 'bin/rails log:clear tmp:clear'
+ system! "bin/rails log:clear tmp:clear"
end
diff --git a/docker-compose.yaml b/compose.yaml
similarity index 84%
rename from docker-compose.yaml
rename to compose.yaml
index 6e1afd3e2..e4da03f3b 100644
--- a/docker-compose.yaml
+++ b/compose.yaml
@@ -2,7 +2,7 @@ services:
linuxfr.org:
build:
context: .
- dockerfile: deployment/linuxfr.org/Dockerfile
+ dockerfile: deployment/linuxfr.org/Containerfile
env_file:
- deployment/default.env
volumes:
@@ -10,6 +10,8 @@ services:
# and see the result without need to restart the container
- ./app:/linuxfr.org/app:Z
- ./db:/linuxfr.org/db:Z
+ - ./Gemfile:/linuxfr.org/Gemfile:Z
+ - ./Gemfile.lock:/linuxfr.org/Gemfile.lock:Z
- ./lib:/linuxfr.org/lib:Z
- ./public:/linuxfr.org/public:Z
- ./test:/linuxfr.org/test:Z
@@ -60,7 +62,7 @@ services:
- cache-img:/linuxfr-img/cache
nginx:
- image: docker.io/nginx:stable
+ image: docker.io/nginxinc/nginx-unprivileged:stable-alpine
env_file:
- deployment/default.env
volumes:
@@ -68,11 +70,14 @@ services:
- ./public/fonts:/var/linuxfr/fonts:Z
- data-uploads:/var/linuxfr/uploads
ports:
- - target: 80
- published: 127.0.0.1:80
+ - target: 8080
+ # If you customize the published port, you have to update the
+ # DOMAIN_HTTP_PORT and IMAGE_DOMAIN_HTTP_PORT variables
+ # into the `deployment/default.env` file too
+ published: 127.0.0.1:9000
protocol: tcp
healthcheck:
- test: ["CMD", "curl", "--silent", "--fail", "--fail-early", "--head", "http://$$DOMAIN", "http://$$DOMAIN/img", "http://$$DOMAIN/b", "http://$$IMAGE_DOMAIN/status"]
+ test: ["CMD", "curl", "--silent", "--fail", "--fail-early", "--location", "--head", "http://$$DOMAIN:8080", "http://$$DOMAIN:8080/img/status", "http://$$DOMAIN:8080/b", "http://$$IMAGE_DOMAIN:8080/status"]
interval: 10s
start_period: 5s
depends_on:
diff --git a/config.ru b/config.ru
index 547e0f794..ed1b7d1db 100644
--- a/config.ru
+++ b/config.ru
@@ -8,3 +8,4 @@ if defined?(Unicorn::HttpRequest)
end
run Rails.application
+Rails.application.load_server
diff --git a/config/application.rb b/config/application.rb
index bd4033c13..a097d366c 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,12 +1,18 @@
-# encoding: utf-8
-require_relative 'boot'
+require_relative "boot"
-require 'rails/all'
+require "rails/all"
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module LinuxfrOrg
class Application < Rails::Application
+ # Initialize configuration defaults for originally generated Rails version.
+ config.load_defaults 8.1
+
+ config.action_view.button_to_generates_button_tag = false
+
I18n.enforce_available_locales = true
config.generators do |g|
@@ -20,7 +26,19 @@ class Application < Rails::Application
ActiveSupport::XmlMini.backend = "Nokogiri"
end
- config.time_zone = 'Paris'
+ # Please, add to the `ignore` list any other `lib` subdirectories that do
+ # not contain `.rb` files, or that should not be reloaded or eager loaded.
+ # Common ones are `templates`, `generators`, or `middleware`, for example.
+ config.autoload_lib(ignore: %w[assets tasks])
+
+ # Configuration for the application, engines, and railties goes here.
+ #
+ # These settings can be overridden in specific environments using the files
+ # in config/environments, which are processed later.
+ #
+ config.time_zone = "Paris"
+ # config.time_zone = "Central Time (US & Canada)"
+ # config.eager_load_paths << Rails.root.join("extras")
config.to_prepare do
Doorkeeper::AuthorizationsController.layout "doorkeeper"
diff --git a/config/boot.rb b/config/boot.rb
index b9e460cef..988a5ddc4 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,4 +1,4 @@
-ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
-require 'bundler/setup' # Set up gems listed in the Gemfile.
-require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
+require "bundler/setup" # Set up gems listed in the Gemfile.
+require "bootsnap/setup" # Speed up boot time by caching expensive operations.
diff --git a/config/cable.yml b/config/cable.yml
new file mode 100644
index 000000000..89298772a
--- /dev/null
+++ b/config/cable.yml
@@ -0,0 +1,10 @@
+development:
+ adapter: async
+
+test:
+ adapter: test
+
+production:
+ adapter: redis
+ url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
+ channel_prefix: linuxfr_org_production
diff --git a/config/ci.rb b/config/ci.rb
new file mode 100644
index 000000000..2e19ccc40
--- /dev/null
+++ b/config/ci.rb
@@ -0,0 +1,19 @@
+# Run using bin/ci
+
+CI.run do
+ step "Setup", "bin/setup --skip-server"
+
+ step "Security: Importmap vulnerability audit", "bin/importmap audit"
+
+ step "Tests: Rails", "bin/rails test"
+ step "Tests: System", "bin/rails test:system"
+ step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant"
+
+ # Optional: set a green GitHub commit status to unblock PR merge.
+ # Requires the `gh` CLI and `gh extension install basecamp/gh-signoff`.
+ # if success?
+ # step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff"
+ # else
+ # failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again."
+ # end
+end
diff --git a/config/credentials/development.key b/config/credentials/development.key
new file mode 100644
index 000000000..8d925ce92
--- /dev/null
+++ b/config/credentials/development.key
@@ -0,0 +1 @@
+f08f41e290950c209023581e95e5ac7d
\ No newline at end of file
diff --git a/config/credentials/development.yml.enc b/config/credentials/development.yml.enc
new file mode 100644
index 000000000..6d8534c8f
--- /dev/null
+++ b/config/credentials/development.yml.enc
@@ -0,0 +1 @@
+wKVNWIoPMuIB4DY10pk4Vg6yV1dyi/NlPbbLmafmwwfbXPE14NaWWegemmFMo2Q+hurEP+cdxFb6Otl4D7/Kw+0IE3Fca9azqTiD2mAhRobVyvebX8frUhw/0ltNyUhw43V/s4oKC+bWUyfyB1w74d0uwLs08tzr7BwEwqCRx71xstcqY6uFxku3er/Z5AW+yTJl/FHf177YozUJJ1hZz6RAUOyt9TCxGh2luqk8aonrKwkzPYsQWc3O7rRrFEcvrrce3ic36Giveu9fKj2pI1Obk7zizI49Cb25imJyKAIzL9zUFvRCjDj6BjgrZ0aLaba2blKnC/UbCTeq3qMo/URchQBeW7lONQg0XQjSu2YZafcezpvFmluzu1TjRSZ1OmJjZKFsfRAEepxDTpw3wkpPaQRhURob8cH3qbp6VNjGKz86axBC/oHm3YbUR1mPfvomNrmAyqGq2Yr79VICx6w1AX+Yiy9CsGQVqu0gOJ1dsclS840ZA7IxwA7E3nIbGW/BbQ4FwPagInQyM0gkqjC5QRn7e3uHQEHCAtjlOcyLZ1qpJTRa9YV7HBfM/wGyR4bk8cAB--bUuDeo7eYZhBoYL9--fKYwyQcfzMXds2Yn/xpbsg==
\ No newline at end of file
diff --git a/config/credentials/test.key b/config/credentials/test.key
new file mode 100644
index 000000000..23c0e71d9
--- /dev/null
+++ b/config/credentials/test.key
@@ -0,0 +1 @@
+d3f4c631986edacfc0a5eba8e2bb95ad
\ No newline at end of file
diff --git a/config/credentials/test.yml.enc b/config/credentials/test.yml.enc
new file mode 100644
index 000000000..5b0dbae4b
--- /dev/null
+++ b/config/credentials/test.yml.enc
@@ -0,0 +1 @@
+Ysn8Z8G6nBc+AE40ROjvwY39bePKIlN25U3lVg0kGZzIfsjH0gJAv/MAPdzUS5uz4JwY46SbADeTJOE3WMLBflCq7PUhJkLyqZbe3412AUexOdcfTDKmO8WLWi5wAV2amQKWB2wd2+5BttT8qQsMixslPEEjI/vMH9Z9HNZ8EyQLSM/zWdM40bZ2v9k1yLhLWj+6NZhDBYxMc1rl5FMTeM/OkKg5zrXuZ+D5qLLc/2DvRsv03UDEbz4/isfNjReH3TcvroMqsW1D4O4J08P++thk+hGNV0G9Zqqqn6g9ifM6YG7QzVJWfjB7lGHTV4RsH3xRZK6AaIAttVCeCTL7T3sKznQjbhDvo/4WK3ac8C2W4r3blxsyvwkqI/DxzYIr0nz0fp0/k9V6TozqZYeyOcPcCOUzxOr2TLR2AIRewS4A8v4Np5lEfkTlLhCMdy/OsTs5ngJCURV9SLgz30g6EZvgWwQ6VFfKH0Ao9r/sSixQ/mgCtqnNepybNYM4ALP2RKlXhcBqUhXQJRLY8+i9l12HL/wOs3AhuYMxwSnJHakigSEuCYlxrx9I+mvALK9ECR+3Zp3S--1IMNQ/Ks0uYayfvS--I+lN3XglqcY7/qhHTLognQ==
\ No newline at end of file
diff --git a/config/deploy.rb b/config/deploy.rb
deleted file mode 100644
index f43cad056..000000000
--- a/config/deploy.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-# encoding: utf-8
-
-# SSH to the servers
-require 'sushi/ssh'
-
-# Bundler
-require 'bundler/capistrano'
-
-# Maintenance
-require 'capistrano/maintenance'
-set :maintenance_template_path, File.expand_path("../templates/maintenance.rhtml", __FILE__)
-
-# Assets
-set :public_children, %w(images)
-load 'deploy/assets'
-
-# Common options
-set :use_sudo, false
-set :scm, :git
-set :repository, "git://github.com/linuxfrorg/linuxfr.org.git"
-set :deploy_via, :remote_cache
-
-default_run_options[:pty] = true
-
-
-# We have two environments: alpha and prod.
-# To make a deploy, precise on which environment, like this:
-# $ cap prod deploy
-desc "Alpha environment"
-task :alpha do
- set :vserver, "alpha"
- set :user, "alpha"
- set :branch, $1 if `git branch` =~ /\* (\S+)\s/m
- set :rails_env, "alpha"
-end
-
-desc "Production"
-task :prod do
- set :vserver, "prod"
- set :user, "linuxfr"
- set :branch, "master"
- set :rails_env, "production"
-end
-
-desc "[internal] Common stuff to alpha and production"
-task :common do
- set :application, "#{vserver}.linuxfr.org"
- set :deploy_to, "/data/#{vserver}/#{user}/#{rails_env}"
- server "#{user}@#{application}", :app, :web, :db, primary: true
- depend :remote, :file, "#{shared_path}/config/database.yml"
- depend :remote, :file, "#{shared_path}/config/secrets.yml"
-end
-after "alpha", "common"
-after "prod", "common"
-
-
-# Check that we have invoked an environment before deploying
-before :deploy do
- unless exists?(:deploy_to)
- raise "Please invoke me like `cap env:Lorem ipsum dolor sit amet, consectetur adipiscing elit. @@ -55,7 +70,7 @@ lorem_copyright: Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. - Maecenas adipiscing ante non diam sodales hendrerit. + Maecenas adipiscing ante non diam sodales hendrerit. wiki_body: >-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. diff --git a/test/fixtures/files/Logo.png b/test/fixtures/files/Logo.png new file mode 100644 index 000000000..13ee22f9c Binary files /dev/null and b/test/fixtures/files/Logo.png differ diff --git a/test/fixtures/files/blue-smooth.scss b/test/fixtures/files/blue-smooth.scss new file mode 100644 index 000000000..caaf56602 --- /dev/null +++ b/test/fixtures/files/blue-smooth.scss @@ -0,0 +1,2174 @@ +/** + * Author: Mounir + * License: CC-by-sa - http://creativecommons.org/licenses/by-sa/3.0/deed.fr + */ + +/* Contenu par défaut */ + +@font-face { + font-family: Megalopolis; + src: url("/fonts/MEgalopolisExtra.otf") format("opentype"); +} + +/* Contenu par défaut */ + +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +font, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +/* line 17, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +body { + line-height: 1; + color: black; + background: -moz-linear-gradient(#c0c4c8, #c8ccd0); + background-color: #b0c0d0; + font-size: 12px; +} + +/* line 19, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +ol, +ul { + list-style: none; +} + +/* line 21, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +table { + border-collapse: separate; + border-spacing: 0; + vertical-align: middle; +} + +/* line 23, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +caption, +th, +td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} + +/* line 25, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +q, +blockquote { + quotes: "" ""; +} +/* line 96, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +/* line 27, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +a img { + border: none; +} + +/* line 108, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +article, +aside, +canvas, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section, +summary { + margin: 0; + padding: 0; + border: 0; + outline: 0; + display: block; +} + +aside#sidebar { + position: relative; + top: -20px; + padding: 0; +} + +/* line 41, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss */ +body.bp .box { + padding: 1.5em; + margin-bottom: 1.5em; + background: #e5ecf9; +} +/* line 44, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss */ +body.bp div.border { + padding-right: 4px; + margin-right: 5px; + border-right: 1px solid #eeeeee; +} +/* line 47, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss */ +body.bp div.colborder { + padding-right: 24px; + margin-right: 25px; + border-right: 1px solid #eeeeee; +} +/* line 49, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss */ +body.bp hr { + background: #dddddd; + color: #dddddd; + clear: both; + float: none; + width: 100%; + height: 0.1em; + margin: 0 0 1.45em; + border: none; +} +/* line 51, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss */ +body.bp hr.space { + background: #dddddd; + color: #dddddd; + clear: both; + float: none; + width: 100%; + height: 0.1em; + margin: 0 0 1.45em; + border: none; + background: white; + color: white; + visibility: hidden; +} +/* line 53, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_scaffolding.scss */ +body.bp form.inline { + line-height: 3; +} +/* line 6, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +body.bp form.inline p { + margin-bottom: 0; +} + +/* line 23, ../../app/stylesheets/_application.scss */ +body { + line-height: 1.5; + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + color: #33332d; + font-size: 75%; +} +/* line 65, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h1, +body h2, +body h3, +body h4, +body h5, +body h6 { + font-weight: normal; + color: #607080; +} +/* line 66, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h1 img, +body h2 img, +body h3 img, +body h4 img, +body h5 img, +body h6 img { + margin: 0; +} +/* line 67, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h1 { + font-size: 3em; + line-height: 1; + margin-bottom: 0.5em; +} +/* line 68, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h2 { + font-size: 2em; + margin-bottom: 0.75em; +} +/* line 69, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h3 { + font-size: 1.5em; + line-height: 1; + margin-bottom: 1em; +} +/* line 70, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h4 { + font-size: 1.2em; + line-height: 1.25; + margin-bottom: 1.25em; +} +/* line 71, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h5 { + font-size: 1em; + font-weight: bold; + margin-bottom: 1.5em; +} +/* line 72, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body h6 { + font-size: 1em; + font-weight: bold; +} +/* line 73, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body p { + margin: 0 0 1.5em; +} +/* line 74, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body p img.left { + display: inline; + float: left; + margin: 1.5em 1.5em 1.5em 0; + padding: 0; +} +/* line 75, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body p img.right { + display: inline; + float: right; + margin: 1.5em 0 1.5em 1.5em; + padding: 0; +} +/* line 77, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body a { + text-decoration: underline; + color: #000099; +} +/* line 18, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_link-colors.scss */ +body a:visited { + color: black; +} +/* line 21, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_link-colors.scss */ +body a:focus { + color: black; +} +/* line 24, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_link-colors.scss */ +body a:hover { + color: black; +} +/* line 27, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_link-colors.scss */ +body a:active { + color: black; +} +/* line 78, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body blockquote { + margin: 1.5em; + color: #666666; + font-style: italic; +} +/* line 79, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body strong { + font-weight: bold; +} +/* line 80, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body em { + font-style: italic; +} +/* line 81, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body dfn { + font-style: italic; + font-weight: bold; +} +/* line 82, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body sup, +body sub { + line-height: 0; +} +/* line 83, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body abbr, +body acronym { + border-bottom: 1px dotted #666666; +} +/* line 84, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body address { + margin: 0 0 1.5em; + font-style: italic; +} +/* line 85, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body del { + color: #666666; +} +/* line 86, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body pre { + margin: 1.5em 0; + white-space: pre; +} +/* line 87, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body pre, +body code, +body tt { + font: 1em "andale mono", "lucida console", monospace; + line-height: 1.5; +} +/* line 88, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body li ul, +body li ol { + margin: 0; +} +/* line 89, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body ul, +body ol { + margin: 0 1.5em 1.5em 0; + padding-left: 3.333em; +} +/* line 90, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body ul { + list-style-type: disc; +} +/* line 91, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body ol { + list-style-type: decimal; +} +/* line 92, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body dl { + margin: 0 0 1.5em 0; +} +/* line 93, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body dl dt { + font-weight: bold; +} +/* line 94, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body dd { + margin-left: 1.5em; +} +/* line 95, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body table { + margin-bottom: 1.4em; + width: 100%; +} +/* line 96, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body th { + font-weight: bold; +} +/* line 97, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body thead th { + background: #c3d9ff; +} +/* line 98, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body th, +body td, +body caption { + padding: 4px 10px 4px 5px; +} +/* line 99, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body tr.even td { + background: #e5ecf9; +} +/* line 100, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body tfoot { + font-style: italic; +} +/* line 101, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body caption { + background: #eeeeee; +} +/* line 102, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body .quiet { + color: #666660; +} +/* line 103, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_typography.scss */ +body .loud { + color: #11110b; +} +/* line 9, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .clear { + clear: both; +} +/* line 12, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .nowrap { + white-space: nowrap; +} +/* line 16, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .clearfix { + overflow: hidden; + *zoom: 1; +} +/* line 18, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .small { + font-size: 0.8em; + margin-bottom: 1.875em; + line-height: 1.875em; +} +/* line 22, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .large { + font-size: 1.2em; + line-height: 2.5em; + margin-bottom: 1.25em; +} +/* line 26, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .first { + margin-left: 0; + padding-left: 0; +} +/* line 29, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .last { + margin-right: 0; + padding-right: 0; +} +/* line 32, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .top { + margin-top: 0; + padding-top: 0; +} +/* line 35, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_utilities.scss */ +body .bottom { + margin-bottom: 0; + padding-bottom: 0; +} +/* line 8, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_debug.scss */ +body .showgrid { + background: url("/images/grid.png"); +} +/* line 4, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .error { + padding: 0.8em; + margin-bottom: 1em; + border: 2px solid #dddddd; + background: #fbe3e4; + color: #8a1f11; + border-color: #fbc2c4; +} +/* line 29, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .error a { + color: #8a1f11; +} +/* line 6, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .notice { + padding: 0.8em; + margin-bottom: 1em; + border: 2px solid #dddddd; + background: #fff6bf; + color: #514721; + border-color: #ffd324; +} +/* line 37, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .notice a { + color: #514721; +} +/* line 8, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .success { + padding: 0.8em; + margin-bottom: 1em; + border: 2px solid #dddddd; + background: #e6efc2; + color: #264409; + border-color: #c6d880; +} +/* line 45, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .success a { + color: #264409; +} +/* line 10, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .hide { + display: none; +} +/* line 12, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .highlight { + background: yellow; +} +/* line 14, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .added { + background: #006600; + color: white; +} +/* line 16, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_interaction.scss */ +body .removed { + background: #990000; + color: white; +} + +/* line 18, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form label { + font-weight: bold; +} +/* line 19, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form fieldset { + padding: 1.4em; + margin: 0 0 1.5em 0; +} +/* line 20, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form legend { + font-weight: bold; + font-size: 1.2em; +} +/* line 26, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form input.text, +form input.title, +form input[type="email"], +form input[type="text"], +form input[type="password"] { + margin: 0.5em 0; + background-color: white; + padding: 5px; +} +/* line 27, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form input.title { + font-size: 1.5em; +} +/* line 31, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form input[type="checkbox"], +form input.checkbox, +form input[type="radio"], +form input.radio { + position: relative; + top: 0.25em; +} +/* line 33, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form textarea { + margin: 0.5em 0; + padding: 5px; +} +/* line 34, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form select { + margin: 0.5em 0; +} +/* line 59, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form fieldset { + border: 1px solid #cccccc; +} +/* line 62, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form input.text, +form input.title, +form input[type="email"], +form input[type="text"], +form input[type="password"], +form textarea, +form select { + border: 1px solid #bbbbbb; +} +/* line 64, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form input.text:focus, +form input.title:focus, +form input[type="email"]:focus, +form input[type="text"]:focus, +form input[type="password"]:focus, +form textarea:focus, +form select:focus { + border: 1px solid #666666; +} +/* line 48, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form input.text, +form input.title, +form input[type="email"], +form input[type="text"], +form input[type="password"] { + width: 300px; + background: -moz-linear-gradient(white, #e8e8e8) white; + border: 1px solid #405070; + padding: 0; +} +/* line 50, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/blueprint/stylesheets/blueprint/_form.scss */ +form textarea { + width: 390px; + height: 250px; +} + +/* line 1, ../../app/stylesheets/layout/_site.scss */ +#site { + background: -moz-linear-gradient(#8090a0, #607080) repeat scroll 0 0 + transparent; + background-color: #607080; + border-bottom: 2px solid #405070; + margin-bottom: 20px; + padding: 1px 0 1px 0; +} +/* line 5, ../../app/stylesheets/layout/_site.scss */ +#site .go_to_content { + float: left; + text-indent: -119988px; + overflow: hidden; + text-align: left; +} +/* line 8, ../../app/stylesheets/layout/_site.scss */ +#site ul { + display: inline; + list-style: none; + width: 100%; +} +/* line 4, ../../app/stylesheets/mixins/_list.scss */ +#site ul li { + display: inline; +} +/* line 10, ../../app/stylesheets/mixins/_list.scss */ +#site ul li:after { + content: " | "; +} +/* line 13, ../../app/stylesheets/mixins/_list.scss */ +#site ul li:last-child:after, +#site ul li.last:after { + content: ""; +} +/* line 11, ../../app/stylesheets/layout/_site.scss */ +#site ul li { + padding: 5px 0; + color: white; + font-size: 1em; +} +/* line 15, ../../app/stylesheets/layout/_site.scss */ +#site ul li a { + color: inherit; + text-decoration: none; +} +/* line 4, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_hover-link.scss */ +#site ul li a:hover { + text-decoration: underline; +} +/* line 18, ../../app/stylesheets/layout/_site.scss */ +#site form { + float: right; +} + +/* line 21, ../../app/stylesheets/layout/_site.scss */ +#label_query { + float: left; + text-indent: -119988px; + overflow: hidden; + text-align: left; +} + +#query { + background: -moz-linear-gradient(#a0b0c0, #a8b8c8) repeat scroll 0 0 + transparent; + background-color: #a0a8b0; + border: 1px solid black; +} + +/* line 1, ../../app/stylesheets/layout/_sidebar.scss */ +#sidebar { + padding: 10px; +} +/* line 6, ../../app/stylesheets/layout/_sidebar.scss */ +#sidebar .box { + margin: 15px 0 0 0; + padding: 10px; + background-color: #a8b8c8; + border-style: solid; + border-color: black; + border-width: 2px 2px 2px 0; +} + +#sidebar .box a { + font-weight: bold; + text-decoration: none; + color: #203040; +} + +#sidebar .box ul { + padding-left: 2em; +} + +#sidebar .box li { + font-weight: bold; + text-decoration: none; + color: #203040; +} + +#sidebar .login { + padding: 0; + padding-bottom: 10px; +} + +#sidebar .login > h1 { + background: -moz-linear-gradient(#8090a0, #607080); + background-color: #607080; + border-bottom: 1px solid #405070; + font-size: 1.4em; + font-weight: bold; + color: white; + padding: 0.1em 0 0.4em 2px; + text-align: left; +} + +#sidebar .login > h1 a { + text-decoration: none; + color: white; +} + +#sidebar .login p { + margin: 0; + padding-left: 1em; + margin-bottom: 0; +} + +#sidebar .login p:first-letter { + font-weight: bold; +} + +#sidebar .login p a { + text-decoration: none; + color: black; +} + +/* line 12, ../../app/stylesheets/layout/_sidebar.scss */ +#sidebar h1 { + font-size: 1.6em; + text-align: center; +} +/* line 15, ../../app/stylesheets/layout/_sidebar.scss */ +#sidebar input { + max-width: 180px; +} +/* line 17, ../../app/stylesheets/layout/_sidebar.scss */ +#sidebar .forum h2 { + font-size: 1.1em; +} + +/* line 21, ../../app/stylesheets/layout/_sidebar.scss */ +#branding h1 { + display: block; + width: 201px; + height: 186px; + border-bottom: 2px solid black; + border-right: 2px solid black; + -moz-border-radius-bottomright: 10px; +} +/* line 27, ../../app/stylesheets/layout/_sidebar.scss */ +#branding h1 a { + display: block; + width: 100%; + height: 100%; + text-indent: -119988px; + overflow: hidden; + text-align: left; +} + +/* line 2, ../../app/stylesheets/layout/_container.scss */ +#container > h1 { + margin-bottom: 1em; + text-align: center; + font-family: Megalopolis, helvetica, arial, serif; + font-size: 3.5em; + font-weight: bolder; + line-height: 1em; +} + +/* +#container nav.toolbox +{ + background:-moz-linear-gradient(white, #F0F0F0); + border:2px solid #1F1F18; + -moz-border-radius:10px; +} +*/ + +/* Navigation */ + +#container nav.toolbox > div, +#container nav.toolbox > div a { + margin: 0 auto 0 auto; + /* background:-moz-linear-gradient(#8090A0, #607080) #607080; */ + text-align: center; + text-decoration: none; + color: #607080; +} + +#container nav.toolbox > div a:hover { + background: white; + opacity: 0.5; +} + +/* Suivi (faire une demande pour obtenir un vrai id) */ + +#container > p, +#container > p a, +#container > footer, +#container > footer a { + text-decoration: none; + color: #607080; +} + +#container > p a:hover, +#container > footer a:hover { + background: white; + opacity: 0.5; +} + +/* line 9, ../../app/stylesheets/layout/_container.scss */ +#container nav.toolbox ul, +#container .toolbox li { + display: inline; +} + +/* line 1, ../../app/stylesheets/layout/_bigfooter.scss */ +#bigfooter { + margin: 15px 0 0; + background: -moz-linear-gradient(#8090a0, #607080) #607080; + padding-bottom: 25px; + border-top: 2px solid #405070; +} + +/* line 6, ../../app/stylesheets/layout/_bigfooter.scss */ +#bigfooter nav, +#bigfooter section { + display: inline-block; + padding-top: 5px; + height: 100%; + vertical-align: top; +} +/* line 11, ../../app/stylesheets/layout/_bigfooter.scss */ +#bigfooter nav h1, +#bigfooter section h1 { + font-size: 2em; + color: white; +} +/* line 13, ../../app/stylesheets/layout/_bigfooter.scss */ +#bigfooter #about_us { + margin-right: 0; +} + +#bigfooter a { + color: white; + text-decoration: none; +} + +/* line 7, ../../app/stylesheets/layout/_layout.scss */ +#site { + overflow: hidden; +} + +/* line 10, ../../app/stylesheets/layout/_layout.scss */ +#sidebar { + display: inline; + float: left; + overflow: hidden; + width: 20.003%; + margin-right: 1.042%; + width: 203px; +} + +/* line 14, ../../app/stylesheets/layout/_layout.scss */ +#container { +} +/* line 16, ../../app/stylesheets/layout/_layout.scss */ +#container > * { + margin: 0 50px 0 257px; +} + +/* line 19, ../../app/stylesheets/layout/_layout.scss */ +#edition { + display: inline; + float: left; + overflow: hidden; + width: 62.093%; + margin-right: 1.042%; +} + +/* line 22, ../../app/stylesheets/layout/_layout.scss */ +#chat { + display: inline; + float: left; + overflow: hidden; + width: 32.63%; + margin-right: 1.042%; +} + +/* line 25, ../../app/stylesheets/layout/_layout.scss */ +#bigfooter { + display: inline; + float: left; + overflow: hidden; + width: 99.974%; + margin-right: 1.042%; +} +/* line 27, ../../app/stylesheets/layout/_layout.scss */ +#bigfooter nav, +#bigfooter section { + display: inline; + float: left; + overflow: hidden; + width: 24.212%; + margin-right: 1.042%; +} + +/* line 1, ../../app/stylesheets/partials/_generics.scss */ +body { + color: #33332d; + font-family: "Droid Sans", sans-serif; +} + +/* line 5, ../../app/stylesheets/partials/_generics.scss */ +ins.diffins, +ins.diffmod { + background-color: #33ff33; +} + +/* line 8, ../../app/stylesheets/partials/_generics.scss */ +del.diffdel, +del.diffmod { + background-color: #ff3333; +} + +/* line 12, ../../app/stylesheets/partials/_generics.scss */ +a.action:before, +time.norloge:before, +span.content_type:before { + content: "["; +} +/* line 14, ../../app/stylesheets/partials/_generics.scss */ +a.action:after, +time.norloge:after, +span.content_type:after { + content: "]"; +} + +/* line 17, ../../app/stylesheets/partials/_generics.scss */ +footer.actions:before { + content: "⇾"; +} + +li#comment_new footer.actions:before { + content: ""; + height: 2em; + clear: both; +} + +/* line 20, ../../app/stylesheets/partials/_generics.scss */ +aside.banner { + background: -moz-linear-gradient(#8090a0, #607080) #607080; + font-size: 2em; + border: 2px solid black; + -moz-border-radius: 2em; + padding-left: 2em; + padding-right: 2em; + text-align: center; + color: white; +} + +aside.banner a { + font-weight: bold; + text-decoration: none; + color: white; +} + +/* line 1, ../../app/stylesheets/partials/_forms.scss */ +.fieldWithErrors input { + border: 1px solid red; +} + +/* line 2, ../../app/stylesheets/partials/_contents.scss */ +article { + margin: 15px 0; + padding: 0; + background: -moz-linear-gradient(white, #f0f0f0); + border: 2px solid #1f1f18; + overflow: hidden; +} + +article header { + margin: 0 0 0 0; +} + +/* line 9, ../../app/stylesheets/partials/_contents.scss */ +article header h1 { + margin: 0; + background: -moz-linear-gradient(#8090a0, #607080); + background-color: #607080; + border-bottom: 1px solid black; + padding-left: 2px; + font-family: Megalopolis, helvetica, arial, serif; + font-size: 1.4em; + color: white; +} + +/* line 14, ../../app/stylesheets/partials/_contents.scss */ +article header h1 a, +article header h1 a:visited { + text-decoration: none; + color: white; +} +/* line 4, ../../../../shared/bundle/ruby/1.9.1/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_hover-link.scss */ +article header h1 a:hover, +article header h1 a:active { + color: #e0e0e4; +} + +/* line 16, ../../app/stylesheets/partials/_contents.scss */ +article header h1 a + a:before { + content: " : "; +} + +article header .meta, +div#comments ul.threads li.comment p.meta, +div#contents ul.threads li.comment p.meta, +li#comment_new p.meta { + padding-left: 4px; + color: #808080; + font-style: italic; +} + +article header .meta a, +div#comments ul.threads li.comment p.meta a, +div#contents ul.threads li.comment p.meta a, +li#comment_new p.meta a { + color: #808080; + text-decoration: none; +} + +article header .meta a:hover, +div#comments ul.threads li.comment p.meta a:hover, +div#contents ul.threads li.comment p.meta a:hover, +li#comment_new p.meta a:hover { + color: black; + text-decoration: underline; +} + +/* line 18, ../../app/stylesheets/partials/_contents.scss */ +article figure { + float: left; + margin-left: 2px; + margin-right: 5px; +} +/* line 21, ../../app/stylesheets/partials/_contents.scss */ +article figure.score { + float: right; + width: 2em; + height: 2em; + margin-left: 5px; + margin-right: 1.5em; + padding: 0.2em 0 0 0; + background: -moz-linear-gradient(white, #e0e0f0); + border: 1px solid #e0e0f0; + border-radius: 2em; + -moz-border-radius: 2em; + -webkit-border-radius: 2em; + font-weight: bold; + text-align: center; + color: #a0a0b0; +} + +article div.tags { + float: right; +} + +/* line 29, ../../app/stylesheets/partials/_contents.scss */ +article ul.tag_cloud { + display: inline; + list-style: none; + margin-left: 0; + padding: 0; +} +/* line 4, ../../app/stylesheets/mixins/_list.scss */ +article ul.tag_cloud li { + display: inline; +} + +article div.content { + margin-top: 1em; + padding: 0 4.5em 1em 1.5em; +} + +article div.content a, +article footer.actions a { + text-decoration: none; + color: #405060; + font-weight: bold; +} + +/* +article div.content h2, +article div.content h3, +article div.content h4, +article div.content h2 a, +article div.content h3 a, +article div.content h4 a +{ + color:black; +} +*/ + +article#contents { + padding: 1em; +} + +article#contents > h1, +li#comment_new .content h1 { + margin-bottom: 0.7em; + padding-bottom: 0; + line-height: 85%; + font-size: 1.8em; + font-weight: bold; + text-align: center; +} + +article > h2, +article div.content h2, +article#contents div.body h2, +li#comment_new .content h2 { + margin-bottom: 0.7em; + border-bottom: 1px solid #607080; + padding-bottom: 0; + line-height: 85%; + font-size: 1.5em; + font-weight: bold; +} + +article > h3, +article div.content h3, +article#contents div.body h3, +li#comment_new .content h3 { + margin-bottom: 0.7em; + border-bottom: 1px solid #c0c4c8; + padding-bottom: 0; + line-height: 85%; + font-size: 1.3em; + font-weight: bold; +} + +article > h4, +article div.content h4, +article#contents div.body h4, +li#comment_new .content h4 { + margin-bottom: 0.7em; + font-size: 1.2em; + font-weight: bold; +} + +article#contents div.body h2, +article#contents div.body h3, +article#contents div.body h4, +li#comment_new .content h1, +li#comment_new .content h2, +li#comment_new .content h3, +li#comment_new .content h4 { + border-bottom: none; +} + +article div.content p { + text-align: justify; + text-indent: 1em; +} + +article div.content a:hover, +article div.content a:active, +article div.content a:visited, +article footer.actions a:hover, +article footer.actions a:active, +article footer.actions a:visited { + color: #203040; +} + +article div.content pre { + margin-left: 2em; + margin-right: 2em; + border: 1px solid #c8c8d0; + padding: 2px; + overflow: auto; +} + +/* line 4, ../../app/stylesheets/partials/_forms.scss */ + +article footer.actions, +div#comments ul.threads li.comment footer.actions, +div#contents ul.threads li.comment footer.actions { + padding: 0 1em 0 1em; + clear: both; + text-align: right; +} + +article footer.actions a.action, +div#comments ul.threads li.comment footer.actions a.action, +div#contents ul.threads li.comment footer.actions a.action { + vertical-align: top; + font-size: 0.9em; + font-weight: bold; + text-decoration: none; + color: black; +} + +#container header li .add_tag, +#container header li .remove_tag { + display: none; +} + +article footer.actions .vote, +div#comments ul.threads li.comment footer.actions .vote, +div#contents ul.threads li.comment footer.actions .vote { + font-size: 0.8em; + font-style: italic; + text-align: right; + color: #808080; +} + +article footer.actions .vote form.button_to, +div#comments ul.threads li.comment footer.actions .vote form, +div#contents ul.threads li.comment footer.actions .vote form { + display: inline-block; +} + +article footer.actions .vote form.button_to div input, +div#comments + ul.threads + li.comment + footer.actions + .vote + form.button_to + div + input, +div#contents + ul.threads + li.comment + footer.actions + .vote + form.button_to + div + input { + margin: 0px; + background: inherit; + border: 0px; + padding: 0px; + font: inherit; + font-weight: bold; +} + +div#comments { + margin-top: 1em; + padding: 0 4.5em 1em 1.5em; +} + +/* Lien "envoyer un commentaire" et "proposer une entrée" */ + +div#comments > p:first-child, +#container nav.toolbox div.new_content, +#container > p { + width: 15em; + margin: 1.5em auto 1.5em auto; + background: -moz-linear-gradient(#8090a0, #607080) #607080; + border: 2px solid black; + -moz-border-radius: 10px; + padding: 1px 2px 1px 2px; + font-weight: bold; + text-align: center; +} + +div#comments p:first-child a, +#container nav.toolbox div.new_content a, +#container > p a { + color: white; + text-decoration: none; +} + +/* Déclage de "proposer une entrée" dans suivi */ +#container > p { + position: relative; + left: 110px; +} + +div#comments ul.threads, +div#contents ul.threads { +} + +div#comments ul.threads li.comment, +div#contents ul.threads li.comment, +li#comment_new { + position: relative; + margin: 2em 0 0.5em 0; + background: -moz-linear-gradient(#e8ecf0, #d8dce0); + border-left: 1px solid #405060; + /*-moz-linear-gradient(#A0B0C0, #A8B8C8) #A0A8B0;*/ + list-style: none; +} + +div#comments ul.threads > li.comment, +div#contents ul.threads > li.comment, +li#comment_new { + /* + Les deux lignes suivantes règlent le problème de la propriété clear + du pied du commentaire qui décale le premier message + sous les boites du panneau de gauche ("Editions par ex.") + */ + display: inline-block; + width: 100%; + + border-right: 1px solid #405060; + border-bottom: 1px solid #405060; +} + +div#comments ul.threads > li.comment ul > li, +div#contents ul.threads > li.comment ul > li { + border-bottom: 1px solid #708090; + margin-bottom: 0; +} + +div#comments ul.threads > li.comment ul > li:last-child, +div#contents ul.threads > li.comment ul > li:last-child { + border-bottom: none; + margin-bottom: 0; +} + +div#comments ul.threads li.comment > h2, +div#contents ul.threads li.comment > h2, +li#comment_new > h2 { + margin: 0; + position: relative; + left: -2%; + top: -0.5em; + width: 102%; + background: -moz-linear-gradient(#8090a0, #607080); + background-color: #607080; + border: 2px solid black; + -moz-border-radius: 10px; + padding: 0 0 0 3px; + font-family: Megalopolis, helvetica, arial, serif; + font-size: 1em; +} + +div#comments ul.threads li.comment > h2, +div#comments ul.threads li.comment > h2 a, +div#comments ul.threads li.comment > h2 a:hover, +div#comments ul.threads li.comment > h2 a:visited, +div#comments ul.threads li.comment > h2 a:active, +div#contents ul.threads li.comment > h2, +div#contents ul.threads li.comment > h2 a, +div#contents ul.threads li.comment > h2 a:hover, +div#contents ul.threads li.comment > h2 a:visited, +div#contents ul.threads li.comment > h2 a:active, +li#comment_new h2 a, +li#comment_new h2 a:hover, +li#comment_new h2 a:visited, +li#comment_new h2 a:active { + color: white; + text-decoration: none; +} + +div#comments ul.threads li.comment div.content, +div#contents ul.threads li.comment div.content, +li#comment_new li.comment div.content { + margin-left: 1em; + margin-right: 1em; + padding: 2px 1em 1em 1em; + overflow: hidden; +} + +li#comment_new { + margin-left: 1em; +} + +/* line 34, ../../app/stylesheets/partials/_contents.scss */ +.comment .new_comment h3 { + border: 1px solid red; +} +/* line 36, ../../app/stylesheets/partials/_contents.scss */ +.comment .avatar { + float: left; + margin: 5px 10px; + box-shadow: 8px 8px 12px #607080; + -moz-box-shadow: 8px 8px 12px #aaa; + -webkit-box-shadow: 8px 8px 12px #aaa; +} +/* line 39, ../../app/stylesheets/partials/_contents.scss */ +.comment img { + max-width: 100%; +} + +/* line 44, ../../app/stylesheets/partials/_contents.scss */ +#polls .result, +.poll .result { + display: block; + margin: 0 0 0 10px; + background: -moz-linear-gradient(#a0b0c0, #a8b8c8) #a0a8b0; + border: 1px solid #333333; + -moz-border-radius-topright: 10px; + -moz-border-radius-bottomright: 10px; + padding-left: 2px; +} +/* line 49, ../../app/stylesheets/partials/_contents.scss */ +#polls ul, +.poll ul { + list-style: none; + margin-left: 10px; +} + +article ul.archived ul { + list-style: none; + margin-left: 0px; +} + +article ul.archived > li { + margin-bottom: 10px; +} + +/* line 56, ../../app/stylesheets/partials/_contents.scss */ +#tracker .fix a, +#tracker .invalid a, +.tracker .fix a, +.tracker .invalid a { + text-decoration: line-through; +} + +/* line 1, ../../app/stylesheets/partials/_toolbar.scss */ +#toolbar { + position: fixed; + overflow: hidden; + bottom: 0; + left: 20px; + right: 20px; + padding: 2px; + color: #333333; + background-color: #dfd6d1; + border: 1px solid #bbaaaa; +} + +/* line 12, ../../app/stylesheets/partials/_toolbar.scss */ +#toolbar_items { + float: right; +} + +/* line 15, ../../app/stylesheets/partials/_toolbar.scss */ +.fold > .meta, +.fold > .image, +.fold > .content, +.fold > .actions { + display: none; +} + +/* line 1, ../../app/stylesheets/partials/_autocomplete.scss */ +.ac_results { + padding: 0px; + border: 1px solid black; + background-color: white; + overflow: hidden; + z-index: 99999; +} +/* line 7, ../../app/stylesheets/partials/_autocomplete.scss */ +.ac_results ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} +/* line 13, ../../app/stylesheets/partials/_autocomplete.scss */ +.ac_results li { + font: menu; + margin: 0; + padding: 2px 5px; + cursor: default; + display: block; + font-size: 12px; + line-height: 16px; + overflow: hidden; +} + +/* line 23, ../../app/stylesheets/partials/_autocomplete.scss */ +.ac_loading { + background: white url("/images/ajax-loader.gif") right center no-repeat; +} + +/* line 26, ../../app/stylesheets/partials/_autocomplete.scss */ +.ac_odd { + background-color: #eeeeee; +} + +/* line 29, ../../app/stylesheets/partials/_autocomplete.scss */ +.ac_over { + background-color: #0a246a; + color: white; +} + +/* line 1, ../../app/stylesheets/partials/_notice.scss */ +.notice-wrap { + position: fixed; + top: 20px; + right: 20px; + width: 250px; + height: 1em; + z-index: 9999; +} + +/* line 8, ../../app/stylesheets/partials/_notice.scss */ +.notice-item { + height: 60px; + background: #333333; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + color: #eeeeee; + padding: 6px 6px 0 6px; + font-family: lucida Grande; + font-size: 11px; + border: 2px solid #999999; + display: block; + position: relative; + margin: 0 0 12px 0; +} + +/* line 22, ../../app/stylesheets/partials/_notice.scss */ +.notice-item-close { + position: absolute; + font-family: Arial; + font-size: 12px; + font-weight: bold; + right: 6px; + top: 6px; + cursor: pointer; +} + +/* line 1, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp { + /* width: 700px; */ + margin: 5px 0 5px 0; + /* border: 5px solid #f5f5f5; */ +} +/* line 6, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .markItUp a:link, +.markItUp .markItUp a:visited { + color: black; + text-decoration: none; +} + +.markItUpHeader { + background: black; +} + +.markItUpHeader > ul > li.markItUpButton { + background: -moz-linear-gradient(#8090a0, #607080) repeat scroll 0 0 #607080; + border: 1px solid #405070; +} + +/* line 10, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpContainer { + /* border: 1px solid #3c769d; */ + /* background: white url(/images/markitup/bg-container.png) repeat-x top left; */ + padding: 5px 5px 2px 5px; + font: 11px Verdana, Arial, Helvetica, sans-serif; +} + +/* line 16, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpEditor { + font: 12px "Courier New", Courier, monospace; + padding: 5px 5px 5px 35px; + border: 1px solid #405070; + /* width: 643px; */ + width: 90%; + margin: 0 auto 0 auto; + height: 320px; + background-image: url(/images/markitup/bg-editor-markdown.png); + background-repeat: no-repeat; + /* clear: both */ + display: block; + line-height: 18px; + -moz-box-shadow: 8px 8px 12px #aaa; + -webkit-box-shadow: 8px 8px 12px #aaa; + overflow: auto; +} + +/* line 29, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpPreviewFrame { + overflow: auto; + background-color: white; + border: 1px solid #3c769d; + width: 99.9%; + height: 300px; + margin: 5px 0; +} + +/* line 37, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpFooter { + width: 100%; + cursor: n-resize; +} + +/* line 41, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpResizeHandle { + overflow: hidden; + width: 22px; + height: 5px; + margin-left: auto; + margin-right: auto; + background-image: url(/images/markitup/handle.png); + cursor: n-resize; +} + +/* line 51, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul li { + list-style: none; + float: left; + position: relative; +} +/* line 55, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul li ul { + display: none; +} +/* line 57, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul li:hover > ul { + display: block; +} +/* line 59, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul a { + display: block; + width: 16px; + height: 16px; + text-indent: -10000px; + background-repeat: no-repeat; + padding: 3px; + margin: 0px; +} +/* line 67, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul .markItUpDropMenu { + background: transparent url(/images/markitup/menu.png) no-repeat 115% 50%; + margin-right: 5px; +} +/* line 70, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul .markItUpDropMenu li { + margin-right: 0px; +} +/* line 72, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul .markItUpSeparator { + margin: 0 10px; + width: 1px; + height: 16px; + overflow: hidden; + background-color: #cccccc; +} +/* line 78, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul { + display: none; + position: absolute; + top: 18px; + left: 0px; + background: #f5f5f5; + border: 1px solid #3c769d; + height: inherit; +} +/* line 86, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul .markItUpSeparator { + width: auto; + height: 1px; + margin: 0px; +} +/* line 90, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul li { + float: none; + border-bottom: 1px solid #3c769d; +} +/* line 93, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul .markItUpDropMenu { + background: #f5f5f5 url(/images/markitup/submenu.png) no-repeat 100% 50%; +} +/* line 95, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul ul { + position: absolute; + top: -1px; + left: 150px; +} +/* line 99, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul ul li { + float: none; +} +/* line 101, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul a { + display: block; + padding-left: 0px; + text-indent: 0; + width: 120px; + padding: 5px 5px 5px 25px; + background-position: 2px 50%; +} +/* line 108, ../../app/stylesheets/partials/_markitup.scss */ +.markItUpHeader ul ul a:hover { + color: white; + background-color: #3c769d; +} + +/* line 113, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .h1 a { + background-image: url(/images/markitup/h1.png); +} +/* line 115, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .h2 a { + background-image: url(/images/markitup/h2.png); +} +/* line 117, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .h3 a { + background-image: url(/images/markitup/h3.png); +} +/* line 119, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .h4 a { + background-image: url(/images/markitup/h4.png); +} +/* line 121, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .bold a { + background-image: url(/images/markitup/bold.png); +} +/* line 123, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .italic a { + background-image: url(/images/markitup/italic.png); +} +/* line 125, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .stroke a { + background-image: url(/images/markitup/stroke.png); +} +/* line 127, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .list-bullet a { + background-image: url(/images/markitup/list-bullet.png); +} +/* line 129, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .list-numeric a { + background-image: url(/images/markitup/list-numeric.png); +} +/* line 131, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .image a { + background-image: url(/images/markitup/picture.png); +} +/* line 133, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .link a { + background-image: url(/images/markitup/link.png); +} +/* line 135, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .quotes a { + background-image: url(/images/markitup/quotes.png); +} +/* line 137, ../../app/stylesheets/partials/_markitup.scss */ +.markItUp .code a { + background-image: url(/images/markitup/page_white_code.png); +} + +/* line 1, ../../app/stylesheets/pygments/colorful.scss */ +.hll { + background-color: #ffffcc; +} + +/* line 3, ../../app/stylesheets/pygments/colorful.scss */ +code.c { + color: #808080; +} + +/* line 5, ../../app/stylesheets/pygments/colorful.scss */ +.err { + color: #f00000; + background-color: #f0a0a0; +} + +/* line 8, ../../app/stylesheets/pygments/colorful.scss */ +.k { + color: #008000; + font-weight: bold; +} + +/* line 11, ../../app/stylesheets/pygments/colorful.scss */ +.o { + color: #303030; +} + +/* line 13, ../../app/stylesheets/pygments/colorful.scss */ +.cm { + color: #808080; +} + +/* line 15, ../../app/stylesheets/pygments/colorful.scss */ +.cp { + color: #507090; +} + +/* line 17, ../../app/stylesheets/pygments/colorful.scss */ +.c1 { + color: #808080; +} + +/* line 19, ../../app/stylesheets/pygments/colorful.scss */ +.cs { + color: #cc0000; + font-weight: bold; +} + +/* line 22, ../../app/stylesheets/pygments/colorful.scss */ +.gd { + color: #a00000; +} + +/* line 24, ../../app/stylesheets/pygments/colorful.scss */ +.ge { + font-style: italic; +} + +/* line 26, ../../app/stylesheets/pygments/colorful.scss */ +.gr { + color: #ff0000; +} + +/* line 28, ../../app/stylesheets/pygments/colorful.scss */ +.gh { + color: #000080; + font-weight: bold; +} + +/* line 31, ../../app/stylesheets/pygments/colorful.scss */ +.gi { + color: #00a000; +} + +/* line 33, ../../app/stylesheets/pygments/colorful.scss */ +.go { + color: #808080; +} + +/* line 35, ../../app/stylesheets/pygments/colorful.scss */ +.gp { + color: #c65d09; + font-weight: bold; +} + +/* line 38, ../../app/stylesheets/pygments/colorful.scss */ +.gs { + font-weight: bold; +} + +/* line 40, ../../app/stylesheets/pygments/colorful.scss */ +.gu { + color: #800080; + font-weight: bold; +} + +/* line 43, ../../app/stylesheets/pygments/colorful.scss */ +.gt { + color: #0040d0; +} + +/* line 45, ../../app/stylesheets/pygments/colorful.scss */ +.kc, +.kd, +.kn { + color: #008000; + font-weight: bold; +} + +/* line 48, ../../app/stylesheets/pygments/colorful.scss */ +.kp { + color: #003080; + font-weight: bold; +} + +/* line 51, ../../app/stylesheets/pygments/colorful.scss */ +.kr { + color: #008000; + font-weight: bold; +} + +/* line 54, ../../app/stylesheets/pygments/colorful.scss */ +.kt { + color: #303090; + font-weight: bold; +} + +/* line 57, ../../app/stylesheets/pygments/colorful.scss */ +.m { + color: #6000e0; + font-weight: bold; +} + +/* line 60, ../../app/stylesheets/pygments/colorful.scss */ +.s { + background-color: #fff0f0; +} + +/* line 62, ../../app/stylesheets/pygments/colorful.scss */ +.na { + color: #0000c0; +} + +/* line 64, ../../app/stylesheets/pygments/colorful.scss */ +.nb { + color: #007020; +} + +/* line 66, ../../app/stylesheets/pygments/colorful.scss */ +.nc { + color: #b00060; + font-weight: bold; +} + +/* line 69, ../../app/stylesheets/pygments/colorful.scss */ +.no { + color: #003060; + font-weight: bold; +} + +/* line 72, ../../app/stylesheets/pygments/colorful.scss */ +.nd { + color: #505050; + font-weight: bold; +} + +/* line 75, ../../app/stylesheets/pygments/colorful.scss */ +.ni { + color: #800000; + font-weight: bold; +} + +/* line 78, ../../app/stylesheets/pygments/colorful.scss */ +.ne { + color: #f00000; + font-weight: bold; +} + +/* line 81, ../../app/stylesheets/pygments/colorful.scss */ +.nf { + color: #0060b0; + font-weight: bold; +} + +/* line 84, ../../app/stylesheets/pygments/colorful.scss */ +.nl { + color: #907000; + font-weight: bold; +} + +/* line 87, ../../app/stylesheets/pygments/colorful.scss */ +.nn { + color: #0e84b5; + font-weight: bold; +} + +/* line 90, ../../app/stylesheets/pygments/colorful.scss */ +.nt { + color: #007000; +} + +/* line 92, ../../app/stylesheets/pygments/colorful.scss */ +.nv { + color: #906030; +} + +/* line 94, ../../app/stylesheets/pygments/colorful.scss */ +.ow { + color: #000000; + font-weight: bold; +} + +/* line 97, ../../app/stylesheets/pygments/colorful.scss */ +.w { + color: #bbbbbb; +} + +/* line 99, ../../app/stylesheets/pygments/colorful.scss */ +.mf { + color: #6000e0; + font-weight: bold; +} + +/* line 102, ../../app/stylesheets/pygments/colorful.scss */ +.mh { + color: #005080; + font-weight: bold; +} + +/* line 105, ../../app/stylesheets/pygments/colorful.scss */ +.mi { + color: #0000d0; + font-weight: bold; +} + +/* line 108, ../../app/stylesheets/pygments/colorful.scss */ +.mo { + color: #4000e0; + font-weight: bold; +} + +/* line 111, ../../app/stylesheets/pygments/colorful.scss */ +.sb { + background-color: #fff0f0; +} + +/* line 113, ../../app/stylesheets/pygments/colorful.scss */ +.sc { + color: #0040d0; +} + +/* line 115, ../../app/stylesheets/pygments/colorful.scss */ +.sd { + color: #d04020; +} + +/* line 117, ../../app/stylesheets/pygments/colorful.scss */ +.s2 { + background-color: #fff0f0; +} + +/* line 119, ../../app/stylesheets/pygments/colorful.scss */ +.se { + color: #606060; + font-weight: bold; + background-color: #fff0f0; +} + +/* line 123, ../../app/stylesheets/pygments/colorful.scss */ +.sh { + background-color: #fff0f0; +} + +/* line 125, ../../app/stylesheets/pygments/colorful.scss */ +.si { + background-color: #e0e0e0; +} + +/* line 127, ../../app/stylesheets/pygments/colorful.scss */ +.sx { + color: #d02000; + background-color: #fff0f0; +} + +/* line 130, ../../app/stylesheets/pygments/colorful.scss */ +.sr { + color: #000000; + background-color: #fff0ff; +} + +/* line 133, ../../app/stylesheets/pygments/colorful.scss */ +.s1 { + background-color: #fff0f0; +} + +/* line 135, ../../app/stylesheets/pygments/colorful.scss */ +.ss { + color: #a06000; +} + +/* line 137, ../../app/stylesheets/pygments/colorful.scss */ +.bp { + color: #007020; +} + +/* line 139, ../../app/stylesheets/pygments/colorful.scss */ +.vc { + color: #306090; +} + +/* line 141, ../../app/stylesheets/pygments/colorful.scss */ +.vg { + color: #d07000; + font-weight: bold; +} + +/* line 144, ../../app/stylesheets/pygments/colorful.scss */ +.vi { + color: #3030b0; +} + +/* line 146, ../../app/stylesheets/pygments/colorful.scss */ +.il { + color: #0000d0; + font-weight: bold; +} + +table#my_comments, +table#my_posts, +table#tracker { + border-collapse: collapse; + border: 2px solid black; +} + +table#my_comments tbody th, +table#my_posts tbody th, +table#tracker tbody th { + background: -moz-linear-gradient(#8090a0, #607080) #607080; + border: 1px solid #405070; + border-bottom: 2px solid black; + font-weight: bold; + color: white; +} + +table#my_comments tbody td, +table#my_posts tbody td, +table#tracker tbody td { + border: 1px solid #405070; + border-bottom-color: #607080; + background: white; +} + +table#my_comments a, +table#my_posts a, +table#tracker a { + color: black; + text-decoration: none; +} + +table#my_comments a:hover, +table#my_posts a:hover, +table#tracker a:hover { + text-decoration: underline; +} + +table#wiki_help { + background: -moz-linear-gradient(#8090a0, #607080) repeat scroll 0 0 #607080; +} + +table#wiki_help tbody tr td:first-child { + background: none; + border: 1px 0 0 1px solid black; + color: white; +} + +table#wiki_help tbody tr td { + background: white; + border-width: 4px 0 1px 0; + border-style: solid; + border-color: #c0c4c8; +} + +.misspelled { + color: inherit; + background-color: inherit; + border-bottom: 1px dashed red; +} +.pot_de_miel { + display: none; +} + +@import "../common/statistics"; diff --git a/test/fixtures/forums.yml b/test/fixtures/forums.yml new file mode 100644 index 000000000..b4b0ccf68 --- /dev/null +++ b/test/fixtures/forums.yml @@ -0,0 +1,9 @@ +one: + title: "Foo bar forum" + cached_slug: "foo-bar-forum" + position: 1 + +two: + title: "Foo bar forum 2" + cached_slug: "foo-bar-forum-2" + position: 2 diff --git a/test/fixtures/friend_sites.yml b/test/fixtures/friend_sites.yml new file mode 100644 index 000000000..4de055f17 --- /dev/null +++ b/test/fixtures/friend_sites.yml @@ -0,0 +1,21 @@ +# == Schema Information +# +# Table name: friend_sites +# +# id :integer(4) not null, primary key +# title :string(255) +# url :string(255) +# position :integer(4) +# + +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + title: MyString + url: MyString + position: 1 + +two: + title: MyString + url: MyString + position: 2 diff --git a/test/fixtures/links.yml b/test/fixtures/links.yml new file mode 100644 index 000000000..e1b7a58f1 --- /dev/null +++ b/test/fixtures/links.yml @@ -0,0 +1,5 @@ +one: + news: news + title: Un joli lien + url: /links + lang: fr diff --git a/test/fixtures/news.yml b/test/fixtures/news.yml new file mode 100644 index 000000000..0a0d807d9 --- /dev/null +++ b/test/fixtures/news.yml @@ -0,0 +1,39 @@ +news: + section: news + state: published + title: "The Lord of the Rings: The Fellowship of the Ring" + cached_slug: the-lord-of-the-rings-the-fellowship-of-the-ring + author_name: J.R.R. Tolkien + author_email: test@exemple.com + body: Une jolie nouvelle + second_part: En deuxième partie + moderator: moderator_1 + +draft: + section: news + state: draft + title: Une jolie actualité en cours d'écriture + cached_slug: une-jolie-actualite-en-cours-decriture + author_name: Auteur sympa + author_email: test@exemple.com + body: Nouvelle en brouillon + second_part: En deuxième partie + +candidate: + section: news + state: candidate + title: Une actualité en cours de soumission + cached_slug: une-actualite-en-cours-de-soumission + author_name: Auteur sympa + author_email: test@exemple.com + body: Nouvelle en soumission + second_part: En deuxième partie + +first_part_only: + section: news + state: draft + title: Une actualité avec une seule partie + cached_slug: une-actualite-avec-une-seule-partie + author_name: Auteur sympa + author_email: test@exemple.com + body: Uns seule partie diff --git a/test/fixtures/news_notifications/accept b/test/fixtures/news_notifications/accept new file mode 100644 index 000000000..8196add6a --- /dev/null +++ b/test/fixtures/news_notifications/accept @@ -0,0 +1,3 @@ +NewsNotifications#accept + +Find me in app/views/news_notifications/accept.erb diff --git a/test/fixtures/news_notifications/refuse b/test/fixtures/news_notifications/refuse new file mode 100644 index 000000000..891ac91ab --- /dev/null +++ b/test/fixtures/news_notifications/refuse @@ -0,0 +1,3 @@ +NewsNotifications#refuse + +Find me in app/views/news_notifications/refuse.erb diff --git a/test/fixtures/nodes.yml b/test/fixtures/nodes.yml index 75c7dbbc6..9085774bc 100644 --- a/test/fixtures/nodes.yml +++ b/test/fixtures/nodes.yml @@ -1,11 +1,108 @@ -diary_lorem_cc_licensed: +one: + user: visitor_1 + cc_licensed: true + content: one + content_type: Diary + created_at: <%= Time.now %> + +old: + user: visitor_1 cc_licensed: true + content: old + content_type: Diary + created_at: <%= 4.months.ago %> + +diary_lorem_cc_licensed: user: visitor_1 + cc_licensed: true content: lorem_cc_licensed - content_type: Journal + content_type: Diary diary_lorem_copyright: - cc_licensed: false user: visitor_2 + cc_licensed: false content: lorem_copyright - content_type: Journal + content_type: Diary + +tracker_one: + user: visitor_1 + cc_licensed: true + content: one + content_type: Tracker + +tracker_two: + user: visitor_1 + cc_licensed: true + content: two + content_type: Tracker + +forum: + user: visitor_1 + cc_licensed: true + content: one + content_type: Forum + +news: + user: moderator_1 + cc_licensed: true + content: news + content_type: News + +draft: + user: moderator_1 + cc_licensed: true + content: draft + content_type: News + +candidate: + user: moderator_1 + cc_licensed: true + content: candidate + content_type: News + +first_part_only: + user: moderator_1 + cc_licensed: true + content: first_part_only + content_type: News + +poll: + user: moderator_1 + cc_licensed: true + content: one + content_type: Poll + +poll_draft: + user: moderator_1 + cc_licensed: true + content: draft + content_type: Poll + +poll_collectif: + user: community + cc_licensed: true + content: collectif + content_type: Poll + +post: + user: moderator_1 + cc_licensed: true + content: one + content_type: Post + +wiki: + user: moderator_1 + cc_licensed: true + content: one + content_type: WikiPage + +homePage: + user: moderator_1 + cc_licensed: true + content: homePage + content_type: WikiPage + +bookmark: + user: visitor_0 + content: one + content_type: Bookmark diff --git a/test/fixtures/oauth_applications.yml b/test/fixtures/oauth_applications.yml new file mode 100644 index 000000000..0072c0a0b --- /dev/null +++ b/test/fixtures/oauth_applications.yml @@ -0,0 +1,8 @@ +one: + owner_id: 0 + owner_type: User + name: Test + uid: 12345 + secret: 12345 + redirect_uri: https://localhost:8080 + scopes: [read, write] diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml new file mode 100644 index 000000000..b013189c2 --- /dev/null +++ b/test/fixtures/pages.yml @@ -0,0 +1,19 @@ +one: + title: Une jolie page + slug: jolie-page + body: Joe contenu de page + +equipe: + title: Notre équipe + slug: equipe + body: Le contenu de l'équipe + +amis: + title: Nos amis + slug: amis + body: Le contenu des amis + +moderation: + title: Règles de modération + slug: moderations + body: Le contenu des règles de modération diff --git a/test/fixtures/paragraphs.yml b/test/fixtures/paragraphs.yml new file mode 100644 index 000000000..1a880c4eb --- /dev/null +++ b/test/fixtures/paragraphs.yml @@ -0,0 +1,26 @@ +# == Schema Information +# +# Table name: paragraphs +# +# id :integer(4) not null, primary key +# news_id :integer(4) not null +# position :integer(4) +# second_part :boolean(1) +# locked_by :integer(4) +# body :text +# wiki_body :text +# + +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + news: news + position: 1 + second_part: false + body: MyText + +two: + news: news + position: 1 + second_part: false + body: MyText diff --git a/test/fixtures/poll_answers.yml b/test/fixtures/poll_answers.yml new file mode 100644 index 000000000..617851f7e --- /dev/null +++ b/test/fixtures/poll_answers.yml @@ -0,0 +1,4 @@ +one: + poll: one + answer: et hop + position: 0 diff --git a/test/fixtures/polls.yml b/test/fixtures/polls.yml new file mode 100644 index 000000000..896b02695 --- /dev/null +++ b/test/fixtures/polls.yml @@ -0,0 +1,14 @@ +one: + state: published + title: Un joli sondage + cached_slug: un-joli-sondage + +draft: + state: draft + title: Un sondage en cours d'édition + cached_slug: un-sondage-en-cours-dedition + +collectif: + state: published + title: collectif + cached_slug: collectif diff --git a/test/fixtures/posts.yml b/test/fixtures/posts.yml new file mode 100644 index 000000000..eb65ffd89 --- /dev/null +++ b/test/fixtures/posts.yml @@ -0,0 +1,4 @@ +one: + forum: one + title: Joli post de forum + cached_slug: joli-post-de-forum diff --git a/test/fixtures/responses.yml b/test/fixtures/responses.yml new file mode 100644 index 000000000..2957fad22 --- /dev/null +++ b/test/fixtures/responses.yml @@ -0,0 +1,18 @@ +# == Schema Information +# +# Table name: responses +# +# id :integer(4) not null, primary key +# title :string(255) not null +# content :text +# + +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + title: MyString + content: MyText + +two: + title: MyString + content: MyText diff --git a/test/fixtures/sections.yml b/test/fixtures/sections.yml index 648dfd57f..26e35612d 100644 --- a/test/fixtures/sections.yml +++ b/test/fixtures/sections.yml @@ -1,3 +1,7 @@ default: title: LinuxFr.org cached_slug: linuxfr-org + +news: + title: News + cached_slug: news diff --git a/test/fixtures/taggings.yml b/test/fixtures/taggings.yml new file mode 100644 index 000000000..6a31f6f70 --- /dev/null +++ b/test/fixtures/taggings.yml @@ -0,0 +1,4 @@ +one: + tag: one + node: one + user: visitor_0 diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml new file mode 100644 index 000000000..472860afd --- /dev/null +++ b/test/fixtures/tags.yml @@ -0,0 +1,3 @@ +one: + name: test + taggings_count: 1 diff --git a/test/fixtures/trackers.yml b/test/fixtures/trackers.yml new file mode 100644 index 000000000..e79ec5831 --- /dev/null +++ b/test/fixtures/trackers.yml @@ -0,0 +1,11 @@ +one: + category: one + title: A nice tracker title + wiki_body: A nice tracker description + cached_slug: tracker_one + +two: + category: one + title: Another nice tracker title + wiki_body: Another nice tracker description + cached_slug: tracker_two diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index ef517563f..48bf15b30 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -40,3 +40,10 @@ admin_<%= n%>: name: <%= "admin_#{n}" %> cached_slug: <%= "admin_#{n}" %> <% end %> + +joe: + name: Joe + cached_slug: joe +bob: + name: Bob + cached_slug: bob diff --git a/test/fixtures/wiki_pages.yml b/test/fixtures/wiki_pages.yml new file mode 100644 index 000000000..e7a045a2b --- /dev/null +++ b/test/fixtures/wiki_pages.yml @@ -0,0 +1,7 @@ +one: + title: The Lord of the Rings + cached_slug: the-lord-of-the-rings + +homePage: + title: LinuxFr.org + cached_slug: home-page diff --git a/test/fixtures/wiki_versions.yml b/test/fixtures/wiki_versions.yml new file mode 100644 index 000000000..a4b9ec134 --- /dev/null +++ b/test/fixtures/wiki_versions.yml @@ -0,0 +1,26 @@ +# == Schema Information +# +# Table name: wiki_versions +# +# id :integer(4) not null, primary key +# wiki_page_id :integer(4) +# user_id :integer(4) +# version :integer(4) +# message :string(255) +# body :text +# created_at :datetime +# + +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + wiki_page: one + version: 1 + message: MyString + body: MyText + +two: + wiki_page: one + version: 1 + message: MyString + body: MyText diff --git a/test/helpers/account_helper_test.rb b/test/helpers/account_helper_test.rb new file mode 100644 index 000000000..eb01bf3e1 --- /dev/null +++ b/test/helpers/account_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class AccountHelperTest < ActionView::TestCase +end diff --git a/test/helpers/account_session_helper_test.rb b/test/helpers/account_session_helper_test.rb new file mode 100644 index 000000000..ec45e21c4 --- /dev/null +++ b/test/helpers/account_session_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class AccountSessionHelperTest < ActionView::TestCase +end diff --git a/test/helpers/admin/accounts_helper_test.rb b/test/helpers/admin/accounts_helper_test.rb new file mode 100644 index 000000000..cfac5d3e7 --- /dev/null +++ b/test/helpers/admin/accounts_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class Admin::AccountsHelperTest < ActionView::TestCase +end diff --git a/test/helpers/admin/banners_helper_test.rb b/test/helpers/admin/banners_helper_test.rb new file mode 100644 index 000000000..01c89668b --- /dev/null +++ b/test/helpers/admin/banners_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class Admin::BannersHelperTest < ActionView::TestCase +end diff --git a/test/helpers/admin/forums_helper_test.rb b/test/helpers/admin/forums_helper_test.rb new file mode 100644 index 000000000..07d68dd9b --- /dev/null +++ b/test/helpers/admin/forums_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class Admin::ForumsHelperTest < ActionView::TestCase +end diff --git a/test/helpers/admin/logos_helper_test.rb b/test/helpers/admin/logos_helper_test.rb new file mode 100644 index 000000000..94cb4ad63 --- /dev/null +++ b/test/helpers/admin/logos_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class Admin::LogosHelperTest < ActionView::TestCase +end diff --git a/test/helpers/admin/responses_helper_test.rb b/test/helpers/admin/responses_helper_test.rb new file mode 100644 index 000000000..f3e798da6 --- /dev/null +++ b/test/helpers/admin/responses_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class Admin::ResponsesHelperTest < ActionView::TestCase +end diff --git a/test/helpers/admin/sections_helper_test.rb b/test/helpers/admin/sections_helper_test.rb new file mode 100644 index 000000000..84de0dda2 --- /dev/null +++ b/test/helpers/admin/sections_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class Admin::SectionsHelperTest < ActionView::TestCase +end diff --git a/test/helpers/boards_helper_test.rb b/test/helpers/boards_helper_test.rb new file mode 100644 index 000000000..283b2671b --- /dev/null +++ b/test/helpers/boards_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class BoardsHelperTest < ActionView::TestCase +end diff --git a/test/helpers/comments_helper_test.rb b/test/helpers/comments_helper_test.rb new file mode 100644 index 000000000..b623af28d --- /dev/null +++ b/test/helpers/comments_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class CommentsHelperTest < ActionView::TestCase +end diff --git a/test/helpers/dashboard_helper_test.rb b/test/helpers/dashboard_helper_test.rb new file mode 100644 index 000000000..f8ef9aeca --- /dev/null +++ b/test/helpers/dashboard_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class DashboardHelperTest < ActionView::TestCase +end diff --git a/test/helpers/diaries_helper_test.rb b/test/helpers/diaries_helper_test.rb new file mode 100644 index 000000000..ffdac8460 --- /dev/null +++ b/test/helpers/diaries_helper_test.rb @@ -0,0 +1,4 @@ +require "test_helper" + +class DiariesHelperTest < ActionView::TestCase +end diff --git a/test/helpers/form_helper_test.rb b/test/helpers/form_helper_test.rb new file mode 100644 index 000000000..22898119d --- /dev/null +++ b/test/helpers/form_helper_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class FormHelperTest < ActionView::TestCase + test "should display errors" do + news = News.new + news.valid? + + assert_match(/