diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..fde1b09 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,80 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + test_stable: + runs-on: ubuntu-latest + strategy: + matrix: + firefox: [ '73.0' ] + include: + - nim-version: 'stable' + cache-key: 'stable' + steps: + - uses: actions/checkout@v2 + - name: Checkout submodules + run: git submodule update --init --recursive + + - name: Setup firefox + uses: browser-actions/setup-firefox@latest + with: + firefox-version: ${{ matrix.firefox }} + + - name: Get Date + id: get-date + run: echo "::set-output name=date::$(date "+%Y-%m-%d")" + shell: bash + + - name: Cache choosenim + uses: actions/cache@v2 + with: + path: ~/.choosenim + key: ${{ runner.os }}-choosenim-${{ matrix.cache-key }} + + - name: Cache nimble + uses: actions/cache@v2 + with: + path: ~/.nimble + key: ${{ runner.os }}-nimble-${{ hashFiles('*.nimble') }} + + - uses: jiro4989/setup-nim-action@v1 + with: + nim-version: "${{ matrix.nim-version }}" + + - name: Install geckodriver + run: | + sudo apt-get -qq update + sudo apt-get install autoconf libtool libsass-dev + + wget https://github.com/mozilla/geckodriver/releases/download/v0.29.1/geckodriver-v0.29.1-linux64.tar.gz + mkdir geckodriver + tar -xzf geckodriver-v0.29.1-linux64.tar.gz -C geckodriver + export PATH=$PATH:$PWD/geckodriver + + - name: Install choosenim + run: | + export CHOOSENIM_CHOOSE_VERSION="stable" + curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh + sh init.sh -y + export PATH=$HOME/.nimble/bin:$PATH + nimble refresh -y + + - name: Run tests + run: | + export MOZ_HEADLESS=1 + nimble -y install + nimble -y test + diff --git a/.gitignore b/.gitignore index 83421ca..fe26a8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # Wildcard patterns. *.swp nimcache/ -*.db +*.db* # Specific paths /createdb @@ -12,3 +12,12 @@ nimcache/ forum createdb editdb + +.vscode +forum.json* +browsertester +setup_nimforum +buildcss +nimforum.css + +/src/frontend/forum.js diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b80127e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -os: - - linux - -language: c - -cache: - directories: - - "$HOME/.nimble" - - "$HOME/.choosenim" - -addons: - firefox: "60.0.1" - -before_install: - - sudo apt-get -qq update - - sudo apt-get install autoconf libtool - - git clone -b 3.5.4 https://github.com/sass/libsass.git - - cd libsass - - autoreconf --force --install - - | - ./configure \ - --disable-tests \ - --disable-static \ - --enable-shared \ - --prefix=/usr - - sudo make -j5 install - - cd .. - - - wget https://github.com/mozilla/geckodriver/releases/download/v0.20.1/geckodriver-v0.20.1-linux64.tar.gz - - mkdir geckodriver - - tar -xzf geckodriver-v0.20.1-linux64.tar.gz -C geckodriver - - export PATH=$PATH:$PWD/geckodriver - -install: - - export CHOOSENIM_CHOOSE_VERSION="#987bf13" - - | - curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh - sh init.sh -y - - export PATH=$HOME/.nimble/bin:$PATH - - nimble refresh -y - -script: - - export MOZ_HEADLESS=1 - - nimble -y test \ No newline at end of file diff --git a/README.md b/README.md index b0ee351..d7dedb4 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,131 @@ # nimforum -This is Nim's forum. Available at http://forum.nim-lang.org. +NimForum is a light-weight forum implementation +with many similarities to Discourse. It is implemented in +the [Nim](https://nim-lang.org) programming +language and uses SQLite for its database. -## Building +## Examples in the wild -You can use ``nimble`` (available [here](https://github.com/nim-lang/nimble)) -to get all the necessary -[dependencies](https://github.com/nim-lang/nimforum/blob/master/nimforum.nimble#L11). +[](https://forum.nim-lang.org) -Clone this repo and execute ``nimble build`` in this repositories directory. +
-See also: Running the forum for how to create the database. +## Features + +* Efficient, type safe and clean **single-page application** developed using the + [Karax](https://github.com/pragmagic/karax) and + [Jester](https://github.com/dom96/jester) frameworks. +* **Utilizes SQLite** making set up much easier. +* Endlessly **customizable** using SASS. +* Spam blocking via new user sandboxing with great tools for moderators. +* reStructuredText enriched by Markdown to make formatting your posts a breeze. +* Search powered by SQLite's full-text search. +* Context-aware replies. +* Last visit tracking. +* Gravatar support. +* And much more! + +## Setup + +[See this document.](https://github.com/nim-lang/nimforum/blob/master/setup.md) ## Dependencies -The code depends on the RST parser of the Nim compiler and on Jester. -The captchas for registration uses the [reCaptcha module](https://github.com/euantorano/recaptcha.nim). +The following lists the dependencies which you may need to install manually +in order to get NimForum running, compiled*, or tested†. -#### bcrypt +* libsass +* SQLite +* pcre +* Nim (and the Nimble package manager)* +* [geckodriver](https://github.com/mozilla/geckodriver)† + * Firefox† -On macosx you also need to make sure to use the bcrypt >= 0.2.1 module if that -is not yet updated you can install it with: +[*] Build time dependencies + +[†] Test time dependencies + +## Development + +Check out the tasks defined by this project's ``nimforum.nimble`` file by +running ``nimble tasks``, as of writing they are: ``` -nimble install https://github.com/oderwat/bcryptnim.git@#fix-osx +backend Compiles and runs the forum backend +runbackend Runs the forum backend +frontend Builds the necessary JS frontend (with CSS) +minify Minifies the JS using Google's closure compiler +testdb Creates a test DB (with admin account!) +devdb Creates a test DB (with admin account!) +blankdb Creates a blank DB +test Runs tester +fasttest Runs tester without recompiling backend ``` -You may also need to change `nimforum.nimble` such that it uses 0.2.1 by -changing the dependencies slightly. +To get up and running: -``` -[Deps] -Requires: "nim >= 0.14.0, jester#head, bcrypt >= 0.2.1, recaptcha >= 1.0.0" +```bash +git clone https://github.com/nim-lang/nimforum +cd nimforum +git submodule update --init --recursive + +# Setup the db with user: admin, pass: admin and some other users +nimble devdb + +# Run this again if frontend code changes +nimble frontend + +# Will start a server at localhost:5000 +nimble backend ``` -# Running the forum +Development typically involves running `nimble devdb` which sets up the +database for development and testing, then `nimble backend` +which compiles and runs the forum's backend, and `nimble frontend` +separately to build the frontend. When making changes to the frontend it +should be enough to simply run `nimble frontend` again to rebuild. This command +will also build the SASS ``nimforum.scss`` file in the `public/css` directory. -**Important: You need to compile and run `createdb` to generate the initial database -before you can run `forum` the first time**! +### With docker -**Note: If you do not have a mail server set up locally, you can specify -``-d:dev`` during compilation to prevent nimforum from attempting to send -emails and to automatically activate user accounts** +You can easily launch site on localhost if you have `docker` and `docker-compose`. +You don't have to setup dependencies (libsass, sglite, pcre, etc...) on you host PC. -This is as simple as: +To get up and running: -``` -nim c -r createdb +```bash +cd docker +docker-compose build +docker-compose up ``` -After that you can just run `forum` and if everything is ok you will get the info which URL you need to open in your browser (http://localhost:5000) to access it. +And you can access local NimForum site. +Open http://localhost:5000 . -_There is an update helper `editdb` which you can safely ignore for now._ +# Troubleshooting -_The file `cache.nim` is included by `forum.nim` and do -not need to be compiled by you._ +You might have to run `nimble install karax@#5f21dcd`, if setup fails +with: + +``` +andinus@circinus ~/projects/forks/nimforum> nimble --verbose devdb +[...] + Installing karax@#5f21dcd + Tip: 24 messages have been suppressed, use --verbose to show them. + Error: No binaries built, did you specify a valid binary name? +[...] + Error: Exception raised during nimble script execution +``` + +The hash needs to be replaced with the one specified in output. # Copyright -Copyright (c) 2012-2017 Andreas Rumpf, Dominik Picheta. +Copyright (c) 2012-2018 Andreas Rumpf, Dominik Picheta. All rights reserved. # License -Nimforum is licensed under the MIT license. +NimForum is licensed under the MIT license. diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..cb3191a --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,14 @@ +FROM nimlang/nim:1.2.6-ubuntu + +RUN apt-get update -yqq \ + && apt-get install -y --no-install-recommends \ + libsass-dev \ + sqlite3 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY . /app + +# install dependencies +RUN nimble install -Y diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..8657235 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3.7" + +services: + forum: + build: + context: ../ + dockerfile: ./docker/Dockerfile + volumes: + - "../:/app" + ports: + - "5000:5000" + entrypoint: "/app/docker/entrypoint.sh" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000..d8f5923 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set -eu + +git submodule update --init --recursive + +# setup +nimble c -d:release src/setup_nimforum.nim +./src/setup_nimforum --dev + +# build frontend +nimble c -r src/buildcss +nimble js -d:release src/frontend/forum.nim +mkdir -p public/js +cp src/frontend/forum.js public/js/forum.js + +# build backend +nimble c src/forum.nim +./src/forum diff --git a/forum.json.example b/forum.json.example deleted file mode 100644 index 8cf9e86..0000000 --- a/forum.json.example +++ /dev/null @@ -1,4 +0,0 @@ -{ - "recaptchaSecretKey": "", - "recaptchaSiteKey": "" -} \ No newline at end of file diff --git a/license.txt b/license.txt index cf4ac4a..3eb168b 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright (C) 2015 Andreas Rumpf, Dominik Picheta +Copyright (C) 2018 Andreas Rumpf, Dominik Picheta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -7,7 +7,7 @@ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR diff --git a/localhost.local/public/css/custom-style.scss b/localhost.local/public/css/custom-style.scss index f866829..6c9e50c 100644 --- a/localhost.local/public/css/custom-style.scss +++ b/localhost.local/public/css/custom-style.scss @@ -9,4 +9,8 @@ $secondary-btn-color: #f1f1f1; $body-bg: #ffffff; $navbar-color: $body-bg; $navbar-border-color-dark: $body-bg; -$navbar-primary-color: #e80080; \ No newline at end of file +$navbar-primary-color: #e80080; + +#main-navbar input#search-box { + border: 1px solid #e6e6e6; +} \ No newline at end of file diff --git a/nimforum.nimble b/nimforum.nimble index a24424e..58a22f7 100644 --- a/nimforum.nimble +++ b/nimforum.nimble @@ -1,5 +1,5 @@ # Package -version = "0.1.0" +version = "2.1.0" author = "Dominik Picheta" description = "The Nim forum" license = "MIT" @@ -12,16 +12,16 @@ skipExt = @["nim"] # Dependencies -requires "nim >= 0.14.0" -requires "jester#64295c8" -requires "bcrypt#head" +requires "nim >= 1.0.6" +requires "jester#405be2e" +requires "bcrypt#440c5676ff6" requires "hmac#9c61ebe2fd134cf97" -requires "recaptcha 1.0.2" -requires "sass" +requires "recaptcha#d06488e" +requires "sass#649e0701fa5c" -requires "https://github.com/dom96/karax#7a884fb" +requires "karax#5f21dcd" -requires "webdriver#a2be578" +requires "webdriver#429933a" # Tasks @@ -32,26 +32,33 @@ task backend, "Compiles and runs the forum backend": task runbackend, "Runs the forum backend": exec "./src/forum" +task testbackend, "Runs the forum backend in test mode": + exec "nimble c -r -d:skipRateLimitCheck src/forum.nim" + task frontend, "Builds the necessary JS frontend (with CSS)": exec "nimble c -r src/buildcss" exec "nimble js -d:release src/frontend/forum.nim" mkDir "public/js" - cpFile "src/frontend/nimcache/forum.js", "public/js/forum.js" + cpFile "src/frontend/forum.js", "public/js/forum.js" task minify, "Minifies the JS using Google's closure compiler": exec "closure-compiler public/js/forum.js --js_output_file public/js/forum.js.opt" -task testdb, "Creates a test DB": +task testdb, "Creates a test DB (with admin account!)": exec "nimble c src/setup_nimforum" exec "./src/setup_nimforum --test" -task devdb, "Creates a test DB": +task devdb, "Creates a test DB (with admin account!)": exec "nimble c src/setup_nimforum" exec "./src/setup_nimforum --dev" +task blankdb, "Creates a blank DB": + exec "nimble c src/setup_nimforum" + exec "./src/setup_nimforum --blank" + task test, "Runs tester": exec "nimble c -y src/forum.nim" - exec "nimble c -y -r tests/browsertester" + exec "nimble c -y -r -d:actionDelayMs=0 tests/browsertester" task fasttest, "Runs tester without recompiling backend": - exec "nimble c -r tests/browsertester" \ No newline at end of file + exec "nimble c -r -d:actionDelayMs=0 tests/browsertester" diff --git a/public/css/nimforum.scss b/public/css/nimforum.scss index ad1d712..2daecdb 100644 --- a/public/css/nimforum.scss +++ b/public/css/nimforum.scss @@ -22,6 +22,7 @@ table th { // Custom styles. // - Navigation bar. $navbar-height: 60px; +$default-category-color: #a3a3a3; $logo-height: $navbar-height - 20px; .navbar-button { @@ -50,6 +51,7 @@ $logo-height: $navbar-height - 20px; // Unfortunately we must colour the controls in the navbar manually. .search-input { @extend .form-input; + min-width: 120px; border-color: $navbar-border-color-dark; } @@ -107,12 +109,51 @@ $logo-height: $navbar-height - 20px; } } +#category-selection { + .dropdown { + .btn { + margin-right: 0px; + } + } + .plus-btn { + margin-right: 0px; + i { + margin-right: 0px; + } + } +} + +.category-description { + opacity: 0.6; + font-size: small; +} + +.category-status { + font-size: small; + font-weight: bold; + + .topic-count { + margin-left: 5px; + opacity: 0.7; + font-size: small; + } +} + +.category { + white-space: nowrap; +} + #new-thread { .modal-container .modal-body { max-height: none; } - .form-input { + .panel-body { + padding-top: $control-padding-y*2; + padding-bottom: $control-padding-y*2; + } + + .form-input[name='subject'] { margin-bottom: $control-padding-y*2; } @@ -143,6 +184,33 @@ $logo-height: $navbar-height - 20px; } } +.thread-list { + @extend .container; + @extend .grid-xl; +} + +.category-list { + @extend .thread-list; + + + .category-title { + @extend .thread-title; + a, a:hover { + color: lighten($body-font-color, 10%); + text-decoration: none; + } + } + + .category-description { + opacity: 0.6; + } +} + +#categories-list .category { + border-left: 6px solid; + border-left-color: $default-category-color; +} + $super-popular-color: #f86713; $popular-color: darken($super-popular-color, 25%); $threads-meta-color: #545d70; @@ -191,14 +259,12 @@ $threads-meta-color: #545d70; } } -.triangle { - // TODO: Abstract this into a "category" class. +.category-color { width: 0; height: 0; - border-left: 0.3rem solid transparent; - border-right: 0.3rem solid transparent; - border-bottom: 0.6rem solid #98c766; + border: 0.25rem solid $default-category-color; display: inline-block; + margin-right: 5px; } .load-more-separator { @@ -235,6 +301,14 @@ $threads-meta-color: #545d70; } } +.thread-replies, .thread-time, .views-text, .popular-text, .centered-header { + text-align: center; +} + +.thread-users { + text-align: left; +} + .thread-time { color: $threads-meta-color; @@ -248,8 +322,11 @@ $threads-meta-color: #545d70; } -#threads-list tr.banned { - display: none; // TODO: Fix server so that it doesn't send banned threads. +// Hide all the avatars but the first on small screens. +@media screen and (max-width: 600px) { + #threads-list a:not(:first-child) > .avatar { + display: none; + } } .posts, .about { @@ -353,7 +430,7 @@ $threads-meta-color: #545d70; } } -.post-content { +.post-content, .about { img { max-width: 100%; } @@ -483,6 +560,12 @@ blockquote { display: none; } +.post-content { + pre:not(.code) { + overflow: scroll; + } +} + .information { @extend .tile; border-top: 1px solid $border-color; @@ -696,18 +779,3 @@ hr { margin-top: $control-padding-y*2; } } - -// - Hide features that have not been implemented yet. -#main-buttons > section.navbar-section:nth-child(1) { - display: none; -} - -#threads-list.table { - tr > th:nth-child(2), tr > td:nth-child(2) { - display: none; - } -} - -.category, div.flag-button { - display: none; -} \ No newline at end of file diff --git a/public/karax.html b/public/karax.html index e43498e..3f7f41b 100644 --- a/public/karax.html +++ b/public/karax.html @@ -11,12 +11,21 @@ + + + + - + - $scripts