Giter Site home page Giter Site logo

ahushh / monaba Goto Github PK

View Code? Open in Web Editor NEW
86.0 7.0 9.0 34.42 MB

Imageboard engine written in Haskell and powered by Yesod

Home Page: https://haibane.ru

License: MIT License

Haskell 78.72% PHP 0.08% CSS 19.34% Shell 0.49% Dockerfile 1.05% Perl 0.33%
haskell imageboard yesod docker imageboard-engine chan

monaba's Introduction

Monaba

Monaba

Imageboard engine written in Haskell and powered by Yesod. Demo board.

It's a classic web application with the flavour of AJAX and EventSource used to extend UI of good ol' design insipred by Wakaba.

GitLab CI/CD: https://gitlab.com/ahushh/Monaba

Features

  • Main capabilities:

    • Boards groupping by categories
    • Hiding boards from the list
    • Easy Tor configuration
    • Making boards to be accessed through Tor only
    • Feed page and RSS
    • Threads catalog
    • Threads bookmarks
    • Post deletion and editing
    • Post editing history
    • Multiple file attachment
    • File deletion
    • Video, audio and flash support
    • File rating system: SFW, R15, R18, R18G
    • Text formatting based on BBCode
    • Code highlighting and dice support
    • Prooflables as replacement of tripcodes
    • Private messages
    • Online users counter
    • New posts counter displayed for each board
    • Embedded and customizable CAPTCHA
    • Full-text search
    • Internationalization (English, Русский, Português, Brasil)
    • Country flag support
    • Works fine with JavaScript disabled
    • Custom banners at the top of the page
    • Reports system
  • UI enhancements:

    • Posting through AJAX and quick reply
    • Threads hiding
    • Answer map and post previews
    • Expanding of threads and images
    • YouTube, Vimeo, Coub embedding
    • 20+ switchable stylesheets
    • Buttons for searching selected image using several search engines like Google, TinEye, etc.
    • Desktop notifications of new posts
    • Each UI feature can be configured or disabled
  • Administration features:

    • Hellbanning by session
    • Banning by IP
    • Listing and recovering deleted posts
    • OP can moderate his own thread
    • Flexible account system with customizable groups and permissions
    • Ability to stick and lock threads and to put on auto-sage
    • Moving threads between boards
    • Moving posts between threads
    • Modlog which allows to view previous actions done by staff
    • Post search by ID and UID
    • Wordfilter with regex support which can trigger different actions (ban, replace text, hide post, deny posting and so on)
    • Each board can be configured independently and has a lot of options
    • Home and about pages and footer can be filled in with custom HTML

Cons

  • Bad UI/UX design of administration tools

  • Can be slow in some cases

  • Have not been tested much, no unit/integration tests

  • Difficult to contribute: slow building, legacy dependencies, ugly code

  • Not scalable due to sessions which are being stored on disk

  • Not under active development

Known issues

  • Docker Swarm: Monaba gets incorrect anon's IP. Onion detection doesn't work too.

  • Memory leak while building: #14

  • Incorrect pagination of search results

Requirements

  • Unix-like distro supported by Docker

  • Server with 2GB RAM and 2 CPU cores would be fine

  • If you are going to build Monaba from source, you'd better have 16GB RAM and i7 CPU. MacBook Pro 13 2017 without TouchBar has been dying on build.

API docs

https://documenter.getpostman.com/view/5005722/SzRxVpvC?version=latest

Installation guide

Docker & docker-compose Installation

That's official Docker install script for Debian:

cd /usr/local/src && wget -qO- https://get.docker.com/ | sh

Make Docker to work without sudo:

sudo groupadd docker && sudo usermod -aG docker $USER

Then log out and log back in your system.

Run Docker service:

sudo systemctl start docker

And download docker-compose - yeah, just download it:

sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Monaba Installation

Option #1. Plain Docker

Open your CLI and type:

git clone https://github.com/ahushh/Monaba && cd Monaba

Prepare local dependencies by running build script:

./build.sh

The previous command has just created settings.yml file that contains all run configurations. All you want to edit is under CUSTOMIZE section.

Pull Docker images

Log in to github registry to get access to pull Monaba images:

docker login docker.pkg.github.com -u ahushh -p 18ba5e57502213ad4218a61e73d107096e249a85

Once you're ready to go further let's get all docker images by running this command:

docker-compose pull

Or build them by yourself:

docker-compose build

It takes rather long time so be patient.

Run

Start the application:

docker-compose up -d

In production mode Monaba binds 80 port.

Almost there

Now open you browser and visit /admin/setup page and you will be redirected to the login form. Use admin both for login and password to log in the admin panel. Don't forget to change your password on /admin/account page afterwards.

By opnening /admin/setup Monaba creates admin user with default password admin. This method works only once.

Open admin/boards/list/NewBoard/- and create your first board.

Note

The maximum files size is hardcoded, but it can be changed in Foundation.hs before building. Default value is 25 MB. After you made your changes, docker image must be rebuilt:

docker-compose build app

Option #2. Docker Swarm

This is an experimental options and is not recommended to use. Furthermore, it has no reasonable advantages as Monaba is not a stateless server.

Assuming you have a server on haibane.tk with ssh access for user ahushh.

Open terminal on your local machine and follow the instructions.

Create SSH key and add it to our server:

ssh-keygen -f ~/.ssh/monaba

ssh-copy-id -i ~/.ssh/monaba [email protected]

Create docker instance on the server:

docker-machine create --driver generic --generic-ip-address haibane.tk --generic-ssh-user ahushh --generic-ssh-key ~/.ssh/haibane1 --engine-storage-driver=overlay2 monaba

Connect to the server using SSH:

docker-machine ssh monaba

Install docker & docker-compose, clone repository and change dir, run build.sh script:

See the previous sections. 

Initialize Docker Cluster:

docker swarm init

Deploy

This command pulls the latest monaba images from registry and runs everything:

docker stack deploy --compose-file docker-compose.yml monaba

Cheatsheet

Setting up onion service

  1. Install Eschalot

    sudo apt-get install openssl

    git clone https://github.com/ReclaimYourPrivacy/eschalot.git

    cd eschalot && make

  2. Generate a domain name

    ./eschalot -vct4 -p desiredDomainPrefix

Wait until you get a domain name you like. Remove -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- from the key and encode it with base64 using the tool with the same name.

  1. Open env_prod file and uncomment the last three lines, fill in TORGATE_HOSTNAME and TORGATE_PRIVATE_KEY with the domain name and encoded key.

  2. Restart torgate service: docker-compose restart torgate

Update and restart

cd ~/haibane.ru/Monaba

docker-compose pull

docker-compose down

docker-compose up -d

Check the status of all services

docker-compose ps

Check the logs of the selected service

docker-compose logs webserver | less

Contribution

Guide to install development environment

Tested on: Linux Mint 18.2 Sonya / macOS Catalina

Docker version: 18.09 / 19.03

dontremembershouldbethesame / GHC 8.8.2 and stack 2.1.3

It is possible to run Monaba in dev mode through Docker using dev.Dockefile, but it has been a while since I tried that last time

Install stack (Linux):

curl -sSL https://get.haskellstack.org/ | sh

It's the best way to get the latest version. You can use package manager of course.

For macOS:

brew install haskell-stack

Install local deps (Linux):

sudo apt-get update && sudo apt-get -y install \
  php7.0-fpm \
  libav-tools \
  exiftool \
  libpq-dev \
  libmagickwand-dev \
  libmagickcore-dev \
  libgeoip-dev \
  libicu-dev \
  libcrypto++-dev

For non-apt distro you have to look for equivalent version of these packages.

For macOS:

# binary tools used by Monaba
brew install php libav imagemagick
sudo ln -s /usr/local/bin/convert /usr/bin/convert
# You may need to run these commands in order to edit /usr/bin directory
# csrutil disable
# reboot 
# Or just update convertPath to point /usr/local/bin/convert in src/Utils/File.hs during development

# download dmg here https://exiftool.org/

# required for postgresql-libpq
brew install postgres libpq

# set geoipcitypath to the file path in settings.yml
wget https://github.com/ahushh/monaba/releases/download/v2.5.0/GeoIPCity.dat

# required for hs-GeoIP
brew install libpq libgeoip

# required for nano-md5 
brew install openssl 

# required text-icu
brew install icu4c

Go to the project and prepare some local deps:

cd Monaba

./build.sh

Let's install all those Haskell packages...

cd monaba

stack setup

Build Monaba:

stack build

If you gen an error try this:

stack build --extra-lib-dirs=/usr/local/opt/icu4c/lib --extra-include-dirs=/usr/local/opt/icu4c/include --extra-lib-dirs=/usr/local/opt/[email protected]/lib --extra-include-dirs=/usr/local/opt/[email protected]/include

Then we need executable version of yesod which support hot reloading:

stack install yesod-bin

Give all access to file upload directory:

chmod 777 upload

Build captcha executable file (if you are going to use it):

cd captcha && stack setup && stack install && cp ~/.local/bin/PlainCaptcha .. && cd ..

Unarchive GeoIPCity.data file:

gunzip ./GeoIPCity.dat.gz

Run nginx, postgres, sphinx:

docker-compose -f docker-compose.dev.yml up

Load env variables:

source ../monaba_dev_env

Open monaba/config/settings.yml and check all paths are set correctly.

Run:

stack exec yesod devel

And do not forget to update /etc/hosts for your convenience with:

127.0.0.1       monaba.in

monaba's People

Contributors

ahushh avatar hails avatar kernelic avatar stefkin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

monaba's Issues

Docker & Docker Swarm configs are strange and don't work

Good day. It's really cool project with great features, but...

I see some configurations for Docker & Docker Swarm environments, I just tried to run it on my Win10 or MacOS. It doesn't work. I guess you have specific network setup on your dev machine.

  • First of all, why is there strong IP hard-coding: ipv4_address: 172.19.0.6 and so on?

  • For what you are set constraints: [node.role == manager]?

  • Main application is crashed with error on /opt/monaba/Monaba /var/settings.yml and message that settings.yml cannot be parsed as valid yaml file. Btw I checked this file in yaml online validator - it was valid. Also I checked the file inside a docker container, file was in the path /var/settings.yml and contains all configs.

  • Why you set host aliases for containers: search.in and so on? I didn't find the usage of it.

  • What is the reason to use exactly this subnet: subnet: 172.19.0.0/16?

Please, help! :octocat:

UI small fixes bundle

resize textarea fix
add resizable and scrolling code tag
placeholders instead post-block named
rebuild Mayuri
and more

index 13f9ab9..c380877 100644
--- a/Handler/Posting.hs
+++ b/Handler/Posting.hs
@@ -61,13 +61,18 @@ postForm boardVal extra = do
       ratings :: [(Text, Censorship)]
       ratings = map (showText &&& id) [minBound..maxBound]
       fInput lbl = lbl { fsAttrs = [("onchange","handleFiles(this)"),("class","file-input")] }
-   
-  let nameInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgName)] }
-      subjectInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgSubject)] }
-      passwordInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgPassword)] }
-      captchaInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgCaptcha)] }
  ----------------------------------------------------------------------------------------------------------------
