{"id":15017439,"url":"https://github.com/kberov/slovo","last_synced_at":"2025-04-09T19:42:26.896Z","repository":{"id":31015162,"uuid":"126513321","full_name":"kberov/Slovo","owner":"kberov","description":"Искони бѣ Слово - already in production at https://слово.бг","archived":false,"fork":false,"pushed_at":"2023-04-25T22:35:47.000Z","size":2551,"stargazers_count":19,"open_issues_count":1,"forks_count":3,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-23T21:45:33.075Z","etag":null,"topics":["cms","cms-framework","markdown","mojolicious","mvc","mvc-architecture","openapi","perl5","rest-api","slovo","trumbowyg-wysiwyg"],"latest_commit_sha":null,"homepage":"https://слово.бг","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kberov.png","metadata":{"files":{"readme":"README.pod","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-23T16:45:28.000Z","updated_at":"2024-02-23T19:07:28.000Z","dependencies_parsed_at":"2024-06-19T00:21:35.782Z","dependency_job_id":"eb4395c5-4fa9-4045-a890-2e999661bb1c","html_url":"https://github.com/kberov/Slovo","commit_stats":{"total_commits":188,"total_committers":6,"mean_commits":"31.333333333333332","dds":"0.18085106382978722","last_synced_commit":"a6aef2ab9765caa7c9efa2400dc1befcd777fae9"},"previous_names":[],"tags_count":57,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kberov%2FSlovo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kberov%2FSlovo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kberov%2FSlovo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kberov%2FSlovo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kberov","download_url":"https://codeload.github.com/kberov/Slovo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248101099,"owners_count":21047901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","cms-framework","markdown","mojolicious","mvc","mvc-architecture","openapi","perl5","rest-api","slovo","trumbowyg-wysiwyg"],"created_at":"2024-09-24T19:50:27.947Z","updated_at":"2025-04-09T19:42:26.871Z","avatar_url":"https://github.com/kberov.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"=encoding utf8\n\n=head1 NAME\n\nSlovo - Искони бѣ Слово\n\n=head1 SYNOPSIS\n\nInstall Slovo locally with all dependencies in less than two minutes\n\n    time curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org \\\n    -q -n -l ~/opt/slovo Slovo\n\nRun slovo for the first time in debug mode\n\n   morbo ~/opt/slovo/bin/slovo\n\nVisit L\u003chttp://127.0.0.1:3000\u003e.\nFor help visit L\u003chttp://127.0.0.1:3000/perldoc\u003e.\n\n=head1 DESCRIPTION\n\nL\u003cSlovo\u003e is a simple to install and extensible L\u003cMojolicious\u003e\nL\u003cCMS|https://en.wikipedia.org/wiki/Web_content_management_system\u003e\nwith nice core features, listed below. \n\nThis is a usable release, yet B\u003cfull of creeping bugs\u003e and B\u003chalf-implemented\npieces\u003e! The project is in active development, so expect often breaking changes.\n\n=over\n\n=item * On the fly generation of static pages under Apache/CGI – perfect for\ncheap shared hosting and blogging – BETA;\n\n=item * Multi-domain support - BETA;\n\n=item * Multi-language pages - WIP;\n\n=item * Cached published pages and content - DONE;\n\n=item * Multi-user support - DONE;\n\n=item * User onboarding - WIP;\n\n=item * User sign in - DONE;\n\n=item * Managing pages, content, domains, users - WIP;\n\n=item * Managing groups - BASIC;\n\n=item * Multiple groups per user - DONE;\n\n=item * Ownership and permissions management per page and it's content - BETA;\n\n=item * Automatic 301 and 308 (Moved Permanently) redirects for renamed pages\nand content - DONE;\n\n=item * Embedded fonts for displaying all\nL\u003cAzbuka|https://en.wikipedia.org/wiki/Cyrillic_script\u003e and\nL\u003cGlagolitsa|https://en.wikipedia.org/wiki/Glagolitic_script\u003e characters -\nDONE;\n\n=item * OpenAPI 2/3.0 (Swagger) REST API - BASIC;\n\n=item * Embedded Trumbowyg - L\u003cA lightweight WYSIWYG editor|https://alex-d.github.io/Trumbowyg/\u003e;\n\n=item * Embedded Editor.md - L\u003cThe open source embeddable online markdown editor\n(component), based on CodeMirror \u0026 jQuery \u0026\nMarked|http://editor.md.ipandao.com/\u003e;\n\n=item * Example startup scripts for slovo and slovo_minion services\nfor L\u003csystemd|https://freedesktop.org/wiki/Software/systemd/\u003e, L\u003cApache\n2.4|https://httpd.apache.org/docs/2.4/\u003e and NGINX vhost configuration files.\n\n=item * Inflatable embedded themes support - BETA;\n\n=item * and more to come…\n\n=back\n\nBy default Slovo comes with SQLite database, but support for PostgreSQL or\nMySQL is about to be added when needed. It is just a question of making\ncompatible and/or translating some limited number of SQL queries to the\ncorresponding SQL dialects. Contributors are welcome.\n\nThe word \"slovo\" (слово) has one unchanged meaning during the last millennium\namong all slavic languages. It is actually one language that started splitting\napart less than one thousand years ago. The meaning is \"word\" – the God's word\n(when used with capital letter). Hence the self-naming of this group of people\nC\u003cqr/sl(o|a)v(e|a|i)n(i|y|e)/\u003e - people who have been given the God's word or\npeople who can speak. All others were considered \"mute\", hence the naming\n(немци)...\n\n=head1 INSTALL\n\nAll you need is a one-liner, it takes less than a minute.\n\n    $ curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org -n -l ~/opt/slovo Slovo\n\nWe recommend the use of a L\u003cPerlbrew|http://perlbrew.pl\u003e environment.\n\nIf you already downloaded it and you have L\u003ccpanm\u003e.\n\n    $ cpanm -l ~/opt/slovo Slovo-XXXX.XX.XX.tar.gz\n\nOr even if you don't have C\u003ccpanm\u003e. Note that you need to install dependencies first.\nSet C\u003cINSTALL_BASE\u003e, remove old Slovo installation, make, test, install, create\ndata directory for sqlite database and run slovo to see available commands.\n\n    tar zxf Slovo-XXXX.XX.XX.tar.gz\n    cd  Slovo-XXXX.XX.XX\n    INSTALL_BASE=~/opt/slovo \u0026\u0026 rm -rf $INSTALL_BASE \u0026\u0026 make distclean; \\\n    perl Makefile.PL INSTALL_BASE=$INSTALL_BASE \u0026\u0026 make \u0026\u0026 make test \u0026\u0026 make install \\\n    \u0026\u0026 $INSTALL_BASE/bin/slovo eval 'app-\u003ehome-\u003echild(\"data\")-\u003emake_path({mode =\u003e 0700});' \\\n    \u0026\u0026 $INSTALL_BASE/bin/slovo\n\nUse cpanm to install or update into a custom location as self contained application and\nrun slovo to see how it's going.\n\n    # From metacpan. org\n    export PREFIX=~/opt/slovo;\n    cpanm -M https://cpan.metacpan.org -n --self-contained -l $PREFIX Slovo \\\n    $PREFIX/bin/slovo eval 'app-\u003ehome-\u003echild(\"data\")-\u003emake_path({mode =\u003e 0700});' \\\n    $PREFIX/bin/slovo\n\n    # From the directory where you unpacked Slovo\n    export PREFIX=~/opt/slovo;\n    cpanm . -n --self-contained -l $PREFIX Slovo\n    $PREFIX/bin/slovo eval 'app-\u003ehome-\u003echild(\"data\")-\u003emake_path({mode =\u003e 0700});'\n    $PREFIX/bin/slovo\n\nStart the development server and open a browser\n\n    morbo ./script/slovo -l http://*:3000 \u0026 sleep 1 exo-open http://localhost:3000\n\n=head1 USAGE\n\n    cd /path/to/installed/slovo\n    # ...and see various options\n    ./bin/slovo\n\n=head1 CONFIGURATION, PATHS and UPGRADING\n\nL\u003cSlovo\u003e is a L\u003cMojolicious\u003e application which means that everything\napplying to Mojolicious applies to it too. Slovo main configuration file is\nin C\u003clib/Slovo/resourses/etc/slovo.conf\u003e. You can use your own by setting\nC\u003c$ENV{MOJO_CONFIG}\u003e or by just copying C\u003cslovo.conf\u003e to $ENV{MOJO_HOME} and\nmodify it as you wish. Routes can be added or removed in C\u003croutes.conf\u003e. See\nL\u003cMojolicious::Plugin::RoutesConfig\u003e for details and examples. New plugins can\nbe added per deployment in C\u003cplugins\u003e section in C\u003cslovo.conf\u003e.\n\nC\u003c$ENV{MOJO_HOME}\u003e (L\u003cwhere you installed Slovo|/home\u003e) is automatically\ndetected and used. All paths, used in the application, are expected to be its\nchildren. You can add your own templates in C\u003c$ENV{MOJO_HOME}/templates\u003e and\nthey will be loaded and used with priority. You can theme your own instance of\nSlovo by just copying C\u003c$ENV{MOJO_HOME}/lib/Slovo/resources/templates\u003e to\nC\u003c$ENV{MOJO_HOME}/templates\u003e and modify them. You can add your own static files\nto C\u003c$ENV{MOJO_HOME}/public\u003e. You can create custom themes by forking\nL\u003cSlovo::Themes::Malka\u003e and using it as a starting point.\n\nYou can have separate static files and templates per domain under\nC\u003c$ENV{MOJO_HOME}/domove/your.domain/public\u003e,\nC\u003c$ENV{MOJO_HOME}/domove/your.other.domain/templates\u003e, etc. See\nC\u003c$ENV{MOJO_HOME}/domove/localhost\u003e for example.\n\nYou can switch between different themes by just selecting the theme in the\nform for editing domains.\n\nLast but not least, you can add your own classes into\nC\u003c$ENV{MOJO_HOME}/site/lib\u003e and (why not) replace entirely some Slovo classes\nor just extend them. C\u003c$ENV{MOJO_HOME}/bin/slovo\u003e will load them with priority.\n\nWith all the above, you can upgrade L\u003cSlovo\u003e by just installing new versions\nover it and your files will not be touched. And of course, we know that you are\nusing versioning just in case anything goes wrong. See L\u003c/home\u003e.\n\n=head1 ATTRIBUTES\n\nL\u003cSlovo\u003e inherits all attributes from L\u003cMojolicious\u003e and implements\nthe following new ones.\n\n=head2 home\n\nL\u003cSlovo\u003e detects where B\u003chome\u003e is not like L\u003cMojo::Home\u003e by where\nC\u003clib/Mojolicous.pm\u003e is but by where the C\u003cscript/\u003e or C\u003cbin/\u003e folder resides\nstarting from where C\u003clib/Slovo.pm\u003e is and going up the tree. If in one of\nthese folders there is a C\u003cslovo\u003e executable, then the upper folder is the\nhome.\n\nExamples:\n\n    berov@Skylake:Slovo$ pwd\n    /home/berov/opt/dev/Slovo\n    berov@Skylake:Slovo$ perl script/slovo eval 'say app-\u003ehome'\n    /home/berov/opt/dev/Slovo\n\n    berov@Skylake:Slovo$ cpanm . -n -l ~/opt/t.com/slovo\n    --\u003e Working on .\n    Configuring /home/berov/opt/dev/Slovo ... OK\n    Building Slovo-v2019.06.09 ... OK\n    Successfully installed Slovo-v2019.06.09\n    1 distribution installed\n\n    berov@Skylake:t.com$ pwd\n    /home/berov/opt/t.com\n    berov@Skylake:t.com$ slovo/bin/slovo eval 'say app-\u003ehome'\n    /home/berov/opt/t.com/slovo\n\n    berov@Skylake:t.com$ pwd\n    /home/berov/opt/t.com\n    berov@Skylake:t.com$ perl -Islovo/lib/perl5 -MSlovo -E 'say Slovo-\u003enew-\u003ehome'\n    /home/berov/opt/t.com/slovo\n\n=head2 log\n\nOverrides L\u003cMojolicious/log\u003e. Logs to C\u003cself-E\u003cgt\u003ehome-E\u003cgt\u003echild('log/slovo.log')\u003e\nif C\u003c$self-E\u003cgt\u003ehome-E\u003cgt\u003echild('log')\u003e exists and is writable. Oderwise writes to\nSTDERR. The log-level will default to either the C\u003cMOJO_LOG_LEVEL\u003e environment\nvariable, C\u003cdebug\u003e if the \"mode\" is C\u003cdevelopment\u003e, or C\u003cinfo\u003e otherwise.\n\n=head2 resources\n\n  push @{$app-\u003estatic-\u003epaths}, $app-\u003eresources-\u003echild('public');\n\nReturns a L\u003cMojo::File\u003e instance for path L\u003cSlovo/resources\u003e next to where\nC\u003cSlovo.pm\u003e is installed.\n\n=head2 validator\n\n  my $validator = $app-\u003evalidator;\n  $app          = $app-\u003evalidator(Slovo::Validator-\u003enew);\n\nValidate values, defaults to a L\u003cSlovo::Validator\u003e object.\n\n  # Add validation check\n  $app-\u003evalidator-\u003eadd_check(foo =\u003e sub {\n    my ($v, $name, $value) = @_;\n    return $value ne 'foo';\n  });\n\n  # Add validation filter\n  $app-\u003evalidator-\u003eadd_filter(quotemeta =\u003e sub {\n    my ($v, $name, $value) = @_;\n    return quotemeta $value;\n  });\n\n=head1 METHODS\n\nL\u003cSlovo\u003e inherits all methods from L\u003cMojolicious\u003e and implements\nthe following new ones.\n\n=head2 load_class\n\nA convenient wrapper with check for L\u003cMojo::Loader/load_class\u003e.\nLoads a class and croaks if something is wrong. This could be a helper.\n\n  for my $class (@{$config-\u003e{load_classes} // []}) {\n    $app-\u003eload_class($class);\n  }\n\n=head2 startup\n\nStarts the application. Adds hooks, prepares C\u003c$app-E\u003cgt\u003eroutes\u003e for use, loads\nconfiguration files and applies settings from them, loads plugins, sets default\npaths, and returns the application instance. See also L\u003cMojolicious/startup\u003e.\n\n=head1 HOOKS\n\nSlovo adds custom code to the following hooks.\n\n=head2 around_action\n\nOn each request we set the following variables in the stash so they are\navailable in the respective templates. Here they are:\n\n    $stash-\u003e{l}         //= $c-\u003elanguage;     # current language\n    $stash-\u003e{user}      //= $c-\u003euser;         # current user\n\n=head2 around_dispatch\n\nOn each request we determine the current host and modify the static and\nrenderer paths accordingly. This is how each domain has its own templates and\nstatic files.\n\nAlso if the C\u003ctemplates\u003e field for the current domain is not empty, we\ndetermine from it the templates root for the theme to be used for this domain\nduring this request. This is how the themes support for multiple domains in one\nL\u003cSlovo\u003e instance work.\n\nIt is also important to note that in a long running application (not CGI) the\ntemplates are cached in memory and the relative path from the current\ntemplates root to each template is used as the key in L\u003cMojo::Cache\u003e cache. We\nhad to implement L\u003cSlovo::Cache/key_prefix\u003e to be able to differentiate between\ntemplates having the same names, but found in different paths. All this is\npossible thanks to L\u003cMojolicious\u003e's well decoupled components.\n\nExample: Let's suppose that the domain L\u003chttps://слово.бг\u003e has the field\n'templates' value set to C\u003cthemes/malka\u003e (малка==small f. in Bulgarian).\n\nRenderer paths before the check is performed:\n\n  [\n    \"/home/berov/opt/dev/Slovo/templates\",\n    \"/home/berov/perl5/perlbrew/perls/perl-5.28.2/lib/site_perl/5.28.2/Mojolicious/Plugin/Minion/resources/templates\",\n    \"/home/berov/opt/dev/Slovo/lib/Slovo/resources/templates\"\n  ]\n\nStatic paths before the check:\n\n  [\n    \"/home/berov/opt/dev/Slovo/public\",\n    \"/home/berov/perl5/perlbrew/perls/perl-5.28.2/lib/site_perl/5.28.2/Mojolicious/Plugin/Minion/resources/public\",\n    \"/home/berov/opt/dev/Slovo/lib/Slovo/resources/public\"\n  ]\n\nRenderer paths after the check is performed. The first path in the list will be\nused with priority:\n\n  [\n    \"/home/berov/opt/dev/Slovo/lib/Slovo/resources/templates/themes/malka\", # if exists!\n    \"/home/berov/opt/dev/Slovo/domove/xn--b1arjbl.xn--90ae/templates\", # if exists!\n    \"/home/berov/opt/dev/Slovo/templates\",\n    \"/home/berov/perl5/perlbrew/perls/perl-5.28.2/lib/site_perl/5.28.2/Mojolicious/Plugin/Minion/resources/templates\",\n    \"/home/berov/opt/dev/Slovo/lib/Slovo/resources/templates\"\n  ]\n\nStatic paths after the check:\n\n  [\n    \"/home/berov/opt/dev/Slovo/domove/xn--b1arjbl.xn--90ae/public\", # if exists!\n    \"/home/berov/opt/dev/Slovo/public\",\n    \"/home/berov/perl5/perlbrew/perls/perl-5.28.2/lib/site_perl/5.28.2/Mojolicious/Plugin/Minion/resources/public\",\n    \"/home/berov/opt/dev/Slovo/lib/Slovo/resources/public\"\n  ]\n\nIn addition the current domain row from table C\u003cdomove\u003e becomes available in\nthe stash as C\u003c$domain\u003e.\n\n  # In a controller or model\n  $c-\u003estash('domain')-\u003e{id};\n  $m-\u003ec-\u003estash('domain')-\u003e{aliases};\n\n  # In a template like\n  # lib/Slovo/resources/templates/stranici/_form.html.ep\n  \u003c%=\n  select_box\n    dom_id   =\u003e $domove,\n    required =\u003e 1,\n    label    =\u003e 'Дом',\n    title    =\u003e 'В кой сайт се намира страницата.',\n    readonly =\u003e '',\n    value    =\u003e $domain-\u003e{id} #default value\n  %\u003e\n\n=head2 before_dispatch\n\nOn each request we check if we have a logged in user and set the current user\nto C\u003cguest\u003e if we don't. This way every part of the application (including\nnewly developed plugins) can count on having a current user. The user is needed\nto determine the permissions for any table that has column C\u003cpermissions\u003e. The\ncurrent user is available as C\u003c$c-E\u003cgt\u003euser\u003e.\n\n=head1 HELPERS\n\nSlovo implements the following helpers.\n\n=head2 openapi_spec\n\nWe need to have our OpenAPI API specification always at hand as a unified\nsource of truth so here it is.\n\n    # anywhere via $app or $c, even not via a REST call\n    state $columns =\n        $c-\u003eopenapi_spec('/paths/~1stranici/get/parameters/3/default');\n    [\n      \"id\",\n      \"pid\",\n      \"alias\",\n      \"title\",\n      \"is_dir\"\n    ]\n\n=head1 BUGS, SUPPORT, CONTRIBUTING, DISCUSS\n\n=for html \u003ca href=\"https://travis-ci.org/kberov/Slovo\"\u003e\u003cimg src=\"https://travis-ci.org/kberov/Slovo.svg?branch=master\"\u003e\u003c/a\u003e\n\nTo report a bug, please create issues at\nL\u003cGitHub|https://github.com/kberov/Slovo/issues\u003e, fork the project and make\npull requests.\n\n\n=head1 AUTHOR\n\n    Красимир Беров\n    CPAN ID: BEROV\n    berov на cpan точка org\n    http://i-can.eu\n\n=head1 CONTRIBUTORS\n\nOrdered by time of first commit.\n\n=over\n\n=item * MANWAR (Mohammad S Anwar)\n\n=item * KABANOID (Mikhail Katasonov)\n\n=item * 0xAF (Stanislav Lechev)\n\n=back\n\n=head1 COPYRIGHT\n\nThis is free software, licensed under:\n\n  The Artistic License 2.0 (GPL Compatible)\n\nThe full text of the license can be found in the\nLICENSE file included with this module.\n\nThis distribution contains other free software which belongs to their\nrespective authors.\n\n=head1 TODO\n\n=over\n\n=item * Stop adding features. Stabilize what we have.\n\n=item * Gradually replace L\u003cMUI CSS|https://www.muicss.com/\u003e with L\u003cChota\nCSS|https://jenil.github.io/chota/\u003e - site part is done.\n\n=item * Considerably improve the Adminiastration UI - now it is quite\nsimplistic. Use ES6 directly as per L\u003cbrowsers compatibility\ntable|https://kangax.github.io/compat-table/es6/\u003e\n\n=item * Consider using L\u003cMithril|https://github.com/MithrilJS/mithril.js\u003e or\nL\u003cVue.js|https://vuejs.org/\u003e or something light as frontend framework for\nbuilding UI. We already use jQuery distributed with the Mojolicious distro.\n\n=back\n\n=head1 SEE ALSO\n\nL\u003cSlovo::Plugin::TagHelpers\u003e, L\u003cSlovo::Plugin::DefaultHelpers\u003e,\nL\u003cSlovo::Validator\u003e, L\u003cMojolicious\u003e, L\u003cMojolicious::Guides\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkberov%2Fslovo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkberov%2Fslovo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkberov%2Fslovo/lists"}