-  (nameRes     , nameView    ) <- mopt textField              "" (Just <$> lastName)
-  (subjectRes  , subjectView ) <- mopt textField              "" (Just              <$> lastTitle)
-  (messageRes  , messageView ) <- mopt myMessageField         "" ((Just . Textarea) <$> lastMessage)
-  (passwordRes , passwordView) <- mreq passwordField          "" Nothing
-  (captchaRes  , captchaView ) <- mopt textField              "" Nothing
-  (gobackRes   , gobackView  ) <- mreq (selectFieldList urls) "" (Just $ maybe ToBoard (\x -> read $ unpack x :: GoBackTo) lastGoback)
-  (nameRes     , nameView    ) <- mopt textField      (nameInput     "")  (Just              <$> lastName)
-  (subjectRes  , subjectView ) <- mopt textField      (subjectInput  "")  (Just              <$> lastTitle)
-  (messageRes  , messageView ) <- mopt myMessageField                ""  ((Just . Textarea)  <$> lastMessage)
-  (passwordRes , passwordView) <- mreq passwordField  (passwordInput "")   Nothing
-  (captchaRes  , captchaView ) <- mopt textField      (captchaInput  "")   Nothing
-  (gobackRes   , gobackView  ) <- mreq        (selectFieldList urls) ""   (Just $ maybe ToBoard (\x -> read $ unpack x :: GoBackTo) lastGoback)
  (nobumpRes   , nobumpView  ) <- mopt checkBoxField          "" Nothing
  (fileresults , fileviews   ) <- unzip <$> forM ([1..numberFiles] :: [Int]) (_ -> mopt fileField (fInput "") Nothing)
  (ratingresults, ratingviews) <- unzip <$> forM ([1..numberFiles] :: [Int]) (_ -> mreq (selectFieldList ratings) "" Nothing)
  diff --git a/messages/en.msg b/messages/en.msg
  index fb4000f..4dfc680 100644
  --- a/messages/en.msg
  +++ b/messages/en.msg
  @@ -6,7 +6,7 @@ Name: Name
  Subject: Subject
  SubmitBtn: Submit
  Message: Message
  -Password: Password
  +Password: Type password
  File: File
  Goback: Go back to
  ToThread: thread
  @@ -309,7 +309,7 @@ ApiCount: Number of posts
  ######################################################################################
  #### Captcha
  ######################################################################################
  -Captcha: Captcha
  +Captcha: Type captcha symbols
  ReloadPage: Error. Reload page.
  TypeOnly: Type only 
  ItalicChars: italic characters
  diff --git a/messages/ru.msg b/messages/ru.msg
  index b1285fe..543bb6e 100644
  --- a/messages/ru.msg
  +++ b/messages/ru.msg
  @@ -6,7 +6,7 @@ Name: Имя
  Subject: Тема
  SubmitBtn: Отправить
  Message: Текст
  -Password: Пароль
  +Password: Введите пароль
  File: Файл
  Goback: Перейти к 
  Nobump: Не бампать
  @@ -309,7 +309,7 @@ ApiCount: Количество постов
  ######################################################################################
  #### Captcha
  ######################################################################################
  -Captcha: Капча
  +Captcha: Введите символы с картинки
  ReloadPage: Ошибка. Перезагрузите страницу.
  TypeOnly: Введите только
  ItalicChars: курсивные символы
  diff --git a/static/css/ash.css b/static/css/ash.css
  index 111d503..c892c67 100644
  --- a/static/css/ash.css
  +++ b/static/css/ash.css
  @@ -29,10 +29,6 @@ footer {
   padding: 1em;
  }

-#post-form input, #post-form label, #post-form textarea, #post-form .file-select, #post-form .dropdown {
-    margin-bottom: 3px !important;
  -}
  -
  fieldset {
     border: 1px solid black;
  }
  @@ -119,6 +115,12 @@ textarea:focus {
   padding: 5px;
  }

+pre {
-    background-color: #EEEEEE;
-    border: 1px dashed #DFDFDF;
-    padding: 10px;
  +}
  +
  /\* Header _/
  .file-name {
     font-size: 0.8em;
  @@ -129,14 +131,14 @@ textarea:focus {
   color: #666666;
  }
  /_ Message */
  -.spoiler, .spoiler a {
  +.spoiler, .spoiler a, .spoiler .quote {
   background:#C0C0C0;
   color:transparent;
   transition:all 0.2s ease;
   box-shadow: 1px 1px 0px #999;
  }

-.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+.spoiler:hover, .spoiler a:hover, .spoiler:hover .quote {
     background: none;
     box-shadow: none;
     color:#333333;
@@ -146,10 +148,14 @@ textarea:focus {
     color:#FF6600;
 }

-.quote, .quote .spoiler:hover {
+.quote, #button-quote, .spoiler:hover .quote, .quote .spoiler:hover {
     color: #008000;
 }

+#button-quote:hover {
-    color: #206620;
  +}
  +
  .last-modified {
     font-size: 0.7em;
  }
  diff --git a/static/css/mayuri.css b/static/css/mayuri.css
  index 8b13789..e5c5f2f 100644
  --- a/static/css/mayuri.css
  +++ b/static/css/mayuri.css
  @@ -1 +1,243 @@
  +html, body {
-    font: 15px "Arial", serif;
-    color: #999;
-    background-color: #353535;
  +}

+a {
-    color:#A75353;
  +}
  +
  +a:hover {
-    color:#804040;
  +}
  +
  +footer {
-    text-align:center;
  +}
  +
  +#wrap {
-    overflow: hidden;
-    background-color: #292929;
-    border-bottom: 2px solid #863D3D;
  +}
  +
  +#main {
-    margin: auto 3%;
-    padding:5px 25px;
-    border-right:1px solid #000;
-    border-left: 2px dashed #863D3D;
-    box-shadow: -2px 0px 10px #1A1A1A;
  +}
  +
  +hr {
-    border: 1px #853737;
-    border-style:solid none none;
  +}
  +
  +.current a{
-   background: none!important;
  +}
  +
  +/\* **************************************\* _/
  +/_ **************\* Forms ****************\* _/
  +/_ **************************************\* */
  +.show-plain-form {
-    border-top: 1px solid rgba(10, 10, 10, 0.3);
-    border-bottom: 1px solid rgba(10, 10, 10, 0.3);
-    padding: 1em;
  +}
  +
  +fieldset {
-   border-left: none;
-   border-right: none;
-   border-top: 1px solid rgba(134, 61, 61, 0.67);
-   border-bottom: 1px solid rgba(134, 61, 61, 0.67);
-   
  +}
  +
  +fieldset legend {
-    padding: 3px 5px;
-    background: none;
-    border: 1px dashed rgba(134, 61, 61, 0.67);
  +}
  +
  +input[type="text"],
  +input[type="password"],
  +input[type="date"],
  +input[type="datetime"],
  +input[type="datetime-local"],
  +input[type="month"],
  +input[type="week"],
  +input[type="email"],
  +input[type="number"],
  +input[type="search"],
  +input[type="tel"],
  +input[type="time"],
  +input[type="url"],
  +textarea, .button {
-   box-shadow: 0px 0px 10px #202020;
-   border:1px solid black;
-    background: #212121;
-    color: #CCC;
  +}
  +
  +input[type="text"]:focus,
  +input[type="password"]:focus,
  +input[type="date"]:focus,
  +input[type="datetime"]:focus,
  +input[type="datetime-local"]:focus,
  +input[type="month"]:focus,
  +input[type="week"]:focus,
  +input[type="email"]:focus,
  +input[type="number"]:focus,
  +input[type="search"]:focus,
  +input[type="tel"]:focus,
  +input[type="time"]:focus,
  +input[type="url"]:focus,
  +textarea:focus {
-   box-shadow: 0 1px 4px black;
-   background: #212121;
-   border:1px solid black;
  +}
  +
  +.button {
-    border:1px solid #3a3a3a;
  +}
  +
  +.button:hover {
-    background: #863d3d;
  +}
  +
  +.rules {
-    font-size: 0.7em;
  +}
  +
  +input::-webkit-input-placeholder {
-    color:#4C4C4C ;
  +}
  +
  +input::-moz-placeholder {
-    color:#727272 ;
-   
  +}
  +/\* **************************************\* _/
  +[class^="icon-"], [class_=" icon-"] {
-    background-image: url("/static/img/glyphicons-white.png");
-    opacity: 0.5;
  +}
  +/\* **************************************\* _/
  +/_ **********\* Post and threads *********\* _/
  +/_ **************************************\* */
  +.reply, .post-list .opening, .popup {
-    background: #252525;
-    border: 1px solid #000;
  +}
  +
  +.popup, .highlighted {
-    border:1px dashed #863D3D;
-    box-shadow: 0px 0px 10px #0C0C0C;
  +}
  +
  +.highlighted {
-    background: #1A1A1A;
  +}
  +
  +.thumb, .video-thumb, iframe {
-   box-shadow: 0 1px 4px black;
  +}
  +
  +pre {
-    background-color: rgba(0,0,0,0.1);
-    border: 1px dashed #5c1f1f;
-    padding: 10px;
-    margin: 10px 7px ;
  +}
  +
  +.thread {
-    border-bottom: 2px solid rgba(134, 61, 61, 0.67);
  +}
  +
  +.post-list .hidden-thread {
-    background: none repeat scroll 0% 0% #CFCFCF;
-    border-radius: 3px;
-    border: 1px solid #EEEEEE;
-    padding: 5px;
  +}
  +
  +.post-title {
-    color: #963428;
-    font-size: 1.1em;
-    font-weight: bold;
  +}
  +
  +/\* Header */
  +.file-name {
-    font-size: 0.8em;
  +}
  +
  +.time {
-    font-size: 0.8em;
-    color: #666666;
  +}
  +/\* Message */
  +.spoiler, .spoiler a, .spoiler .quote {
-    background: #000;
-    box-shadow: -2px 1px 2px #1A1A1A;
-    color: transparent;
-    transition:all 0.2s ease;
  +}
  +
  +.spoiler:hover, .spoiler a:hover, .spoiler:hover .quote {
-    background: none;
-    color: #999;
-    box-shadow: none;
  +}
  +
  +.spoiler a:hover {
-    color:#804040;
  +}
  +
  +.quote, #button-quote, .quote .spoiler:hover, .spoiler:hover .quote {
-    color: #51860F;
  +}
  +
  +#button-quote:hover {
-    color: #426E0F;
  +}
  +
  +.last-modified {
-    font-size: 0.7em;
  +}
  +/\* Files */
  +.file-info {
-    display: none;
  +}
  +/\* **************************************\* _/
  +/_ ***************\* Admin ***************\* _/
  +/_ **************************************\* */
  +.admin-navbar {
-    border-right: 1px solid rgba(10, 10, 10, 0.3);
  +}
  +.admin-navbar li:hover {
-    background-color: #CFCFCF;
  +}
  +
  +/\* **************************************\* _/
  +/_ **********\* Popup alerts *************\* _/
  +/_ **************************************\* */
  +.popup-alert, .panel {
-    background: none repeat scroll 0% 0% #2C2C2C;
-    border-radius: 3px;
-    border: 1px dashed #5c1f1f;
-    box-shadow: 2px 4px 25px -4px #1A1A1A;
  +}
  +/\* **************************************\* _/
  +/_ ***********\* Home page ***************\* _/
  +/_ **************************************\* */
  +.board-category {
-    font-weight: bold;
  +}
  +.panel p, #board-title, #main-title h1, #main h2, .pagination a, .top-bar a {
-    color: #a2a2a2!important;
  +}
  diff --git a/templates/default-layout.lucius b/templates/default-layout.lucius
  index 74d7836..9c2eca8 100644
  --- a/templates/default-layout.lucius
  +++ b/templates/default-layout.lucius
  @@ -44,74 +44,78 @@ footer {
   content: "✖";
  }

-input[type="text"],
-input[type="password"],
-input[type="date"],
-input[type="datetime"],
-input[type="datetime-local"],
-input[type="month"],
-input[type="week"],
-input[type="email"],
-input[type="number"],
-input[type="search"],
-input[type="tel"],
-input[type="time"],
-input[type="url"],
-textarea {
-    display: block;
-    font-size: 0.875em;
-    margin: 0 0 1em 0;
-    padding: 0.1em;
-    height: 1.5em;
-    width: 100%;
  -}
  -
  -.prefix,
  -.postfix {
-    font-size: 0.875em;
-    height: 1.5em;
-    line-height: 1.25em;
  -}
  +#edit-form textarea {
-    width: 97%;
  +}
  +
  +/\*    input[type="datetime-local"],              _/
  +/_    input[type="password"],                    _/
  +/_    input[type="datetime"],                    _/
  +/_    input[type="number"],                      _/
  +/_    input[type="search"],                      _/
  +/_    input[type="month"],                       _/
  +/_    input[type="email"],                       _/
  +/_    input[type="week"],                        _/
  +/_    input[type="time"],                        _/
  +/_    input[type="date"],                        _/
  +/_    input[type="text"],                        _/
  +/_    input[type="tel"],                         _/
  +/_    input[type="url"] {                        _/
  +/_        display: block;                        _/
  +/_        font-size: 0.875em;                    _/
  +/_        margin: 0 0 1em 0;                     _/
  +/_        padding: 0.1em;                        _/
  +/_        height: 1.5em;                         _/
  +/_        width: 100%;                           _/
  +/_    }                                          _/
  +/_                                               _/
  +/_    .prefix,                                   _/
  +/_    .postfix {                                 _/
  +/_        font-size: 0.875em;                    _/
  +/_        height: 1.5em;                         _/
  +/_        line-height: 1.25em;                   _/
  +/_    }                                          */
  
  /\* Adjust padding, alignment and radius if pre/post element is a button */
  -.postfix.button {
-    line-height: 1.25em;
  -}
  +/\*    .postfix.button {                          _/
  +/_        line-height: 1.25em;                   _/
  +/_    }                                          _/
  +/_                                               _/
  +/_    .prefix.button {                           _/
  +/_        line-height: 1.25em;                   _/
  +/_    }                                          _/
  +/_                                               _/
  +/_    button, .button {                          _/
  +/_        margin: 0 0 1.25em;                    _/
  +/_        padding-top: 0.75em;                   _/
  +/_        padding-right: 1.5em;                  _/
  +/_        padding-bottom: 0.8125em;              _/
  +/_        padding-left: 1.5em;                   _/
  +/_        font-size: 0.875em;                    _/
  +/_    }                                          _/
  +
  +/_    form.custom .custom.dropdown .current {    _/
  +/_        line-height: 1.225em;                  _/
  +/_        fon-size: 0.875em;                     _/
  +/_    }                                          _/
  +/_                                               _/
  +/_    form.custom .custom.dropdown {             _/
  +/_        height: 1.5em;                         _/
  +/_    }                                          _/
  +
  +/_    form.custom .custom.dropdown .selector {   _/
  +/_        height: 1.5em;                         _/
  +/_    }                                          _/
  +/_                                               _/
  +/_    label.inline {                             _/
  +/_        margin: 0 0 1em;                       _/
  +/_        padding: 0;                            _/
  +/_    }                                          _/
  +/_                                               _/
  +/_    form.custom .custom.checkbox:before {      _/
  +/_        line-height: 1.11;                     _/
  +/_    }                                          */

-.prefix.button {
-    line-height: 1.25em;
  -}
  -
  -button, .button {
-    margin: 0 0 1.25em;
-    padding-top: 0.75em;
-    padding-right: 1.5em;
-    padding-bottom: 0.8125em;
-    padding-left: 1.5em;
-    font-size: 0.875em;
  -}
  -
  -form.custom .custom.dropdown .current {
-    line-height: 1.225em;
-    fon-size: 0.875em;
  -}
  -
  -form.custom .custom.dropdown {
-    height: 1.5em;
  -}
  -
  -form.custom .custom.dropdown .selector {
-    height: 1.5em;
  -}
  -
  -label.inline {
-    margin: 0 0 1em;
-    padding: 0;
  -}
  -
  -form.custom .custom.checkbox:before {
-    line-height: 1.11;
  -}
  /\* ********************************\* _/
  /_ ************\* Icons ************\* _/
  /_ ********************************\* */
  @@ -172,10 +176,6 @@ form.custom .custom.checkbox:before {
   float: right;
  }

-.no-js .icon-hide-thread {
-    display: none;
  -}
  -
  .icon-show-thread {
     float: right;
     background-position: -1037px -77px;
  @@ -186,20 +186,11 @@ form.custom .custom.checkbox:before {
   background-position: -77px -29px;
  }

-.no-js .icon-hide-thread-completely {
-    display: none;
  -}
  -
  .icon-reply {
     background-position: -605px -173px;
  }

-.no-js .icon-reply {
-    display: none;
  -}
  -
  .show-plain-form {
-    display:none;
   text-align: center;
  }

@@ -211,10 +202,6 @@ form.custom .custom.checkbox:before {
     background-position: -77px -77px;
 }

-.no-js .icon-edit-post {
-    display: none;
  -}
  -
  .icon-close {
     background-position: -269px -101px;
  }
  @@ -224,10 +211,6 @@ form.custom .custom.checkbox:before {
   opacity: 0.3;
  }

-.no-js .icon-del-post {
-    display: none;
  -}
  -
  .icon-eye-open {
     background-position: -53px -29px;
     cursor: auto;
  @@ -237,6 +220,17 @@ form.custom .custom.checkbox:before {
   background-position: -629px -77px;
   margin-right: 3px;
  }
  +
  +
  +.no-js .icon-hide-thread-completely,
  +.no-js .icon-hide-thread,
  +.no-js .icon-edit-post,
  +.no-js .icon-del-post,
  +.no-js .icon-reply,
  +.show-plain-form {
-    display: none;
  +}
  +
  /\* **************************************\* _/
  /_ ***************\* Header **************\* _/
  /_ **************************************\* */
  @@ -264,8 +258,11 @@ form.custom .custom.checkbox:before {
  }
  
  .post {
-    padding: 5px;
-    margin: 3px;
-   padding: 9px 12px!important;
  +}
  +
  +.reply {
-   margin-bottom: 6px!important;
  }
  
  .multi-file {
  @@ -285,10 +282,32 @@ form.custom .custom.checkbox:before {
   display: block;
  }

-.censored {
+#captcha, .censored, iframe, pre {
     display: block;
 }

+.video-thumb {
-    cursor: pointer;
  +}
  +
  +.video-container {
-    display: table;
-    background-color: black;
  +}
  +
  +iframe {
-    border: none;
  +}
  +
  +pre {
-    overflow: auto;
-    width: 450px;
-   min-height: 450px;
-    height: 150px;
-    min-height: 150px;
-    resize: both !important;
  +}
  +
  /\* Message */
  .message {
     padding: 8px 10px;
  @@ -349,6 +368,20 @@ form.custom .custom.checkbox:before {
   float: right;
  }

+.delete-container, .thread-bottom {
-   padding-top: 3px;
  +}
  +
  +.delete-container .tiny {
-    margin-left: 8px;
  +}
  +
  +#edit-button, .delete-container .tiny{
-   padding-top: 5px;
-   padding-bottom: 5px;
-   margin-top: 3px;
  +}
  +
  /\* **************************************\* _/
  /_ **********\* Popup alerts *************\* _/
  /_ **************************************\* */
  @@ -378,132 +411,111 @@ form.custom .custom.checkbox:before {
   top: 10px;
  }

-/\* .admin-table { _/
-/_     border-collapse: collapse; _/
-/_     font-size: 0.8em; _/
-/_     margin: 7px; */
## -/\* } */

-/\* .admin-table td, .admin-table th { _/
-/_     border: 1px solid black; _/
-/_     border-collapse: collapse; _/
-/_     padding: 5px; _/
-/_     padding-right: 8px; */
## -/\* } */

-/\* .admin-table input { _/
-/_     width: 100%; */
## -/\* } */
## 
## 

-/\* header { _/
-/_     padding-bottom: 15px; */
## -/\* } */

-/\* .js .mark-to-delete input[type=checkbox] { _/
-/_     display:none; */
## -/\* } */

-/\* #edit-form textarea { _/
-/_     width: 98%; */
## -/\* } */

-/\* #close-edit-form { _/
-/_     float:right; _/
-/_     margin: 3px 5px; */
## -/\* } */

-/\* .last-modified { _/
-/_     font-size: 0.7em; _/
-/_     float:right; */
## -/\* } */

-/\* .hist-date { _/
-/_     margin: 10px; _/
-/_     text-align: center; _/
-/_     font-weight: bold; */
## -/\* } */

-/\* .hist-msg { _/
-/_     word-wrap: break-word; _/
-/_     width: 50%; _/
-/_     margin: 0 auto; */
## -/\* } */

-/\* #edit-history-header { _/
-/_     text-align: center; */
## -/\* } */

-/\* .file-name { _/
-/_     margin: 2px; */
## -/\* } */

-/\* .file-info { _/
-/_     font-style: italic; _/
-/_     margin: 2px; */
## -/\* } */

-/\* iframe { _/
-/_     border: 0px; */
## -/\* } */

-/\* .focused { _/
-/_     text-decoration: underline; */
## -/\* } */

-/\* ul { _/
-/_     list-style-position: inside; _/
-/_     margin: 0; _/
-/_     padding: 0 0 0 15px; */
## -/\* } */
## 

-/\* .expand-post { _/
-/_     padding: 3px 0 0 8px; */
## -/\* } */

-/\* .shrink-post { _/
-/_     padding-left: 8px; */
## -/\* } */

-/\* .expand-post, .shrink-post { _/
-/_     color: #666666; */
## -/\* } */

-/\* .markup-wrapper { _/
-/_     margin:0 auto; _/
-/_     width:90%; _/
-/_     padding: 5px; */
## -/\* } */

-/\* .abbreviated { _/
-/_     max-height: 250px; _/
-/_     overflow:hidden; */
## -/\* } */

-/\* #delete-container { _/
-/_     clear: both; */
## -/\* } */
## 

-/\* #captcha { _/
-/_     display: block; */
## -/\* } */

-/\* .censored { _/
-/_     display: block; */
## -/\* } */

-/\* .no-js .markup-buttons { _/
-/_     visibility: hidden; _/
-/_     height: 0px; */
## -/\* } */

-/\* .video-thumb { _/
-/_     cursor: pointer; */
## -/\* } */

-/\* .thumb { _/
-/_     outline: none; _/
-/_ } _/
+/_    .admin-table {
+/\*        border-collapse: collapse;
+/\*        font-size: 0.8em;
+/\*        margin: 7px;
+/\*    }                       */
-   
  +/\*    .admin-table td, .admin-table th { _/  
  +/_        border: 1px solid black; _/  
  +/_        border-collapse: collapse; _/  
  +/_        padding: 5px; _/  
  +/_        padding-right: 8px; _/  
  +/_    } */  
-   
  +/\*    .admin-table input { _/  
  +/_        width: 100%; _/  
  +/_    } */  
-   
-   
  +/\*    header { _/  
  +/_        padding-bottom: 15px; _/  
  +/_    } */  
-   
  +/\*    .js .mark-to-delete input[type=checkbox] { _/
  +/_        display:none; _/  
  +/_    } */  
-   
  +/\*    #close-edit-form { _/  
  +/_        float:right; _/  
  +/_        margin: 3px 5px; _/  
  +/_    } */  
-   
  +/\*    .last-modified { _/  
  +/_        font-size: 0.7em; _/  
  +/_        float:right; _/  
  +/_    } */  
-   
  +/\*    .hist-date { _/  
  +/_        margin: 10px; _/  
  +/_        text-align: center; _/  
  +/_        font-weight: bold; _/  
  +/_    } */  
-   
  +/\*    .hist-msg { _/  
  +/_        word-wrap: break-word; _/  
  +/_        width: 50%; _/  
  +/_        margin: 0 auto; _/  
  +/_    } */  
-   
  +/\*    #edit-history-header { _/  
  +/_        text-align: center; _/  
  +/_    } */  
-   
  +/\*    .file-name { _/  
  +/_        margin: 2px; _/  
  +/_    } */  
-   
  +/\*    .file-info { _/  
  +/_        font-style: italic; _/  
  +/_        margin: 2px; _/  
  +/_    } */  
-   
  +/\*    .focused { _/  
  +/_        text-decoration: underline; _/  
  +/_    } */  
- +/\*    ul { _/  
  +/_        list-style-position: inside; _/  
  +/_        margin: 0; _/  
  +/_        padding: 0 0 0 15px; _/  
  +/_    }                                         _/
  +
  +
  +/_    .expand-post {                            _/
  +/_        padding: 3px 0 0 8px;                 _/
  +/_    }                                         _/
  +
  +/_    .shrink-post {                            _/
  +/_        padding-left: 8px;                    _/
  +/_    }                                         _/
  +
  +/_    .expand-post, .shrink-post {              _/
  +/_        color: #666666;                       _/
  +/_    }                                         _/
  +
  +/_    .markup-wrapper {                         _/
  +/_        margin:0 auto;                        _/
  +/_        width:90%;                            _/
  +/_        padding: 5px;                         _/
  +/_    }                                         _/
  +
  +/_    .abbreviated {                            _/
  +/_        max-height: 250px;                    _/
  +/_        overflow:hidden;                      _/
  +/_    }                                         _/
  +
  +/_    #delete-container {                       _/
  +/_        clear: both;                          _/
  +/_    }                                         _/
  +
  +
  +/_    .no-js .markup-buttons {                  _/
  +/_        visibility: hidden;                   _/
  +/_        height: 0px;                          _/
  +/_    }                                         _/
  +
  +/_    .thumb {                                  _/
  +/_        outline: none;                        _/
  +/_    }                                         */
  diff --git a/templates/edit-form.hamlet b/templates/edit-form.hamlet
  index 64b4333..de49806 100644
  --- a/templates/edit-form.hamlet
  +++ b/templates/edit-form.hamlet
  @@ -1,60 +1,57 @@
  # {extra}
  
  -<span style=display:none>
  +<span style="display:none">
   ^{fvInput postIdView}
  
  <div .row>
-  <div .columns .large-12 .small-12>
-  <div .columns .large-11 .small-12>
   ^{fvInput messageView}
  -
  -<div .row>
-  <div .columns .large-12 .small-12>  
-    <div .markup-buttons style=display:inline>
-    <div .markup-buttons style="display:inline">
     <ul .inline-list>
       <li>
-         <a id=button-bold-edit>
-         <a id="button-bold-edit">
           <strong>
             _{MsgMarkupBold}
       <li>
-         <a id=button-italic-edit>
-         <a id="button-italic-edit">
           <em>
             _{MsgMarkupItalic}
       <li>
-         <a id=button-underline-edit>
-         <a id="button-underline-edit">
           <u>
             _{MsgMarkupUnderline}
       <li>
-         <a id=button-strike-edit>
-         <a id="button-strike-edit">
           <span style="text-decoration:line-through">
             _{MsgMarkupStrike}
       <li>
-         <a id=button-spoiler-edit>
-         <a id="button-spoiler-edit">
           <span .spoiler>
             _{MsgMarkupSpoiler}
       <li>
-         <a id=button-code-edit>
-         <a id="button-code-edit">
           _{MsgMarkupCode}
       <li>
-         <a id=button-inline-latex-edit>
-         <a id="button-inline-latex-edit">
           _{MsgMarkupInlineLatex}
       <li>
-         <a id=button-latex-edit>
-         <a id="button-latex-edit">
           _{MsgMarkupLatex}
       <li>
-         <a id=button-quote-edit .quote>
-         <a id="button-quote-edit" .quote>
           _{MsgMarkupQuote}
       <li>
-         <span style=display:inline .symbol-counter>
-         <span style="display:inline" .symbol-counter>
  <div .row>
   <div .columns .large-3 .small-6>
     ^{fvInput passwordView}
  <div .columns .large-3 .small-5>
-    <input .button .tiny type=button id=edit-button value=_{MsgEdit}>
-    <input .button .tiny type="button" id="edit-button" value="_{MsgEdit}">
  <div .columns .large-1 .pull-5 .small-1>
-    <a title=_{MsgCloseIcon} onclick="hideEditForm()" #close-edit-form>
-    <a title="_{MsgCloseIcon}" onclick="hideEditForm()" #close-edit-form>
  
  $if elem ShadowEditP permissions
   <div .row>
     <div .columns .large-12 .small-12>
       ^{fvInput shadowView}
-      <label style=display:inline for=#{fvId shadowView}>
-      <label style="display:inline" for="#{fvId shadowView}">
       _{MsgDontSaveHistory}
  diff --git a/templates/post-form.hamlet b/templates/post-form.hamlet
  index ad24c21..d87b29e 100644
  --- a/templates/post-form.hamlet
  +++ b/templates/post-form.hamlet
  @@ -1,79 +1,71 @@
  #{extra}
  <div .row .collapse>
-  <div .large-1 .small-5 .columns>
-    <label .prefix for=#{fvId nameView}>_{MsgName}
  <div .large-3 .small-7 .columns>
   ^{fvInput nameView}
-  <div .large-2 .pull-6 .small-7 .columns .no-bump-block>
-    <label .inline for=#{fvId nobumpView}>
-  <div .large-2 .pull-7 .small-7 .columns .no-bump-block>
-    <label .inline for="#{fvId nobumpView}">
     _{MsgNobump}
     ^{fvInput nobumpView}
  
  <div .row .collapse .subject-block>
-  <div .large-1 .small-5 .columns>
-    <label for=#{fvId subjectView} .prefix>_{MsgSubject}
  <div .large-3 .small-7 .columns>
   ^{fvInput subjectView}
-  <div .large-2 .pull-6 .small-12 .columns>
-    <input type=submit .button .postfix value=_{MsgSubmitBtn}>
-  <div .large-2 .pull-7 .small-12 .columns>
-    <input type="submit" .button .postfix value="_{MsgSubmitBtn}">
  
  <div .row .collapse>
-  <div .large-12 .columns >
-  <div .large-10 .columns >
   ^{fvInput messageView}
   <div .markup-buttons>
     <ul .inline-list>
       <li>
-         <a id=button-bold>
-         <a id="button-bold">
           <strong>
             _{MsgMarkupBold}
       <li>
-         <a id=button-italic>
-         <a id="button-italic">
           <em>
             _{MsgMarkupItalic}
       <li>
-         <a id=button-underline>
-         <a id="button-underline">
           <u>
             _{MsgMarkupUnderline}
       <li>
-         <a id=button-strike>
-         <a id="button-strike">
           <span style="text-decoration:line-through">
             _{MsgMarkupStrike}
       <li>
-         <a id=button-spoiler>
-         <a id="button-spoiler">
           <span .spoiler>
             _{MsgMarkupSpoiler}
       <li>
-         <a id=button-code>
-         <a id="button-code">
           _{MsgMarkupCode}
       <li>
-         <a id=button-inline-latex>
-         <a id="button-inline-latex">
           _{MsgMarkupInlineLatex}
       <li>
-         <a id=button-latex>
-         <a id="button-latex">
           _{MsgMarkupLatex}
       <li>
-         <a id=button-quote .quote>
-         <a id="button-quote .quote">
           _{MsgMarkupQuote}
       <li>
-         <span style=display:inline .symbol-counter>
-         <span style="display:inline" .symbol-counter>
  <div .row .collapse>
-  <div .large-1 .small-5 .columns>
-    <label for=#{fvId passwordView} .prefix>_{MsgPassword}
-  <div .large-3 .pull-8 .small-7 .columns>
-  <div .large-3 .small-7 .columns>
   ^{fvInput passwordView}
  
  $if enableCaptchaW
-  <div .row .collapse>
-    <div .large-1 .small-5 .columns>
-      <label for=#{fvId captchaView} .prefix>_{MsgCaptcha}
-    <div .large-4 .small-7 .columns>
-  <div .row .collapse style="padding-bottom:3px;">
-    <div .large-3 .small-7 .columns>
     $if isJust muserW
         <span .prefix>_{MsgYouDontNeedCaptcha}  
     $else
         $maybe _ <- acaptchaW
             <span .prefix>_{MsgYouDontNeedCaptcha}
-          $nothing
-              ^{fvInput captchaView} 
-          $nothing  
-              <img alt="captcha" #captcha src="@{CaptchaR}">
             <label #captcha-info for="#{fvId captchaView}">
                 $maybe c <- maybeCaptchaInfoW
                     _{MsgTypeOnly} 
  @@ -85,8 +77,7 @@ $if enableCaptchaW
                         _{MsgRegularChars}
                 $nothing
                     _{MsgReloadPage}
-    <div .large-7 .small-12 .columns>  
-      <img alt=captcha #captcha src=@{CaptchaR}>
- ```
           ^{fvInput captchaView}

$if length fileviews > 0
$forall (fv, rv) <- zip fileviews ratingviews
@@ -99,11 +90,11 @@ $if length fileviews > 0
<div .columns .large-1 .small-4 .file-input-size>
<span .postfix>
<div .columns .large-1 .pull-3 .small-4>

  •    <a .clear-file title=_{MsgRemoveFileIcon} onclick="clearFile('#{unpack $ fvId fv}')"></a>
    
  •    <a .clear-file title="_{MsgRemoveFileIcon}" onclick="clearFile('#{unpack $ fvId fv}')"></a>
    
  • <label for=#{fvId gobackView} .prefix>_{MsgGoback}

  • <label for="#{fvId gobackView}" .prefix>_{MsgGoback}

^{fvInput gobackView}

diff --git a/templates/post-form.lucius b/templates/post-form.lucius
index 479f9be..bb3f87a 100644
--- a/templates/post-form.lucius
+++ b/templates/post-form.lucius
@@ -1,7 +1,16 @@
textarea {

  • height: 150px;
  • min-height: 150px;
  • width: 90% !important;
  • width: 97%;
  • height: 200px;
  • min-height: 200px;
  • resize: both !important;
    +}

+#post-form input,
+#post-form label,
+#post-form textarea,
+#post-form .file-select,
+#post-form .dropdown {

  • margin-bottom: 3px;
    }

.clear-file {
@@ -13,36 +22,27 @@ textarea {
content: "✖";
}

-.clear-file, .file-input-size {

  • display: none;
    -}
    -/* .quick-post-form { /
    -/
    text-align: left; /
    -/
    margin: 5px 0 0; /
    -/
    display: table; /
    -/
    width: 95%; /
    -/
    padding: 5px; */

-/* } */

-/* .plain-post-form { /
-/
width: 75%; /
-/
margin: 10px 10%; /
-/
border: 0px; /
-/
padding: 5px; /
-/
} /
+/
.quick-post-form { /
+/
text-align: left; /
+/
margin: 5px 0 0; /
+/
display: table; /
+/
width: 95%; /
+/
padding: 5px; /
+/
} /
+
+/
.plain-post-form { /
+/
width: 75%; /
+/
margin: 10px 10%; /
+/
border: 0px; /
+/
padding: 5px; /
+/
} */

.close-post-form {
text-align: center;
}

-.js .file-input {

  • visibility: none;
  • position: absolute;
  • left: -999999px;
    -}

-.no-js .file-select, .no-js .close-post-form, .no-js .markup-buttons {

  • display: none;
    +.file-select {
  • padding: 9px !important;
    }

.file-input-thumb {
@@ -51,6 +51,23 @@ textarea {
display: block;
}

-.markup-buttons ul {

  • line-height: 1em;
    +.markup-buttons {
  • font-variant: small-caps;
    }

+.subject-block .button {

  • margin-left: 5px;
    +}

+.no-bump-block label {

  • padding-left: 5px;
    +}

+.no-js .close-post-form,
+.no-js .markup-buttons,
+.no-js .file-select,
+.file-input-size,
+.js .file-input,
+.clear-file {

  • display: none;
    +}
    \ No newline at end of file```

Верни RSS

Если в движке ранее был RSS, То верни плез. Думаю это не создаст серьезных проблем, хотя я код не читал. Да и в Хаскеле не шарю, только в хелловорлд могу

whatanime.ga has moved to trace.moe

Hello, I'm (was) the owner of whatanime.ga
A few days ago, the .ga domain was taken down by freenom T_T,
so the site has moved to https://trace.moe
if you are still actively supporting this project, please update the URL, thank you m(_ _;)m

Stylesheets Fix

  • link spoiler fix
  • quote spoiler fix
  • mayuri fix
  • some colors and shapes fixes
 static/css/ash.css              | 41 ++++++++++++++--------
 static/css/futaba.css           | 35 +++++++++++++------
 static/css/mayuri.css           | 77 +++++++++++++++++++++++++----------------
 static/css/nox.css              | 51 ++++++++++++++++++---------
 static/css/postmodern.css       | 44 +++++++++++++++--------
 templates/default-layout.lucius |  4 ---
 6 files changed, 163 insertions(+), 89 deletions(-)

diff --git a/static/css/ash.css b/static/css/ash.css
index 297c0d0..92689a2 100644
--- a/static/css/ash.css
+++ b/static/css/ash.css
@@ -43,8 +43,33 @@ a:hover {
     color: #FF6600;
 }

+.spoiler, .spoiler a {
+    background:#C0C0C0;
+    color:transparent;
+    transition:all 0.2s ease;
+    box-shadow: 1px 1px 0px #999;
+}
+
+.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+    background: none;
+    box-shadow: none;
+    color:#333333;
+}
+
+.spoiler a:hover {
+    color:#FF6600;
+}
+
+.quote, .quote .spoiler:hover {
+    color: #008000;
+}
+
+#button-quote:hover {
+    color: #206620;
+}
+
 header {
-    border-bottom: 1px solid rgba(10, 10, 10, 0.3);    
+    border-bottom: 1px solid rgba(10, 10, 10, 0.3);
 }

 footer {
@@ -203,10 +228,6 @@ pre {
     color: #666666;
 }

-.quote {
-    color: #206620 !important;
-}
-
 #next-page {
     border-right: 1px solid rgba(10, 10, 10, 0.7);
     padding-right: 5px;
@@ -225,13 +246,3 @@ pre {
 .file-info {
     display:none;
 }
-
-.spoiler {
-    background:#adadad;
-    color:#adadad;
-}
-
-.spoiler:hover {
-    background:#adadad;
-    color:#333333;
-}
diff --git a/static/css/futaba.css b/static/css/futaba.css
index dc1041a..1991ee2 100644
--- a/static/css/futaba.css
+++ b/static/css/futaba.css
@@ -41,6 +41,31 @@ a:hover {
     color: #DD0000;
 }

+.spoiler, .spoiler a {
+    background:#E1D1C7;
+    color:transparent;
+    transition:all 0.2s ease;
+    box-shadow: 1px 1px 0px #B1A29D;
+}
+
+.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+    background: none;
+    box-shadow: none;
+    color:#600000;
+}
+
+.spoiler a:hover {
+    color:#DD0000;
+}
+
+.quote, .quote .spoiler:hover {
+    color: #008000;
+}
+
+#button-quote:hover {
+    color: #206620;
+}
+
 header {
     border-bottom: 1px solid rgba(50,50,50,0.5);
 }
@@ -201,13 +226,3 @@ pre {
     background-color: #EEAA88;
     padding: 2px;
 }
-
-.spoiler {
-    background:#f0d0b6;
-    color:#f0d0b6;
-}
-
-.spoiler:hover {
-    background:#f0d0b6;
-    color:#7d0008;
-}
diff --git a/static/css/mayuri.css b/static/css/mayuri.css
index 86097a1..bbc87cb 100644
--- a/static/css/mayuri.css
+++ b/static/css/mayuri.css
@@ -40,24 +40,37 @@ a:hover {
     color:#804040;
 }

+.spoiler, .spoiler a {
+    background: #000;
+    box-shadow: -2px 1px 2px #1A1A1A;
+    color: transparent;
+    transition:all 0.2s ease;
+}
+
+.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+    background: none;
+    color: #999;
+    box-shadow: none;
+}
+
+.spoiler a:hover {
+    color:#804040;
+}
+
+.quote, .quote .spoiler:hover {
+    color: #51860F;
+}
+
+#button-quote:hover {
+    color: #426E0F;
+}
+
 hr {
     border-color:#853737;
     border-style:solid none none none;
     border-width:1px;
 }

-.spoiler {
-   background: #000;
-    box-shadow: -2px 1px 2px #1A1A1A;
-   color: transparent;
-   transition:all 0.2s ease;
-}
-.spoiler:hover {
-   background: none;
-   color: #999;
-    box-shadow: none;
-}
-
 #board-list-full, .popupMessage {
     background: none repeat scroll 0% 0% #2C2C2C;
     border: 1px dashed #5c1f1f;
@@ -71,7 +84,7 @@ hr {
 }

 .reply-post, .popup-post {
-   display: table;
+    display: table;
     overflow: hidden;
     padding: 8px 15px;
     margin-bottom: 6px;
@@ -86,15 +99,20 @@ hr {
     box-shadow: 0px 0px 10px #0C0C0C;
 }

+input, select, textarea, .post-block-named {
+    background:#212121;
+    color:#CCC;
+    border:1px solid #4C4C4C;
+    box-shadow: 0px 0px 10px #202020;
+}
+
 .post-block-named {
     padding: 1px 8px;
     background-color: #2E2E2E;
     border: 1px solid #0C0C0C;
-    box-shadow: 0px 0px 10px #202020;
-    color: #CCC;
 }

-input[type="text"], input[type="password"] {
+input[type="text"], input[type="password"], input[type="number"] {
     height: 20px;
 }

@@ -102,18 +120,7 @@ input[type="checkbox"], input[type="submit"] {
     margin: 3px 3px 3px 4px;
 }

-select, textarea, input[type="text"], input[type="password"], input[type="submit"] {
-    background:#212121;
-    color:#CCC;
-    border:1px solid #4C4C4C;
-    box-shadow: 0px 0px 10px #202020;
-}
-
-input::-webkit-input-placeholder {
-    color:#727272;
-}
-
-input::-moz-placeholder {
+input::-webkit-input-placeholder, input::-moz-placeholder {
     color:#727272;
 }

@@ -131,6 +138,18 @@ input::-moz-placeholder {
     text-align: right;
 }

+pre {
+    background-color: rgba(0,0,0,0.1);
+    border: 1px dashed #5c1f1f;
+    padding: 10px;
+}
+
+.reply-title {
+    color: #963428;
+    font-size: 1em;
+    font-weight: bold;
+}
+
 footer {
     text-align:center;
-}
\ No newline at end of file
+}
diff --git a/static/css/nox.css b/static/css/nox.css
index f705b34..c01c913 100644
--- a/static/css/nox.css
+++ b/static/css/nox.css
@@ -49,8 +49,41 @@ a:hover {
     color: #742307;
 }

+.spoiler, .spoiler a, .quote .spoiler {
+    background: none;
+    color: transparent;
+    text-shadow:0 0 10px #fff;
+    transition:all 0.2s ease;
+}
+
+.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+    color: #7C7C7C;
+    background:none;
+    text-shadow:none;
+}
+
+.spoiler a {
+    text-shadow:0 0 10px #FF8222;
+}
+
+.quote .spoiler {
+    text-shadow:0 0 10px #509550;
+}
+
+.spoiler a:hover {
+    color: #742307;
+}
+
+.quote, .quote .spoiler:hover {
+    color: #105510;
+}
+
+#button-quote:hover {
+    color: #004400;
+}
+
 header {
-    border-bottom: 1px solid rgba(100, 100, 100, 0.3);    
+    border-bottom: 1px solid rgba(100, 100, 100, 0.3);
 }

 footer {
@@ -204,10 +237,6 @@ pre {
     color: #666666;
 }

-.quote {
-    color: #105510 !important;
-}
-
 #next-page {
     border-right: 1px solid rgba(100, 100, 100, 0.7);
     padding-right: 5px;
@@ -238,15 +267,3 @@ pre {
     border-bottom: 2px dashed rgba(100, 100, 100, 0.7) !important;
     border-top: 2px dashed rgba(100, 100, 100, 0.7) !important;
 }
-
-.spoiler {
-    background: none;
-    color: transparent;
-    text-shadow:0 0 10px #fff;
-}
-
-.spoiler:hover {
-    color: #e1e1e1;
-    background:none;
-    text-shadow:none;
-}
diff --git a/static/css/postmodern.css b/static/css/postmodern.css
index b5b7336..cac2d6e 100644
--- a/static/css/postmodern.css
+++ b/static/css/postmodern.css
@@ -19,6 +19,36 @@ a:hover {
     text-decoration: underline;
 }

+.spoiler, .spoiler a, .quote .spoiler {
+    background: none;
+    color: transparent;
+    text-shadow:0 0 10px #72AEFE;
+    transition:all 0.2s ease;
+}
+
+.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+    color: #496CA0;
+    background:none;
+    text-shadow:none;
+}
+
+.spoiler a {
+    text-shadow:0 0 10px #DEBD18;
+}
+
+.quote .spoiler {
+    text-shadow:0 0 10px #8FC68E;
+}
+
+.spoiler a:hover {
+    color: #927908;
+    text-decoration: underline;
+}
+
+.quote, .quote .spoiler:hover {
+    color: #557755;
+}
+
 .container {
     width: 80%;
     margin: auto 10%;
@@ -286,10 +316,6 @@ pre {
     color: #666666;
 }

-.quote {
-    color: #557755 !important;
-}
-
 #next-page {
     border-right: 1px dotted rgba(10, 10, 10, 0.7);
     padding-right: 5px;
@@ -332,13 +358,3 @@ pre {
 #captcha {
     padding: 1px;
 }
-
-.spoiler {
-    background:#454545;
-    color:#454545;
-}
-
-.spoiler:hover {
-    background:#454545;
-    color:#496ca0;
-}
diff --git a/templates/default-layout.lucius b/templates/default-layout.lucius
index 86ce852..cd623b6 100644
--- a/templates/default-layout.lucius
+++ b/templates/default-layout.lucius
@@ -336,10 +336,6 @@ header {
     margin: 2px;
 }

-.quote {
-    color: green;
-}
-
 iframe {
     border: 0px;
 }

Формирование title

В заголовке страницы идут по порядку сначала имя борды, потом раздел, потом имя треда. Если у тебя несколько вкладок тредов, то они из-за обрезанного браузером текста по ширине вкладки будут выглядеть одинаково, и название треда в заголовке теряет смысл. Нужно в обратном порядке.

API

Здравствуйте.
Я просто проходил мимо.
Уютный проект, а что по API?
Я поискал через Ctrl + F, не нашлось.
Если есть чё, то можно было бы прикрутить вот этот GUI:
https://github.com/catamphetamine/chanchan

UI fix

resize textarea fix
add resizable and scrolling code tag
placeholders instead post-block named
rebuild Mayuri
and more

diff --git a/Handler/Posting.hs b/Handler/Posting.hs
index 13f9ab9..c380877 100644
--- a/Handler/Posting.hs
+++ b/Handler/Posting.hs
@@ -61,13 +61,18 @@ postForm boardVal extra = do
       ratings :: [(Text, Censorship)]
       ratings = map (showText &&& id) [minBound..maxBound]
       fInput lbl = lbl { fsAttrs = [("onchange","handleFiles(this)"),("class","file-input")] }
+     
+  let nameInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgName)] }
+      subjectInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgSubject)] }
+      passwordInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgPassword)] }
+      captchaInput lbl = lbl { fsAttrs = [("placeholder",msgrender MsgCaptcha)] }
   ----------------------------------------------------------------------------------------------------------------
-  (nameRes     , nameView    ) <- mopt textField              "" (Just <$> lastName)
-  (subjectRes  , subjectView ) <- mopt textField              "" (Just              <$> lastTitle)
-  (messageRes  , messageView ) <- mopt myMessageField         "" ((Just . Textarea) <$> lastMessage)
-  (passwordRes , passwordView) <- mreq passwordField          "" Nothing
-  (captchaRes  , captchaView ) <- mopt textField              "" Nothing
-  (gobackRes   , gobackView  ) <- mreq (selectFieldList urls) "" (Just $ maybe ToBoard (\x -> read $ unpack x :: GoBackTo) lastGoback)
+  (nameRes     , nameView    ) <- mopt textField      (nameInput     "")  (Just              <$> lastName)
+  (subjectRes  , subjectView ) <- mopt textField      (subjectInput  "")  (Just              <$> lastTitle)
+  (messageRes  , messageView ) <- mopt myMessageField                ""  ((Just . Textarea)  <$> lastMessage)
+  (passwordRes , passwordView) <- mreq passwordField  (passwordInput "")   Nothing
+  (captchaRes  , captchaView ) <- mopt textField      (captchaInput  "")   Nothing
+  (gobackRes   , gobackView  ) <- mreq        (selectFieldList urls) ""   (Just $ maybe ToBoard (\x -> read $ unpack x :: GoBackTo) lastGoback)
   (nobumpRes   , nobumpView  ) <- mopt checkBoxField          "" Nothing
   (fileresults , fileviews   ) <- unzip <$> forM ([1..numberFiles] :: [Int]) (\_ -> mopt fileField (fInput "") Nothing)
   (ratingresults, ratingviews) <- unzip <$> forM ([1..numberFiles] :: [Int]) (\_ -> mreq (selectFieldList ratings) "" Nothing)
diff --git a/messages/en.msg b/messages/en.msg
index fb4000f..4dfc680 100644
--- a/messages/en.msg
+++ b/messages/en.msg
@@ -6,7 +6,7 @@ Name: Name
 Subject: Subject
 SubmitBtn: Submit
 Message: Message
-Password: Password
+Password: Type password
 File: File
 Goback: Go back to
 ToThread: thread
@@ -309,7 +309,7 @@ ApiCount: Number of posts
 ######################################################################################
 #### Captcha
 ######################################################################################
-Captcha: Captcha
+Captcha: Type captcha symbols
 ReloadPage: Error. Reload page.
 TypeOnly: Type only 
 ItalicChars: italic characters
diff --git a/messages/ru.msg b/messages/ru.msg
index b1285fe..543bb6e 100644
--- a/messages/ru.msg
+++ b/messages/ru.msg
@@ -6,7 +6,7 @@ Name: Имя
 Subject: Тема
 SubmitBtn: Отправить
 Message: Текст
-Password: Пароль
+Password: Введите пароль
 File: Файл
 Goback: Перейти к 
 Nobump: Не бампать
@@ -309,7 +309,7 @@ ApiCount: Количество постов
 ######################################################################################
 #### Captcha
 ######################################################################################
-Captcha: Капча
+Captcha: Введите символы с картинки
 ReloadPage: Ошибка. Перезагрузите страницу.
 TypeOnly: Введите только
 ItalicChars: курсивные символы
diff --git a/static/css/ash.css b/static/css/ash.css
index 111d503..c892c67 100644
--- a/static/css/ash.css
+++ b/static/css/ash.css
@@ -29,10 +29,6 @@ footer {
     padding: 1em;
 }

-#post-form input, #post-form label, #post-form textarea, #post-form .file-select, #post-form .dropdown {
-    margin-bottom: 3px !important;
-}
-
 fieldset {
     border: 1px solid black;
 }
@@ -119,6 +115,12 @@ textarea:focus {
     padding: 5px;
 }

+pre {
+    background-color: #EEEEEE;
+    border: 1px dashed #DFDFDF;
+    padding: 10px;
+}
+
 /* Header */
 .file-name {
     font-size: 0.8em;
@@ -129,14 +131,14 @@ textarea:focus {
     color: #666666;
 }
 /* Message */
-.spoiler, .spoiler a {
+.spoiler, .spoiler a, .spoiler .quote {
     background:#C0C0C0;
     color:transparent;
     transition:all 0.2s ease;
     box-shadow: 1px 1px 0px #999;
 }

-.spoiler:hover, .spoiler a:hover, .quote .spoiler:hover {
+.spoiler:hover, .spoiler a:hover, .spoiler:hover .quote {
     background: none;
     box-shadow: none;
     color:#333333;
@@ -146,10 +148,14 @@ textarea:focus {
     color:#FF6600;
 }

-.quote, .quote .spoiler:hover {
+.quote, #button-quote, .spoiler:hover .quote, .quote .spoiler:hover {
     color: #008000;
 }

+#button-quote:hover {
+    color: #206620;
+}
+
 .last-modified {
     font-size: 0.7em;
 }
diff --git a/static/css/mayuri.css b/static/css/mayuri.css
index 8b13789..e5c5f2f 100644
--- a/static/css/mayuri.css
+++ b/static/css/mayuri.css
@@ -1 +1,243 @@
+html, body {
+    font: 15px "Arial", serif;
+    color: #999;
+    background-color: #353535;
+}

+a {
+    color:#A75353;
+}
+
+a:hover {
+    color:#804040;
+}
+
+footer {
+    text-align:center;
+}
+
+#wrap {
+    overflow: hidden;
+    background-color: #292929;
+    border-bottom: 2px solid #863D3D;
+}
+
+#main {
+    margin: auto 3%;
+    padding:5px 25px;
+    border-right:1px solid #000;
+    border-left: 2px dashed #863D3D;
+    box-shadow: -2px 0px 10px #1A1A1A;
+}
+
+hr {
+    border: 1px #853737;
+    border-style:solid none none;
+}
+
+.current a{
+   background: none!important;
+}
+
+/* *************************************** */
+/* *************** Forms ***************** */
+/* *************************************** */
+.show-plain-form {
+    border-top: 1px solid rgba(10, 10, 10, 0.3);
+    border-bottom: 1px solid rgba(10, 10, 10, 0.3);
+    padding: 1em;
+}
+
+fieldset {
+   border-left: none;
+   border-right: none;
+   border-top: 1px solid rgba(134, 61, 61, 0.67);
+   border-bottom: 1px solid rgba(134, 61, 61, 0.67);
+   
+}
+
+fieldset legend {
+    padding: 3px 5px;
+    background: none;
+    border: 1px dashed rgba(134, 61, 61, 0.67);
+}
+
+input[type="text"],
+input[type="password"],
+input[type="date"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="month"],
+input[type="week"],
+input[type="email"],
+input[type="number"],
+input[type="search"],
+input[type="tel"],
+input[type="time"],
+input[type="url"],
+textarea, .button {
+   box-shadow: 0px 0px 10px #202020;
+   border:1px solid black;
+    background: #212121;
+    color: #CCC;
+}
+
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="date"]:focus,
+input[type="datetime"]:focus,
+input[type="datetime-local"]:focus,
+input[type="month"]:focus,
+input[type="week"]:focus,
+input[type="email"]:focus,
+input[type="number"]:focus,
+input[type="search"]:focus,
+input[type="tel"]:focus,
+input[type="time"]:focus,
+input[type="url"]:focus,
+textarea:focus {
+   box-shadow: 0 1px 4px black;
+   background: #212121;
+   border:1px solid black;
+}
+
+.button {
+    border:1px solid #3a3a3a;
+}
+
+.button:hover {
+    background: #863d3d;
+}
+
+.rules {
+    font-size: 0.7em;
+}
+
+input::-webkit-input-placeholder {
+    color:#4C4C4C ;
+}
+
+input::-moz-placeholder {
+    color:#727272 ;
+   
+}
+/* *************************************** */
+[class^="icon-"], [class*=" icon-"] {
+    background-image: url("/static/img/glyphicons-white.png");
+    opacity: 0.5;
+}
+/* *************************************** */
+/* *********** Post and threads ********** */
+/* *************************************** */
+.reply, .post-list .opening, .popup {
+    background: #252525;
+    border: 1px solid #000;
+}
+
+.popup, .highlighted {
+    border:1px dashed #863D3D;
+    box-shadow: 0px 0px 10px #0C0C0C;
+}
+
+.highlighted {
+    background: #1A1A1A;
+}
+
+.thumb, .video-thumb, iframe {
+   box-shadow: 0 1px 4px black;
+}
+
+pre {
+    background-color: rgba(0,0,0,0.1);
+    border: 1px dashed #5c1f1f;
+    padding: 10px;
+    margin: 10px 7px ;
+}
+
+.thread {
+    border-bottom: 2px solid rgba(134, 61, 61, 0.67);
+}
+
+.post-list .hidden-thread {
+    background: none repeat scroll 0% 0% #CFCFCF;
+    border-radius: 3px;
+    border: 1px solid #EEEEEE;
+    padding: 5px;
+}
+
+.post-title {
+    color: #963428;
+    font-size: 1.1em;
+    font-weight: bold;
+}
+
+/* Header */
+.file-name {
+    font-size: 0.8em;
+}
+
+.time {
+    font-size: 0.8em;
+    color: #666666;
+}
+/* Message */
+.spoiler, .spoiler a, .spoiler .quote {
+    background: #000;
+    box-shadow: -2px 1px 2px #1A1A1A;
+    color: transparent;
+    transition:all 0.2s ease;
+}
+
+.spoiler:hover, .spoiler a:hover, .spoiler:hover .quote {
+    background: none;
+    color: #999;
+    box-shadow: none;
+}
+
+.spoiler a:hover {
+    color:#804040;
+}
+
+.quote, #button-quote, .quote .spoiler:hover, .spoiler:hover .quote {
+    color: #51860F;
+}
+
+#button-quote:hover {
+    color: #426E0F;
+}
+
+.last-modified {
+    font-size: 0.7em;
+}
+/* Files */
+.file-info {
+    display: none;
+}
+/* *************************************** */
+/* **************** Admin **************** */
+/* *************************************** */
+.admin-navbar {
+    border-right: 1px solid rgba(10, 10, 10, 0.3);
+}
+.admin-navbar li:hover {
+    background-color: #CFCFCF;
+}
+
+/* *************************************** */
+/* *********** Popup alerts ************** */
+/* *************************************** */
+.popup-alert, .panel {
+    background: none repeat scroll 0% 0% #2C2C2C;
+    border-radius: 3px;
+    border: 1px dashed #5c1f1f;
+    box-shadow: 2px 4px 25px -4px #1A1A1A;
+}
+/* *************************************** */
+/* ************ Home page **************** */
+/* *************************************** */
+.board-category {
+    font-weight: bold;
+}
+.panel p, #board-title, #main-title h1, #main h2, .pagination a, .top-bar a {
+    color: #a2a2a2!important;
+}
diff --git a/templates/default-layout.lucius b/templates/default-layout.lucius
index 74d7836..9c2eca8 100644
--- a/templates/default-layout.lucius
+++ b/templates/default-layout.lucius
@@ -44,74 +44,78 @@ footer {
     content: "✖";
 }

-input[type="text"],
-input[type="password"],
-input[type="date"],
-input[type="datetime"],
-input[type="datetime-local"],
-input[type="month"],
-input[type="week"],
-input[type="email"],
-input[type="number"],
-input[type="search"],
-input[type="tel"],
-input[type="time"],
-input[type="url"],
-textarea {
-    display: block;
-    font-size: 0.875em;
-    margin: 0 0 1em 0;
-    padding: 0.1em;
-    height: 1.5em;
-    width: 100%;
-}
-
-.prefix,
-.postfix {
-    font-size: 0.875em;
-    height: 1.5em;
-    line-height: 1.25em;
-}
+#edit-form textarea {
+    width: 97%;
+}
+
+/*    input[type="datetime-local"],              */
+/*    input[type="password"],                    */
+/*    input[type="datetime"],                    */
+/*    input[type="number"],                      */
+/*    input[type="search"],                      */
+/*    input[type="month"],                       */
+/*    input[type="email"],                       */
+/*    input[type="week"],                        */
+/*    input[type="time"],                        */
+/*    input[type="date"],                        */
+/*    input[type="text"],                        */
+/*    input[type="tel"],                         */
+/*    input[type="url"] {                        */
+/*        display: block;                        */
+/*        font-size: 0.875em;                    */
+/*        margin: 0 0 1em 0;                     */
+/*        padding: 0.1em;                        */
+/*        height: 1.5em;                         */
+/*        width: 100%;                           */
+/*    }                                          */
+/*                                               */
+/*    .prefix,                                   */
+/*    .postfix {                                 */
+/*        font-size: 0.875em;                    */
+/*        height: 1.5em;                         */
+/*        line-height: 1.25em;                   */
+/*    }                                          */

 /* Adjust padding, alignment and radius if pre/post element is a button */
-.postfix.button {
-    line-height: 1.25em;
-}
+/*    .postfix.button {                          */
+/*        line-height: 1.25em;                   */
+/*    }                                          */
+/*                                               */
+/*    .prefix.button {                           */
+/*        line-height: 1.25em;                   */
+/*    }                                          */
+/*                                               */
+/*    button, .button {                          */
+/*        margin: 0 0 1.25em;                    */
+/*        padding-top: 0.75em;                   */
+/*        padding-right: 1.5em;                  */
+/*        padding-bottom: 0.8125em;              */
+/*        padding-left: 1.5em;                   */
+/*        font-size: 0.875em;                    */
+/*    }                                          */
+
+/*    form.custom .custom.dropdown .current {    */
+/*        line-height: 1.225em;                  */
+/*        fon-size: 0.875em;                     */
+/*    }                                          */
+/*                                               */
+/*    form.custom .custom.dropdown {             */
+/*        height: 1.5em;                         */
+/*    }                                          */
+
+/*    form.custom .custom.dropdown .selector {   */
+/*        height: 1.5em;                         */
+/*    }                                          */
+/*                                               */
+/*    label.inline {                             */
+/*        margin: 0 0 1em;                       */
+/*        padding: 0;                            */
+/*    }                                          */
+/*                                               */
+/*    form.custom .custom.checkbox:before {      */
+/*        line-height: 1.11;                     */
+/*    }                                          */

-.prefix.button {
-    line-height: 1.25em;
-}
-
-button, .button {
-    margin: 0 0 1.25em;
-    padding-top: 0.75em;
-    padding-right: 1.5em;
-    padding-bottom: 0.8125em;
-    padding-left: 1.5em;
-    font-size: 0.875em;
-}
-
-form.custom .custom.dropdown .current {
-    line-height: 1.225em;
-    fon-size: 0.875em;
-}
-
-form.custom .custom.dropdown {
-    height: 1.5em;
-}
-
-form.custom .custom.dropdown .selector {
-    height: 1.5em;
-}
-
-label.inline {
-    margin: 0 0 1em;
-    padding: 0;
-}
-
-form.custom .custom.checkbox:before {
-    line-height: 1.11;
-}
 /* ********************************* */
 /* ************* Icons ************* */
 /* ********************************* */
@@ -172,10 +176,6 @@ form.custom .custom.checkbox:before {
     float: right;
 }

-.no-js .icon-hide-thread {
-    display: none;
-}
-
 .icon-show-thread {
     float: right;
     background-position: -1037px -77px;
@@ -186,20 +186,11 @@ form.custom .custom.checkbox:before {
     background-position: -77px -29px;
 }

-.no-js .icon-hide-thread-completely {
-    display: none;
-}
-
 .icon-reply {
     background-position: -605px -173px;
 }

-.no-js .icon-reply {
-    display: none;
-}
-
 .show-plain-form {
-    display:none;
     text-align: center;
 }

@@ -211,10 +202,6 @@ form.custom .custom.checkbox:before {
     background-position: -77px -77px;
 }

-.no-js .icon-edit-post {
-    display: none;
-}
-
 .icon-close {
     background-position: -269px -101px;
 }
@@ -224,10 +211,6 @@ form.custom .custom.checkbox:before {
     opacity: 0.3;
 }

-.no-js .icon-del-post {
-    display: none;
-}
-
 .icon-eye-open {
     background-position: -53px -29px;
     cursor: auto;
@@ -237,6 +220,17 @@ form.custom .custom.checkbox:before {
     background-position: -629px -77px;
     margin-right: 3px;
 }
+
+
+.no-js .icon-hide-thread-completely,
+.no-js .icon-hide-thread,
+.no-js .icon-edit-post,
+.no-js .icon-del-post,
+.no-js .icon-reply,
+.show-plain-form {
+    display: none;
+}
+
 /* *************************************** */
 /* **************** Header *************** */
 /* *************************************** */
@@ -264,8 +258,11 @@ form.custom .custom.checkbox:before {
 }

 .post {
-    padding: 5px;
-    margin: 3px;
+   padding: 9px 12px!important;
+}
+
+.reply {
+   margin-bottom: 6px!important;
 }

 .multi-file {
@@ -285,10 +282,32 @@ form.custom .custom.checkbox:before {
     display: block;
 }

-.censored {
+#captcha, .censored, iframe, pre {
     display: block;
 }

+.video-thumb {
+    cursor: pointer;
+}
+
+.video-container {
+    display: table;
+    background-color: black;
+}
+
+iframe {
+    border: none;
+}
+
+pre {
+    overflow: auto;
+    width: 450px;
+   min-height: 450px;
+    height: 150px;
+    min-height: 150px;
+    resize: both !important;
+}
+
 /* Message */
 .message {
     padding: 8px 10px;
@@ -349,6 +368,20 @@ form.custom .custom.checkbox:before {
     float: right;
 }

+.delete-container, .thread-bottom {
+   padding-top: 3px;
+}
+
+.delete-container .tiny {
+    margin-left: 8px;
+}
+
+#edit-button, .delete-container .tiny{
+   padding-top: 5px;
+   padding-bottom: 5px;
+   margin-top: 3px;
+}
+
 /* *************************************** */
 /* *********** Popup alerts ************** */
 /* *************************************** */
@@ -378,132 +411,111 @@ form.custom .custom.checkbox:before {
     top: 10px;
 }

-/* .admin-table { */
-/*     border-collapse: collapse; */
-/*     font-size: 0.8em; */
-/*     margin: 7px; */
-/* } */
-
-/* .admin-table td, .admin-table th { */
-/*     border: 1px solid black; */
-/*     border-collapse: collapse; */
-/*     padding: 5px; */
-/*     padding-right: 8px; */
-/* } */
-
-/* .admin-table input { */
-/*     width: 100%; */
-/* } */
-
-
-
-/* header { */
-/*     padding-bottom: 15px; */
-/* } */
-
-/* .js .mark-to-delete input[type=checkbox] { */
-/*     display:none; */
-/* } */
-
-/* #edit-form textarea { */
-/*     width: 98%; */
-/* } */
-
-/* #close-edit-form { */
-/*     float:right; */
-/*     margin: 3px 5px; */
-/* } */
-
-/* .last-modified { */
-/*     font-size: 0.7em; */
-/*     float:right; */
-/* } */
-
-/* .hist-date { */
-/*     margin: 10px; */
-/*     text-align: center; */
-/*     font-weight: bold; */
-/* } */
-
-/* .hist-msg { */
-/*     word-wrap: break-word; */
-/*     width: 50%; */
-/*     margin: 0 auto; */
-/* } */
-
-/* #edit-history-header { */
-/*     text-align: center; */
-/* } */
-
-/* .file-name { */
-/*     margin: 2px; */
-/* } */
-
-/* .file-info { */
-/*     font-style: italic; */
-/*     margin: 2px; */
-/* } */
-
-/* iframe { */
-/*     border: 0px; */
-/* } */
-
-/* .focused { */
-/*     text-decoration: underline; */
-/* } */
-
-/* ul { */
-/*     list-style-position: inside; */
-/*     margin: 0; */
-/*     padding: 0 0 0 15px; */
-/* } */
-
-
-/* .expand-post { */
-/*     padding: 3px 0 0 8px; */
-/* } */
-
-/* .shrink-post { */
-/*     padding-left: 8px; */
-/* } */
-
-/* .expand-post, .shrink-post { */
-/*     color: #666666; */
-/* } */
-
-/* .markup-wrapper { */
-/*     margin:0 auto; */
-/*     width:90%; */
-/*     padding: 5px; */
-/* } */
-
-/* .abbreviated { */
-/*     max-height: 250px; */
-/*     overflow:hidden; */
-/* } */
-
-/* #delete-container { */
-/*     clear: both; */
-/* } */
-
-
-/* #captcha { */
-/*     display: block; */
-/* } */
-
-/* .censored { */
-/*     display: block; */
-/* } */
-
-/* .no-js .markup-buttons { */
-/*     visibility: hidden; */
-/*     height: 0px; */
-/* } */
-
-/* .video-thumb { */
-/*     cursor: pointer; */
-/* } */
-
-/* .thumb { */
-/*     outline: none; */
-/* } */
+/*    .admin-table {
+/*        border-collapse: collapse;
+/*        font-size: 0.8em;
+/*        margin: 7px;
+/*    }                       */
+                                                  
+/*    .admin-table td, .admin-table th { */       
+/*        border: 1px solid black; */             
+/*        border-collapse: collapse; */           
+/*        padding: 5px; */                        
+/*        padding-right: 8px; */                  
+/*    } */                                        
+                                                  
+/*    .admin-table input { */                     
+/*        width: 100%; */                         
+/*    } */                                        
+                                                  
+                                                  
+/*    header { */                                 
+/*        padding-bottom: 15px; */                
+/*    } */                                        
+                                                  
+/*    .js .mark-to-delete input[type=checkbox] { */
+/*        display:none; */                        
+/*    } */                                        
+                                                  
+/*    #close-edit-form { */                       
+/*        float:right; */                         
+/*        margin: 3px 5px; */                     
+/*    } */                                        
+                                                  
+/*    .last-modified { */                         
+/*        font-size: 0.7em; */                    
+/*        float:right; */                         
+/*    } */                                        
+                                                  
+/*    .hist-date { */                             
+/*        margin: 10px; */                        
+/*        text-align: center; */                  
+/*        font-weight: bold; */                   
+/*    } */                                        
+                                                  
+/*    .hist-msg { */                              
+/*        word-wrap: break-word; */               
+/*        width: 50%; */                          
+/*        margin: 0 auto; */                      
+/*    } */                                        
+                                                  
+/*    #edit-history-header { */                   
+/*        text-align: center; */                  
+/*    } */                                        
+                                                  
+/*    .file-name { */                             
+/*        margin: 2px; */                         
+/*    } */                                        
+                                                  
+/*    .file-info { */                             
+/*        font-style: italic; */                  
+/*        margin: 2px; */                         
+/*    } */                                        
+                                                  
+/*    .focused { */                               
+/*        text-decoration: underline; */          
+/*    } */                                        
+                                                  
+/*    ul { */                                     
+/*        list-style-position: inside; */         
+/*        margin: 0; */                           
+/*        padding: 0 0 0 15px; */                 
+/*    }                                         */
+
+
+/*    .expand-post {                            */
+/*        padding: 3px 0 0 8px;                 */
+/*    }                                         */
+
+/*    .shrink-post {                            */
+/*        padding-left: 8px;                    */
+/*    }                                         */
+
+/*    .expand-post, .shrink-post {              */
+/*        color: #666666;                       */
+/*    }                                         */
+
+/*    .markup-wrapper {                         */
+/*        margin:0 auto;                        */
+/*        width:90%;                            */
+/*        padding: 5px;                         */
+/*    }                                         */
+
+/*    .abbreviated {                            */
+/*        max-height: 250px;                    */
+/*        overflow:hidden;                      */
+/*    }                                         */
+
+/*    #delete-container {                       */
+/*        clear: both;                          */
+/*    }                                         */
+
+
+/*    .no-js .markup-buttons {                  */
+/*        visibility: hidden;                   */
+/*        height: 0px;                          */
+/*    }                                         */
+
+/*    .thumb {                                  */
+/*        outline: none;                        */
+/*    }                                         */
diff --git a/templates/edit-form.hamlet b/templates/edit-form.hamlet
index 64b4333..de49806 100644
--- a/templates/edit-form.hamlet
+++ b/templates/edit-form.hamlet
@@ -1,60 +1,57 @@
 #{extra}
-<span style=display:none>
+<span style="display:none">
     ^{fvInput postIdView}

 <div .row>
-  <div .columns .large-12 .small-12>
+  <div .columns .large-11 .small-12>
     ^{fvInput messageView}
-
-<div .row>
-  <div .columns .large-12 .small-12>  
-    <div .markup-buttons style=display:inline>
+    <div .markup-buttons style="display:inline">
       <ul .inline-list>
         <li>
-         <a id=button-bold-edit>
+         <a id="button-bold-edit">
             <strong>
               _{MsgMarkupBold}
         <li>
-         <a id=button-italic-edit>
+         <a id="button-italic-edit">
             <em>
               _{MsgMarkupItalic}
         <li>
-         <a id=button-underline-edit>
+         <a id="button-underline-edit">
             <u>
               _{MsgMarkupUnderline}
         <li>
-         <a id=button-strike-edit>
+         <a id="button-strike-edit">
             <span style="text-decoration:line-through">
               _{MsgMarkupStrike}
         <li>
-         <a id=button-spoiler-edit>
+         <a id="button-spoiler-edit">
             <span .spoiler>
               _{MsgMarkupSpoiler}
         <li>
-         <a id=button-code-edit>
+         <a id="button-code-edit">
             _{MsgMarkupCode}
         <li>
-         <a id=button-inline-latex-edit>
+         <a id="button-inline-latex-edit">
             _{MsgMarkupInlineLatex}
         <li>
-         <a id=button-latex-edit>
+         <a id="button-latex-edit">
             _{MsgMarkupLatex}
         <li>
-         <a id=button-quote-edit .quote>
+         <a id="button-quote-edit" .quote>
             _{MsgMarkupQuote}
         <li>
-         <span style=display:inline .symbol-counter>
+         <span style="display:inline" .symbol-counter>
 <div .row>
   <div .columns .large-3 .small-6>
     ^{fvInput passwordView}
   <div .columns .large-3 .small-5>
-    <input .button .tiny type=button id=edit-button value=_{MsgEdit}>
+    <input .button .tiny type="button" id="edit-button" value="_{MsgEdit}">
   <div .columns .large-1 .pull-5 .small-1>
-    <a title=_{MsgCloseIcon} onclick="hideEditForm()" #close-edit-form>
+    <a title="_{MsgCloseIcon}" onclick="hideEditForm()" #close-edit-form>

 $if elem ShadowEditP permissions
   <div .row>
     <div .columns .large-12 .small-12>
       ^{fvInput shadowView}
-      <label style=display:inline for=#{fvId shadowView}>
+      <label style="display:inline" for="#{fvId shadowView}">
         _{MsgDontSaveHistory}
diff --git a/templates/post-form.hamlet b/templates/post-form.hamlet
index ad24c21..d87b29e 100644
--- a/templates/post-form.hamlet
+++ b/templates/post-form.hamlet
@@ -1,79 +1,71 @@
 #{extra}
 <div .row .collapse>
-  <div .large-1 .small-5 .columns>
-    <label .prefix for=#{fvId nameView}>_{MsgName}
   <div .large-3 .small-7 .columns>
     ^{fvInput nameView}
-  <div .large-2 .pull-6 .small-7 .columns .no-bump-block>
-    <label .inline for=#{fvId nobumpView}>
+  <div .large-2 .pull-7 .small-7 .columns .no-bump-block>
+    <label .inline for="#{fvId nobumpView}">
       _{MsgNobump}
       ^{fvInput nobumpView}

 <div .row .collapse .subject-block>
-  <div .large-1 .small-5 .columns>
-    <label for=#{fvId subjectView} .prefix>_{MsgSubject}
   <div .large-3 .small-7 .columns>
     ^{fvInput subjectView}
-  <div .large-2 .pull-6 .small-12 .columns>
-    <input type=submit .button .postfix value=_{MsgSubmitBtn}>
+  <div .large-2 .pull-7 .small-12 .columns>
+    <input type="submit" .button .postfix value="_{MsgSubmitBtn}">

 <div .row .collapse>
-  <div .large-12 .columns >
+  <div .large-10 .columns >
     ^{fvInput messageView}
     <div .markup-buttons>
       <ul .inline-list>
         <li>
-         <a id=button-bold>
+         <a id="button-bold">
             <strong>
               _{MsgMarkupBold}
         <li>
-         <a id=button-italic>
+         <a id="button-italic">
             <em>
               _{MsgMarkupItalic}
         <li>
-         <a id=button-underline>
+         <a id="button-underline">
             <u>
               _{MsgMarkupUnderline}
         <li>
-         <a id=button-strike>
+         <a id="button-strike">
             <span style="text-decoration:line-through">
               _{MsgMarkupStrike}
         <li>
-         <a id=button-spoiler>
+         <a id="button-spoiler">
             <span .spoiler>
               _{MsgMarkupSpoiler}
         <li>
-         <a id=button-code>
+         <a id="button-code">
             _{MsgMarkupCode}
         <li>
-         <a id=button-inline-latex>
+         <a id="button-inline-latex">
             _{MsgMarkupInlineLatex}
         <li>
-         <a id=button-latex>
+         <a id="button-latex">
             _{MsgMarkupLatex}
         <li>
-         <a id=button-quote .quote>
+         <a id="button-quote .quote">
             _{MsgMarkupQuote}
         <li>
-         <span style=display:inline .symbol-counter>
+         <span style="display:inline" .symbol-counter>
 <div .row .collapse>
-  <div .large-1 .small-5 .columns>
-    <label for=#{fvId passwordView} .prefix>_{MsgPassword}
-  <div .large-3 .pull-8 .small-7 .columns>
+  <div .large-3 .small-7 .columns>
     ^{fvInput passwordView}

 $if enableCaptchaW
-  <div .row .collapse>
-    <div .large-1 .small-5 .columns>
-      <label for=#{fvId captchaView} .prefix>_{MsgCaptcha}
-    <div .large-4 .small-7 .columns>
+  <div .row .collapse style="padding-bottom:3px;">
+    <div .large-3 .small-7 .columns>
       $if isJust muserW
           <span .prefix>_{MsgYouDontNeedCaptcha}      
       $else
           $maybe _ <- acaptchaW
               <span .prefix>_{MsgYouDontNeedCaptcha}
-          $nothing
-              ^{fvInput captchaView} 
+          $nothing                       
+              <img alt="captcha" #captcha src="@{CaptchaR}">
               <label #captcha-info for="#{fvId captchaView}">
                   $maybe c <- maybeCaptchaInfoW
                       _{MsgTypeOnly} 
@@ -85,8 +77,7 @@ $if enableCaptchaW
                           _{MsgRegularChars}
                   $nothing
                       _{MsgReloadPage}
-    <div .large-7 .small-12 .columns>                      
-      <img alt=captcha #captcha src=@{CaptchaR}>
+              ^{fvInput captchaView}

 $if length fileviews > 0
   $forall (fv, rv) <- zip fileviews ratingviews
@@ -99,11 +90,11 @@ $if length fileviews > 0
       <div .columns .large-1 .small-4 .file-input-size>
         <span .postfix>
       <div .columns .large-1 .pull-3 .small-4>
-        <a .clear-file title=_{MsgRemoveFileIcon} onclick="clearFile('#{unpack $ fvId fv}')"></a>
+        <a .clear-file title="_{MsgRemoveFileIcon}" onclick="clearFile('#{unpack $ fvId fv}')"></a>

 <div .row .collapse .go-back-block>
   <div .large-1 .small-5 .columns>
-    <label for=#{fvId gobackView} .prefix>_{MsgGoback}
+    <label for="#{fvId gobackView}" .prefix>_{MsgGoback}
   <div .large-2 .pull-9 .small-7 .columns>
     ^{fvInput gobackView}

diff --git a/templates/post-form.lucius b/templates/post-form.lucius
index 479f9be..bb3f87a 100644
--- a/templates/post-form.lucius
+++ b/templates/post-form.lucius
@@ -1,7 +1,16 @@
 textarea {
-    height: 150px;
-    min-height: 150px;
-    width: 90% !important;
+    width: 97%;
+    height: 200px;
+    min-height: 200px;
+   resize: both !important;
+}
+
+#post-form input, 
+#post-form label, 
+#post-form textarea, 
+#post-form .file-select, 
+#post-form .dropdown {
+    margin-bottom: 3px;
 }

 .clear-file {
@@ -13,36 +22,27 @@ textarea {
     content: "✖";
 }

-.clear-file, .file-input-size {
-    display: none;
-}
-/* .quick-post-form { */
-/*     text-align: left; */
-/*     margin: 5px 0 0; */
-/*     display: table; */
-/*     width: 95%;   */
-/*     padding: 5px; */
-/* } */
-
-/* .plain-post-form { */
-/*     width: 75%; */
-/*     margin: 10px 10%; */
-/*     border: 0px; */
-/*     padding: 5px; */
-/* } */
+/*  .quick-post-form {      */
+/*      text-align: left;   */
+/*      margin: 5px 0 0;    */
+/*      display: table;     */
+/*      width: 95%;         */
+/*      padding: 5px;       */
+/*  }                       */
+
+/*  .plain-post-form {      */
+/*      width: 75%;         */
+/*      margin: 10px 10%;   */
+/*      border: 0px;        */
+/*      padding: 5px;       */
+/*  }                       */

 .close-post-form {
     text-align: center;
 }

-.js .file-input {
-    visibility: none;
-    position: absolute;
-    left: -999999px;
-}
-
-.no-js .file-select, .no-js .close-post-form, .no-js .markup-buttons {
-    display: none;
+.file-select {
+   padding: 9px !important;
 }

 .file-input-thumb {
@@ -51,6 +51,23 @@ textarea {
     display: block;
 }

-.markup-buttons ul {
-    line-height: 1em;    
+.markup-buttons {
+   font-variant: small-caps;
 }
+
+.subject-block .button {
+    margin-left: 5px;
+}
+
+.no-bump-block label {
+    padding-left: 5px;
+}
+
+.no-js .close-post-form,
+.no-js .markup-buttons,
+.no-js .file-select,
+.file-input-size,
+.js .file-input,
+.clear-file {
+    display: none;
+}
\ No newline at end of file

Обновление треда [Операпроблемы]

Пишу пост, отправляю - страница треда как бы перезагружается, но остается такой же, какой она была, когда я зашел на нее. Жму F5 - в треде появляются новые ответы, в т.ч. мой пост. То есть, не работает автообновление, вообще. Кнопка "получить новые посты" никак не действует.

Windows 7 x86, Opera 12.15 (Presto)

captcha doesn't work and breaks all board

image
when I enable captcha feature on board settings and go to check it, page displays only this text
/opt/monaba/PlainCaptcha: readCreateProcess: runInteractiveProcess: exec: does not exist (No such file or directory)

using Debian 10 and Docker image

Не бампаются треды

В списке тредов всегда сохраняется определенный порядок и если писать в нижние треды, она не перемещаются вверх страницы. Иногда порядок меняется, если админ выходит на связь.

Possible memory leak while building from source

When I try to compile/build from source, using either stackage and cabal, the process halts when it reaches the following step [25 of 32] Compiling Handler.Admin.Board ( Handler/Admin/Board.hs, .stack-work/dist/x86_64-linux/Cabal-1.22.4.0/build/Handler/Admin/Board.o ).
I'm currently with 8GB of RAM, SSD, and 2GB of swap (file), and the building process consumes everything before halting (high I/O, system lagging etc).

Удаление постов из треда

При удалении поста нескольких постов в треде, удалился сам тред целиком, база pgsql. Хорошо бы сделать лог администраторских действий в admin area, чтобы можно было отследить действия

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.