Full Code of fdv/typo for AI

master 62b9c0233a18 cached
275 files
621.7 KB
178.4k tokens
198 symbols
1 requests
Download .txt
Showing preview only (690K chars total). Download the full file or copy to clipboard to get everything.
Repository: fdv/typo
Branch: master
Commit: 62b9c0233a18
Files: 275
Total size: 621.7 KB

Directory structure:
gitextract_oagz7ovf/

├── .erb-lint.yml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       └── ruby.yml
├── .gitignore
├── .hound.yml
├── .metrics
├── .reek.yml
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── TODO.txt
├── app/
│   ├── assets/
│   │   ├── config/
│   │   │   └── manifest.js
│   │   └── images/
│   │       └── .keep
│   ├── controllers/
│   │   └── application_controller.rb
│   ├── helpers/
│   │   └── theme_helper.rb
│   ├── mailers/
│   │   └── application_mailer.rb
│   ├── models/
│   │   ├── application_record.rb
│   │   ├── authors_sidebar.rb
│   │   ├── concerns/
│   │   │   └── .keep
│   │   ├── livesearch_sidebar.rb
│   │   ├── notes_sidebar.rb
│   │   ├── popular_sidebar.rb
│   │   └── xml_sidebar.rb
│   └── views/
│       ├── authors_sidebar/
│       │   └── _content.html.erb
│       ├── livesearch_sidebar/
│       │   └── _content.html.erb
│       ├── notes_sidebar/
│       │   └── _content.html.erb
│       ├── popular_sidebar/
│       │   └── _content.html.erb
│       └── xml_sidebar/
│           └── _content.html.erb
├── bin/
│   ├── bundle
│   ├── i18n-tasks
│   ├── rails
│   ├── rake
│   ├── rspec
│   ├── setup
│   ├── update
│   └── yarn
├── config/
│   ├── application.rb
│   ├── boot.rb
│   ├── cable.yml
│   ├── database.yml.mysql
│   ├── database.yml.postgresql
│   ├── environment.rb
│   ├── environments/
│   │   ├── development.rb
│   │   ├── production.rb
│   │   └── test.rb
│   ├── filemanager.yml
│   ├── i18n-tasks.yml
│   ├── initializers/
│   │   ├── application_controller_renderer.rb
│   │   ├── assets.rb
│   │   ├── backtrace_silencers.rb
│   │   ├── carrierwave.rb
│   │   ├── content_security_policy.rb
│   │   ├── cookies_serializer.rb
│   │   ├── filter_parameter_logging.rb
│   │   ├── flickr.rb
│   │   ├── inflections.rb
│   │   ├── mime_types.rb
│   │   ├── new_framework_defaults_7_1.rb
│   │   ├── non_digest_assets.rb
│   │   ├── permissions_policy.rb
│   │   ├── rack_attack.rb
│   │   ├── recaptcha.rb
│   │   ├── session_store.rb
│   │   └── wrap_parameters.rb
│   ├── locales/
│   │   ├── ar.yml
│   │   ├── da.yml
│   │   ├── de.yml
│   │   ├── en.yml
│   │   ├── es-MX.yml
│   │   ├── fr.yml
│   │   ├── he.yml
│   │   ├── it.yml
│   │   ├── ja.yml
│   │   ├── lt.yml
│   │   ├── nb.yml
│   │   ├── nl.yml
│   │   ├── pl.yml
│   │   ├── pt-BR.yml
│   │   ├── ro.yml
│   │   ├── ru.yml
│   │   ├── sidebars.ar.yml
│   │   ├── sidebars.da.yml
│   │   ├── sidebars.de.yml
│   │   ├── sidebars.en.yml
│   │   ├── sidebars.es-MX.yml
│   │   ├── sidebars.fr.yml
│   │   ├── sidebars.he.yml
│   │   ├── sidebars.it.yml
│   │   ├── sidebars.ja.yml
│   │   ├── sidebars.lt.yml
│   │   ├── sidebars.nb.yml
│   │   ├── sidebars.nl.yml
│   │   ├── sidebars.pl.yml
│   │   ├── sidebars.pt-BR.yml
│   │   ├── sidebars.ro.yml
│   │   ├── sidebars.ru.yml
│   │   ├── sidebars.zh-CN.yml
│   │   ├── sidebars.zh-TW.yml
│   │   ├── zh-CN.yml
│   │   └── zh-TW.yml
│   ├── mail.yml.example
│   ├── puma.rb
│   ├── routes.rb
│   ├── secrets.yml
│   ├── spring.rb
│   └── storage.yml
├── config.ru
├── db/
│   ├── converters/
│   │   ├── README
│   │   ├── blogger.rb
│   │   ├── feed.rb
│   │   └── rss.rb
│   ├── migrate/
│   │   ├── 113_initial_schema.publify_core_engine.rb
│   │   ├── 114_fixes_buggy_articles_and_notes.publify_core_engine.rb
│   │   ├── 115_drops_categories_for_tags.publify_core_engine.rb
│   │   ├── 20150207131657_add_missing_indexes.publify_core_engine.rb
│   │   ├── 20150807134129_simplify_redirect_relations.publify_core_engine.rb
│   │   ├── 20150808052637_add_blog_ids.publify_core_engine.rb
│   │   ├── 20150808191127_add_blog_id_to_redirects.publify_core_engine.rb
│   │   ├── 20150810094754_add_blog_id_to_tags.publify_core_engine.rb
│   │   ├── 20160108111120_add_devise_to_users.publify_core_engine.rb
│   │   ├── 20160108184201_move_last_connection_to_last_sign_in_at.publify_core_engine.rb
│   │   ├── 20160110094906_remove_profiles_rights.publify_core_engine.rb
│   │   ├── 20160605103918_replace_profile_id_with_string.publify_core_engine.rb
│   │   ├── 20160605154632_remove_profiles.publify_core_engine.rb
│   │   ├── 20160701061851_demand_blog_id_on_contents.publify_core_engine.rb
│   │   ├── 20160701062604_add_blog_id_to_resources.publify_core_engine.rb
│   │   ├── 20161030121548_add_sessions_table.rb
│   │   ├── 20170528093428_move_resources_to_content.publify_core_engine.rb
│   │   ├── 20170528120220_move_tags_to_content.publify_core_engine.rb
│   │   ├── 20170530063901_remove_separate_published_flag.publify_core_engine.rb
│   │   ├── 20170605103539_remove_extra_state_columns_from_feedback.publify_core_engine.rb
│   │   ├── 20170702105518_remove_published_at_from_feedback.publify_core_engine.rb
│   │   ├── 20190210121314_add_text_filter_name_fields.publify_core_engine.rb
│   │   ├── 20190210121315_move_text_filter_to_name.publify_core_engine.rb
│   │   ├── 20190210121316_remove_text_filter_ids.publify_core_engine.rb
│   │   ├── 20190210121317_remove_text_filters.publify_core_engine.rb
│   │   ├── 20200413141133_add_unique_indexes.publify_core_engine.rb
│   │   ├── 20221007091118_remove_table_sitealizer.publify_core_engine.rb
│   │   ├── 20221010170801_remove_page_caches_table.publify_core_engine.rb
│   │   └── 20221012164027_remove_itunes_fields_from_resources.publify_core_engine.rb
│   ├── schema.rb
│   └── seeds.rb
├── doc/
│   ├── CACHE.SETUP.README
│   └── dependency_decisions.yml
├── lib/
│   ├── generators/
│   │   └── sidebar/
│   │       ├── USAGE
│   │       ├── sidebar_generator.rb
│   │       └── templates/
│   │           ├── _content.html.erb.erb
│   │           ├── model_spec.rb.erb
│   │           └── sidebar.rb.erb
│   ├── publify_app/
│   │   └── textfilter/
│   │       ├── flickr.rb
│   │       ├── htmlfilter.rb
│   │       └── lightbox.rb
│   ├── publify_plugins/
│   │   ├── avatar_plugin.rb
│   │   └── gravatar.rb
│   └── tasks/
│       ├── i18n.rake
│       └── rubocop.rake
├── log/
│   └── .keep
├── public/
│   ├── 404.html
│   ├── 422.html
│   └── 500.html
├── spec/
│   ├── controllers/
│   │   ├── articles_controller_spec.rb
│   │   ├── feedback_controller_spec.rb
│   │   ├── tags_controller_spec.rb
│   │   └── xml_controller_spec.rb
│   ├── features/
│   │   └── switch_theme_spec.rb
│   ├── lib/
│   │   ├── publify_plugins/
│   │   │   └── gravatar_spec.rb
│   │   ├── publify_textfilter_flickr_spec.rb
│   │   ├── publify_textfilter_lightbox_spec.rb
│   │   └── text_filter_plugin_spec.rb
│   ├── models/
│   │   ├── authors_sidebar_spec.rb
│   │   ├── notes_sidebar_spec.rb
│   │   ├── popular_sidebar_spec.rb
│   │   ├── sidebar_registry_spec.rb
│   │   └── xml_sidebar_spec.rb
│   ├── rails_helper.rb
│   ├── spec_helper.rb
│   └── views/
│       ├── comments/
│       │   └── html_sanitization_spec.rb
│       ├── layouts/
│       │   └── default_spec.rb
│       └── xml_sidebar/
│           └── _content.html.erb_spec.rb
├── themes/
│   └── bootstrap-2/
│       ├── about.markdown
│       ├── javascripts/
│       │   └── bootstrap.js
│       ├── less/
│       │   ├── .csscomb.json
│       │   ├── .csslintrc
│       │   ├── alerts.less
│       │   ├── badges.less
│       │   ├── bootstrap.less
│       │   ├── breadcrumbs.less
│       │   ├── button-groups.less
│       │   ├── buttons.less
│       │   ├── carousel.less
│       │   ├── close.less
│       │   ├── code.less
│       │   ├── component-animations.less
│       │   ├── dropdowns.less
│       │   ├── forms.less
│       │   ├── glyphicons.less
│       │   ├── grid.less
│       │   ├── input-groups.less
│       │   ├── jumbotron.less
│       │   ├── labels.less
│       │   ├── list-group.less
│       │   ├── media.less
│       │   ├── mixins/
│       │   │   ├── alerts.less
│       │   │   ├── background-variant.less
│       │   │   ├── border-radius.less
│       │   │   ├── buttons.less
│       │   │   ├── center-block.less
│       │   │   ├── clearfix.less
│       │   │   ├── forms.less
│       │   │   ├── gradients.less
│       │   │   ├── grid-framework.less
│       │   │   ├── grid.less
│       │   │   ├── hide-text.less
│       │   │   ├── image.less
│       │   │   ├── labels.less
│       │   │   ├── list-group.less
│       │   │   ├── nav-divider.less
│       │   │   ├── nav-vertical-align.less
│       │   │   ├── opacity.less
│       │   │   ├── pagination.less
│       │   │   ├── panels.less
│       │   │   ├── progress-bar.less
│       │   │   ├── reset-filter.less
│       │   │   ├── resize.less
│       │   │   ├── responsive-visibility.less
│       │   │   ├── size.less
│       │   │   ├── tab-focus.less
│       │   │   ├── table-row.less
│       │   │   ├── text-emphasis.less
│       │   │   ├── text-overflow.less
│       │   │   └── vendor-prefixes.less
│       │   ├── mixins.less
│       │   ├── modals.less
│       │   ├── navbar.less
│       │   ├── navs.less
│       │   ├── normalize.less
│       │   ├── pager.less
│       │   ├── pagination.less
│       │   ├── panels.less
│       │   ├── popovers.less
│       │   ├── print.less
│       │   ├── progress-bars.less
│       │   ├── responsive-embed.less
│       │   ├── responsive-utilities.less
│       │   ├── scaffolding.less
│       │   ├── tables.less
│       │   ├── theme.less
│       │   ├── thumbnails.less
│       │   ├── tooltip.less
│       │   ├── type.less
│       │   ├── utilities.less
│       │   ├── variables.less
│       │   └── wells.less
│       ├── stylesheets/
│       │   ├── bootstrap.css
│       │   └── style.css
│       └── views/
│           ├── articles/
│           │   ├── _article.html.erb
│           │   ├── _comment_counter.html.erb
│           │   ├── _comment_form.html.erb
│           │   ├── _comment_list.html.erb
│           │   ├── _meta.html.erb
│           │   ├── _trackback.html.erb
│           │   ├── index.html.erb
│           │   ├── read.html.erb
│           │   ├── search.html.erb
│           │   └── view_page.html.erb
│           ├── comments/
│           │   └── _comment.html.erb
│           ├── layouts/
│           │   └── default.html.erb
│           └── tags/
│               └── show.html.erb
└── vendor/
    └── .keep

================================================
FILE CONTENTS
================================================

================================================
FILE: .erb-lint.yml
================================================
---
linters:
  ErbSafety:
    enabled: true
  Rubocop:
    enabled: true
    rubocop_config:
      inherit_from:
        - .rubocop.yml
      Layout/InitialIndentation:
        Enabled: false
      Layout/TrailingBlankLines:
        Enabled: false
      Layout/TrailingWhitespace:
        Enabled: false
      Naming/FileName:
        Enabled: false
      Style/FrozenStringLiteralComment:
        Enabled: false
      Layout/LineLength:
        Enabled: true
      Lint/UselessAssignment:
        Enabled: false
      Rails/OutputSafety:
        Enabled: false


================================================
FILE: .github/dependabot.yml
================================================
# Documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
  - package-ecosystem: "bundler"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 15
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "monthly"


================================================
FILE: .github/workflows/ruby.yml
================================================
# This workflow will download a prebuilt Ruby version, install dependencies and
# run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: CI

"on":
  push:
    branches:
      - master
      - 10-0-stable
      - 9-2-stable
  pull_request:
    branches:
      - master
      - 10-0-stable
      - 9-2-stable
  workflow_dispatch:

jobs:
  test-postgresql:
    name: "Test on PostgreSQL"

    runs-on: ubuntu-latest

    strategy:
      matrix:
        ruby: ["3.2", "3.3", "3.4"]

    services:
      postgres:
        image: postgres:latest
        env:
          POSTGRES_PASSWORD: postgres
        ports: ['5432:5432']

    steps:
      - uses: actions/checkout@v6
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true
      - name: Database Configuration
        run: cp config/database.yml.postgresql config/database.yml
      - name: Migrate database
        run: bundle exec rake db:create db:migrate
      - name: Run tests
        run: bundle exec rake

  test-mysql:
    name: "Test on MySQL"

    runs-on: ubuntu-latest

    strategy:
      matrix:
        ruby: ["3.2", "3.3", "3.4"]

    services:
      mysql:
        image: mysql:latest
        env:
          MYSQL_ROOT_PASSWORD: mysql
        ports: ['3306:3306']

    steps:
      - uses: actions/checkout@v6
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true
      - name: Database Configuration
        run: cp config/database.yml.mysql config/database.yml
      - name: Migrate database
        run: bundle exec rake db:create db:migrate
      - name: Run tests
        run: bundle exec rake

  test-sqlite:
    name: "Test on SQLite"

    runs-on: ubuntu-latest

    strategy:
      matrix:
        ruby: ["3.2", "3.3", "3.4"]

    steps:
      - uses: actions/checkout@v6
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true
      - name: Database Configuration
        run: cp config/database.yml.sqlite config/database.yml
      - name: Migrate database
        run: bundle exec rake db:create db:migrate
      - name: Run tests
        run: bundle exec rake

  lint:
    name: "Linting"

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2
          bundler-cache: true
      - name: Run lint task
        run: bundle exec rake lint


================================================
FILE: .gitignore
================================================
config/database.yml
config/mail.yml
config/timezone.yml
*.log
*~
db/db*
db/*.sqlite*
.*.swp
.*.swo
.DS_Store
.byebug_history
installer/rails_installer.yml
/public/files
/public/images/theme
/public/javascripts/ckeditor/config.js
/public/javascripts/ckeditor/config.bak
/public/javascripts/all.js
/public/robots.txt
/public/stylesheets/theme
/public/stylesheets/all.css
/publify_core/spec/dummy/public/files
tmp/*
coverage/
nbproject
public/cache/*
Gemfile.lock
.rbenv-version
.ruby-version
.env
.bundle/
.sass-cache/
/vendor/bundle
/themes/*
!/themes/bootstrap-2
!/themes/plain
gems/
node_modules/
spec/examples.txt


================================================
FILE: .hound.yml
================================================
ruby:
  config_file: .rubocop.yml


================================================
FILE: .metrics
================================================
MetricFu::Configuration.run do |config|
  config.rcov[:test_files] = 'spec/**/*_spec.rb'
  config.rcov[:rcov_opts] << '-Ispec'
  config.syntax_highlighting = false
end



================================================
FILE: .reek.yml
================================================
exclude_paths:
  - 'db/migrate'
  - 'publify_amazon_sidebar/spec/dummy/db/migrate'
  - 'publify_textfilter_code/spec/dummy/db/migrate'
  - 'publify_core/db/migrate'
directories:
  "app/controllers":
    IrresponsibleModule:
      enabled: false
    NestedIterators:
      max_allowed_nesting: 2
    UnusedPrivateMethod:
      enabled: false
  "app/helpers":
    IrresponsibleModule:
      enabled: false
    UtilityFunction:
      enabled: false
  "app/models":
    IrresponsibleModule:
      enabled: false


================================================
FILE: .rspec
================================================
--color
--require spec_helper


================================================
FILE: .rubocop.yml
================================================
inherit_from: .rubocop_todo.yml

inherit_mode:
  merge:
    - Exclude

plugins:
  - rubocop-capybara
  - rubocop-factory_bot
  - rubocop-performance
  - rubocop-rails
  - rubocop-rspec
  - rubocop-rspec_rails

AllCops:
  Exclude:
    - 'bin/*'
    - 'db/converters/*.rb'
    - 'db/schema.rb'
  NewCops: enable
  TargetRubyVersion: 3.2
  TargetRailsVersion: 7.1

Rails:
  Enabled: true

# We have duplication due to extra logic in the Gemfile
Bundler/DuplicatedGem:
  Enabled: false

# Require tests to specify whether an element is a link or a button
Capybara/ClickLinkOrButtonStyle:
  EnforcedStyle: strict

# Match style of regular expectations
Capybara/RSpec/NegationMatcher:
  EnforcedStyle: not_to

# Make BeginEndAlignment behavior match EndAlignment
Layout/BeginEndAlignment:
  EnforcedStyleAlignWith: begin

# Spaces in strings with line continuations go at the beginning of the line.
Layout/LineContinuationLeadingSpace:
  EnforcedStyle: leading

# Lenient line length that fits in pull requests
Layout/LineLength:
  Max: 92

Layout/MultilineMethodCallBraceLayout:
  EnforcedStyle: same_line

# Multi-line operations should be simply indented. Aligning them makes it even
# harder to keep a sane line length.
Layout/MultilineMethodCallIndentation:
  EnforcedStyle: indented

# Multi-line operations should be simply indented. Aligning them makes it even
# harder to keep a sane line length.
Layout/MultilineOperationIndentation:
  EnforcedStyle: indented

# Uniform block layout
Layout/SpaceBeforeBlockBraces:
  EnforcedStyleForEmptyBraces: space

# Assume the programmer knows how bracketed block syntax works
Lint/AmbiguousBlockAssociation:
  Enabled: false

# Allow if (foo = get_foo) style
Lint/AssignmentInCondition:
  AllowSafeAssignment: true

# Suppress BlockLength for some files:
# - Spec describe blocks can be any length
# - Environment configuration blocks can be any length
Metrics/BlockLength:
  Exclude:
    - 'spec/**/*'
    - 'config/environments/*'

# Initial schema has a very large change method
Metrics/MethodLength:
  Exclude:
    - 'db/migrate/113_initial_schema.publify_core_engine.rb'

Performance/StartWith:
  AutoCorrect: true

Performance/EndWith:
  AutoCorrect: true

# Migrations should not use ApplicationRecord
Rails/ApplicationRecord:
  Exclude:
    - 'db/migrate/*'

# This cop has issues and is too database-specific
Rails/BulkChangeTable:
  Enabled: false

# These tasks do not need environment
Rails/RakeEnvironment:
  Exclude:
    - 'lib/tasks/i18n.rake'
    - 'lib/tasks/rspec.rake'
    - 'lib/tasks/rubocop.rake'

# Migrations should not do validations in general?
Rails/SkipsModelValidations:
  Exclude:
    - 'db/migrate/*'

# Spec type inference is disabled, so this cop must be disabled too.
RSpecRails/InferredSpecType:
  Enabled: false

# Allow the use of 'and' 'or' in control structures.
Style/AndOr:
  EnforcedStyle: conditionals

Style/ClassAndModuleChildren:
  Enabled: false

Style/CollectionMethods:
  Enabled: true

# Documenting all classes is not common in Rails projects.
Style/Documentation:
  Enabled: false

# This cop doesn't detect use of break yet
Style/EachWithObject:
  Enabled: false

# Allows format strings with: format, sprintf or percent.
Style/FormatString:
  Enabled: false

# Require at least two dependent lines before suggesting a guard clause
Style/GuardClause:
  MinBodyLength: 2

# TODO: Re-enable?
Style/NumericPredicate:
  Enabled: false

# Not all objects that implement #size implement #empty?
Style/ZeroLengthPredicate:
  Enabled: false

# Restore previous RuboCop defaults
Style/PercentLiteralDelimiters:
  PreferredDelimiters:
    '%W': ()
    '%w': ()

# Always use raise to raise exceptions
Style/SignalException:
  EnforcedStyle: only_raise

# Allow meaningful names for single-line reduce etc.
Style/SingleLineBlockParams:
  Enabled: false

# Prefer not to commit to need to interpolate
Style/StringLiterals:
  EnforcedStyle: double_quotes

# Be consistent with non-interpolated strings
Style/StringLiteralsInInterpolation:
  EnforcedStyle: double_quotes

# Prefer symbols to look like symbols
Style/SymbolArray:
  EnforcedStyle: brackets

# Allow small arrays of words with quotes
Style/WordArray:
  MinSize: 4


================================================
FILE: .rubocop_todo.yml
================================================
# This configuration was generated by
# `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp`
# using RuboCop version 1.80.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
# URISchemes: http, https
Layout/LineLength:
  Exclude:
    - 'config/initializers/new_framework_defaults_7_1.rb'

# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
  Max: 157

# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
  Max: 177

# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity:
  Max: 19

# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
  Max: 48

# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/PerceivedComplexity:
  Max: 22

# Configuration parameters: Prefixes, AllowedPatterns.
# Prefixes: when, with, without
RSpec/ContextWording:
  Exclude:
    - 'spec/views/xml_sidebar/_content.html.erb_spec.rb'

# Configuration parameters: CountAsOne.
RSpec/ExampleLength:
  Max: 14

# Configuration parameters: AssignmentOnly.
RSpec/InstanceVariable:
  Exclude:
    - 'spec/controllers/tags_controller_spec.rb'
    - 'spec/controllers/xml_controller_spec.rb'
    - 'spec/views/comments/html_sanitization_spec.rb'
    - 'spec/views/layouts/default_spec.rb'
    - 'spec/views/xml_sidebar/_content.html.erb_spec.rb'

RSpec/LetSetup:
  Exclude:
    - 'spec/controllers/articles_controller_spec.rb'
    - 'spec/controllers/feedback_controller_spec.rb'

RSpec/MultipleExpectations:
  Max: 10

# Configuration parameters: AllowedGroups.
RSpec/NestedGroups:
  Max: 5

# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
RSpec/VerifiedDoubles:
  Exclude:
    - 'spec/lib/publify_textfilter_flickr_spec.rb'
    - 'spec/lib/publify_textfilter_lightbox_spec.rb'

Rails/CreateTableWithTimestamps:
  Exclude:
    - 'db/migrate/113_initial_schema.publify_core_engine.rb'
    - 'db/migrate/20150807134129_simplify_redirect_relations.publify_core_engine.rb'
    - 'db/migrate/20160605154632_remove_profiles.publify_core_engine.rb'
    - 'db/migrate/20190210121317_remove_text_filters.publify_core_engine.rb'
    - 'db/migrate/20221010170801_remove_page_caches_table.publify_core_engine.rb'

Rails/ThreeStateBooleanColumn:
  Exclude:
    - 'db/migrate/113_initial_schema.publify_core_engine.rb'

Security/Eval:
  Exclude:
    - 'Gemfile'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
Style/GuardClause:
  Exclude:
    - 'db/migrate/20150808191127_add_blog_id_to_redirects.publify_core_engine.rb'
    - 'db/migrate/20150810094754_add_blog_id_to_tags.publify_core_engine.rb'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
  Exclude:
    - 'db/migrate/20150808052637_add_blog_ids.publify_core_engine.rb'
    - 'lib/publify_textfilter_flickr.rb'


================================================
FILE: CHANGELOG.md
================================================
# Changelog

See the changelogs for the individual engines for more details for releases 9.0
and up.

## 10.0.1 / 2024-06-28

This is a bug fix and security release.

* Update the dependency on `publify_core` from `~> 10.0.0` to `~> 10.0.2`. This
  includes the following two security updates:

   * Safely link target URLs for Redirects in admin ([publify_core#148] by [mvz])
   * Upgrade jquery-ui-rails to version 7.0 ([publify_core#149] by [mvz])

  See the `publify_core` changelog for further details.

* Update various other dependencies (various pull requests)

[publify_core#148]: https://github.com/publify/publify_core/pull/148
[publify_core#149]: https://github.com/publify/publify_core/pull/149
[mvz]: https://github.com/mvz

## 10.0.0 / 2023-06-25

This major release updates Publify to Rails 6.1 in preparation of the upgrade
to Rails 7.0. It also updates the set of supported Rubies to 2.7 through 3.2.

### Security-related changes

* Require at least Rails 6.1.6.1 [#1068](https://github.com/publify/publify/pull/1068)
* Update puma dependency to require at least version 5.6.4 [#1064](https://github.com/publify/publify/pull/1064)

### Updated dependencies

* Upgrade to Rails 6.1
  [#987](https://github.com/publify/publify/pull/987),
  [#1014](https://github.com/publify/publify/pull/1014),
* Support only Ruby 2.7 through 3.2
  [#1013](https://github.com/publify/publify/pull/1013)
  [#1041](https://github.com/publify/publify/pull/1041)
  [#1115](https://github.com/publify/publify/pull/1115)
  [#1120](https://github.com/publify/publify/pull/1120)
* Update various other dependencies (various pull requests)

### Breaking changes

* Remove support for Textile as a text format [#1001](https://github.com/publify/publify/pull/1001)
* Require email uniqueness to be case-insensitive [#1080](https://github.com/publify/publify/pull/1080)

### Other changes

* Add arabic language to the project [#1060](https://github.com/publify/publify/pull/1060)
  by [ahmedhamid13](https://github.com/ahmedhamid13)
* Fix article search rendering in bootstrap theme [#1101](https://github.com/publify/publify/pull/1101)
* Remove local copies of engines and use external ones instead [#1099](https://github.com/publify/publify/pull/1099)
* Require AWS configuration to be present when choosing AWS storage [#1082](https://github.com/publify/publify/pull/1082)
* Replace deprecated non-digest-assets configuration [#1019](https://github.com/publify/publify/pull/1019)

### Internal changes

* Remove `sitealizer` table [#1089](https://github.com/publify/publify/pull/1089)
  by [SupriyaMedankar](https://github.com/SupriyaMedankar)
* Remove itunes fields from resources [#1092](https://github.com/publify/publify/pull/1092)
  by [SupriyaMedankar](https://github.com/SupriyaMedankar)
* Remove `page_caches` table [#1090](https://github.com/publify/publify/pull/1090)
  by [SupriyaMedankar](https://github.com/SupriyaMedankar)
* Remove `dynamic_form` dependency [#991](https://github.com/publify/publify/pull/991)

See also the changelogs for
[publify_core](https://github.com/publify/publify_core/blob/v10.0.0/CHANGELOG.md#1000--2023-06-25),
[publify_textfilter_code](https://github.com/publify/publify_textfilter_code/blob/v10.0.0/CHANGELOG.md#1000--2023-06-25)
and
[publify_amazon_sidebar](https://github.com/publify/publify_amazon_sidebar/blob/v10.0.0/CHANGELOG.md#1000--2023-06-25).

## 9.2.10 / 2023-01-08

This release fixes several security issues:

* Bump Rails version to 5.2.8.1 [#1070](https://github.com/publify/publify/pull/1070)
* Limit length of settings values [#1072](https://github.com/publify/publify/pull/1072)
* Require login to stay unique when updating a User [#1073](https://github.com/publify/publify/pull/1073)
* Validate lengths of string attributes [#1077](https://github.com/publify/publify/pull/1077)
* Strip EXIF data from resource uploads [#1078](https://github.com/publify/publify/pull/1078)
* Require user passwords to be strong [#1086](https://github.com/publify/publify/pull/1086)

## 9.2.9 / 2022-05-22

This release fixes two security issues:

* Fix admin article access control [#1065](https://github.com/publify/publify/pull/1065)
* Refuse html files as resources even if declared to be plain text [#1066](https://github.com/publify/publify/pull/1066)

## 9.2.8 / 2022-05-14

This release fixes several security issues:

* Disallow comments on draft articles [#1048](https://github.com/publify/publify/pull/1048)
* Disallow images in comments [#1054](https://github.com/publify/publify/pull/1054)
* Hide bodies of password-protected articles in search results [#1057](https://github.com/publify/publify/pull/1057)
* Do not create article meta description for password-protected articles [#1061](https://github.com/publify/publify/pull/1061)

Additionally, it includes the following changes:

* Clean up Feedback validation [#1051](https://github.com/publify/publify/pull/1051)
* Bump mimimum puma and Rails versions [#1050](https://github.com/publify/publify/pull/1050)
* Fix password reset process [#1055](https://github.com/publify/publify/pull/1055)
* Fix password protected article reveal [#1049](https://github.com/publify/publify/pull/1049)
* Provide correct `article_id` input in bulkops form [#1058](https://github.com/publify/publify/pull/1058)
* Bump minimum required Rails version [#1062](https://github.com/publify/publify/pull/1062)

## 9.2.7 / 2022-02-07

This release fixes a security issue:

* Fix setting the article password from the Admin [#1044](https://github.com/publify/publify/pull/1044)

## 9.2.6 / 2022-01-07

This release fixes a minor security issue:

* Rate-limit Devise logins and password resets

Additionally, it includes the following change:

* Add documentation about use of the media library

## 9.2.5 / 2021-10-11

This release fixes several security issues:

* Force session cookie to be secure in production
* Block ability to switch themes using a GET request; use a POST instead
* Disallow user self-registration rather than hiding it
* Let the browser not cache admin pages
* Limit the set of allowed mime types for uploaded media
* Limit allowed HTML in articles, pages and notes

Additionally, it includes the following changes:

* Fix resource size display in admin resource list
* Trigger download of media in the Media Library in admin instead of displaying
  them directly

## 9.2.4 / 2021-10-02

* Require at least version 1.12.5 of nokogiri to avoid a security issue
* Drop support for Ruby 2.4 since it is incompatible with nokogiri 1.12.5

## 9.2.3 / 2021-05-22

* Bump Rails dependency to 5.2.6
* Replace mimemagic with marcel [#996](https://github.com/publify/publify/pull/996)

## 9.2.2 / 2021-03-21

* Fix the `publify:textile_to_markdown` task. This task failed on feedback and
  pages.

## 9.2.1 / 2021-03-20

This release updates dependencies due to security issues.

* Bump minimum Rails version to 5.2.4.5
* Update `activerecord-session_store` dependency to 2.0.0

## 9.2.0 / 2021-01-17

### Breaking changes

* Upgrade to Rails 5.2 (mvz)
* Drop support for custom mail.yml configuration. Mail settings should now be
  configured in config/environments/production.rb (mvz)
* Drop support for custom timezone.yml configuration. If relevant, the timezone
  can be set in config/application.rb (mvz)
* Drop support for Ruby 2.2 and 2.3 (mvz)
* Drop support for humans.txt (mvz)
* Deprecate use of Textile. The admin will warn about any content that uses
  Textile formatting. A task has been added to convert this content to
  Markdown. The next release of Publify will drop Textile support entirely
  (mvz)

### Other changes

* Fix comment preview (mvz)
* Fix gravatar request URL (mvz)
* Fix various issues with the bootstrap-2 theme (mvz)
* Add support for Ruby 2.7 (mvz)
* Update dependencies (mvz)
* Allow rake tasks to be loaded when only production gems are present (mvz)

## 9.1.0 / 2018-04-19

* Upgrade to Rails 5.1 (mvz)
* Update translations (xy2z, gergu)
* Remove outdated converters (mvz)
* Fix a bunch of issues (e-tobi)
* Fix google analytics tag rendering (mvz)

## 9.0.1

* Use at least Rails 5.0.4 (mvz)
* Update Russian translations (biggless)

## 9.0.0

### Breaking/large changes

* Use Rails' default method of setting `secret_key_base` in production: Through
  an environment variable. This means you will have to update your production
  environment so this variable is actually set (whithajess)
* Break out Publify functionality into several engine gems (mvz)
* Update to Rails 5.0

### Other changes

* Hide spinner on `ajax:complete` for article search (nathanallen)
* Fix layout for log in form (mvz)
* Fix spinner for sidebar editor (mvz)
* Update copyright information and contributor list (mvz)
* Fix XML sidebar (mvz)

## 8.3.3

* Fix Devise error during sign-in (mvz)
* Protect from forgery on all actions (mvz)
* Have Devise be paranoid by default (mvz)
* Fix resource upload and properly check mime types (mvz)
* Store session in the database to prevent session hijacking (mvz)
* Correctly escape blog name in devise view (mvz)

## 8.3.2

* Replace deprecated count-with-conditions (mvz)
* Loosen/update dependencies (mvz)
* Fix google sitemap (mvz)
* Restore theme helper loading (mvz)
* Fix password edit form (jetware)

## 8.3.1

* Fix live search (mvz)
* Introduce `SidebarRegistry` to avoid need to preload all sidebars (mvz)
* Avoid use of `String#html_safe` (mvz)
* Fix several cases of double-escaped HTML (mvz)
* Avoid ambiguous field reference in feedback scopes (apsheronets)
* Remove spurious error message when starting a new article (mvz)
* Replace bundled bootstrap with bootstrap-sass gem (mvz)
* Link Resource directly to Blog in order to make upload of images to media
  library work again (mvz)
* Fix comment order and other feedback scopes (mvz)
* Fix autosave (mvz)
* Improve russian translation (apsheronets)
* Fix note publication date entry (mvz)
* Ensure settings update flash has the correct language (mvz)

## 8.3.0

### Breaking/large changes

* Make Publify multiblog-ready (mvz)
* Replace custom Publify authentication system with Devise (mvz)
* Replace custom Publify authorization system with CanCanCan (mvz)
* Remove Profile model (mvz)
* Remove long-deprecated `view_root` method for sidebars (mvz)
* Provide registration mechanism for themes, allowing them to be stored
  anywhere (mvz)

### Other changes

* Update Akismet API calls (drakontia)
* Remove old Rails patches (mvz)
* Update dependency on Rails to 4.2.5 (mvz)
* Fix issues with missing translations and HTML escaping errors
* Clean up helpers and partials (mvz)
* Add specs to check for double HTML escaping and fix errors (mvz)
* Load JavaScript asynchronously (mvz)
* Remove own copies of jQuery files (mvz)
* Fixed rake db:seed error (sachiotomita)
* Add check for translation keys and fix errors (mvz)
* Introduce RuboCop to automatically check style errors (mvz)
* Fix many RuboCop offenses (mvz)
* Update Travis config to stop testing on MRI 2.0.0, start testing on 2.3 (mvz)
* Remove unused `#reset_local_cache` method (mvz)
* Load JavaScript asynchronously in supporting layouts (mvz)
* Fix translations for labels in Devise views (mvz)
* Update dependencies (mvz)
* Clean up textfilter code (mvz)
* Test and improve setup process (mvz)
* Update translations for Dutch (mvz)
* Fix syntax error in mailer template (ttibau)
* Ensure development dependencies don't break the build (mvz)
* Fix spelling (mvz)
* Use only the parts from fog needed by Publify (mvz)
* Upgrade to mysql2 0.4.x (ttibau)
* Remove unused code (mvz)
* Load JavaScript asynchronously only in production (priit)
* Run tests as a sub-URL installation by default (mvz)
* Ensure new sidebars have `blog_id` set (mvz)
* Fix bug in article attachment saving (mvz)
* Fix broken authors sidebar (mvz)

## 8.2.0

### Breaking/large changes

* Update rails, jquery-rails and web-console to avoid security vulnerabilities (mvz)
* Update dependencies (mvz, fdv)
* Update to Rails 4.2 (mvz)
* Roll up migrations up to 113 according to our
  [upgrade policy](https://github.com/publify/publify/wiki/Upgrading).
  You must now first upgrade to at least version 7 before upgrading to the
  latest version. (mvz)
* Replace default theme bootstrap with bootstrap-2 (fdv)
* Add a Plain theme demonstrating the use of Publify's default templates (mvz)
* Use HTML instead of XHTML in views (fdv)

### Other changes

* Restore hiding of automatic redirects from admin interface (mvz)
* Fix broken stylesheet link in bootstrap2 theme (hmallett)
* Create a fonts folder for themes, to replicate the Rails default (hmallet)
* Update rubocop todo and use rubocop in travis (whithajess)
* Autocorrect rubocop offenses (mvz)
* Support Ruby 2.2 (mvz)
* Indicate dependency on external JS runtime (mvz)
* Several improvements to the Admin UI
* Update pt-BR translations (ramirovjr)
* Update nl translations (mvz)
* Update fr translations (Stephanyan, giniouxe)
* Update en translations (hmallett, stevenwilkin)
* Update es-MX translations (hernamvel)
* Changed navbar to dropdown onhover (jacemonje)
* Improve Publify's default templates
* Fix sidebar administration (mvz)
* Various cleanups and improvements of code and specs
* Fix several vulnerabilities reported by brakeman (mvz)
* Use more resourceful routes (hmallett)
* Fix editing users in Admin (pacergh)
* Add foreign keys and indexes to the schema (hmallett)
* Add a CONTRIBUTING.md file to help contributors (randomecho)
* Remove test dependency on feedvalidator (mvz)
* Remove old API links from RSD view (mvz)
* Remove outdated schemas rake task (stevenwilkin)
* Improve installation instructions (giniouxe)
* Paginate article archives pages (giniouxe)
* Handle tags that contain colons (ook)
* Ensure cache path exists (pvcarrera)
* Use protocol-relative URIs for Flickr images (flameeyes)
* Update text filter help texts to use 'publify' (mvz)
* Restore hiding/showing of optional comment fields (mvz)
* Use rails-timeago to provide time ago display (mvz)
* Adding new Publify favicon (fdv)
* Fix typo (garethrees)
* Various small bug fixes
* Several theme fixes

## 8.1.1

Frédéric de Villamil (4):

* Fixes broken autosave.
* Fixes editor size for pages and articles.
* Fixes publishing. Need to investigate why the specs did not break on that one.
* Updating Publify version for 8.1.1

## 8.1.0

Frédéric de Villamil (2):

* Adds missing users-style.css in assets precompile.
* Updates Rails version

Matijs van Zuijlen (47):

* Fix spec for sending pings on Article save
* Enforce correct join table name
* Fix finders
* Fix Feedback scopes
* Remove invalid attribute in Trackback spec setup
* Fix finder in spec
* Fix Migrator to match changed ActiveRecord::Migrator
* Declare params used for assignment permitted in admin
* Fix use of finders in admin and its specs
* Move `#text_filter=` override to where it will be picked up
* Fix implementation of `assert_xml`
* Avoid exception when avatar plugin is undefined
* Rewrite use of removed assertions
* Fix tests for layoutless rendering
* Fix rendered template spec
* Avoid attempting to create articles with the same id in spec setup
* Avoid attempting to update articles with the wrong id
* Fix use of finders outside admin
* Make Rails ignore the accept header again
* Declare params permitted
* Fix finders in migrations
* Match files as generated by Rails 4.1
* Remove unused Sidebar methods
* Introduce `valid` scope to find Sidebars safely
* Remove unused methods
* Wrap long comment
* Add a TODO
* Wrap long lines
* Avoid time zone shift
* Add a FIXME
* Use current time zone for Tweets
* Fix check for SQLite connection
* Replace webrat with capybara
* Replace should contain with should match
* Fix usage of `have_selector` matcher
* Make sidebar generator Rails 3 compliant.
* Declare assets for precompilation
* Allow GET to /setup
* Include admin assets in precompile list
* Fix creation of first article in SetupController
* Fix hash rockets and white space in SetupController and its specs
* Include admin css in precompile list
* Move fonts to their normal position
* Precompile font assets without cache buster
* Make sure NonStupidDigestAssets is always defined
* Fix spec setup
* Make rendering notes in article list work

Thomas Lecavelier (16):

* Upgrade rails stack to 4.1.1
* `eager_loading` mandatory in conf
* Page caching removed from Rails4.0, return it as a Gem
* Observers removed from Rails4.0, return it as a Gem
* WIP deprecated stuff conversion
* Can't merge proc, you know…
* `default_scope` explicitly require a block, now
* `attr_accessible` no longer exist. User `params.require`/`permits` in
  controller instead.
* `default_scope` for Note
* I hate you all… T_T match must specify HTTP method(s)
* Can't use same alias for 2 differents routes…
* Misuse of named route + match / via
* Replace every #match by its HTTP verb or define their opened verbs with :via key
* Must check searches
* Fix deprecation warning for Travis
* Fix Blog.default

regonn (3):

* fix heroku config:set
* delete unnecessary command
* add heroku server restart command

## 8.0.2

Alexander Markov (1):

* `.published_on` changed; see below

Benoit C. Sirois (2):

* Added some translations
* Fixes link caching issue (All cached links are the same basically)

Frédéric de Villamil (21):

* Replaces the old Prototype based Lightbox with a more modern based on
  Bootstrap and Jquery.
* Fixes bootstrap use in the image gallery.
* Porting the lightbox plugin to the new version.
* Removing useless Javascript.
* Fixes the specs
* Fixes that very annoying bug in the editor save bar.
* Fixing a bug where the article content is displayed twice when using the more tag.
* Encloses the sidebar admin help text in a blue block (like every help text).
  Also fixes the style on the per widget submit button + removes button class
  on the cancel link (this should be the default)
* Removes the btn class on cancel
* Enables the close icon on the help messages
* Fixes layout differences betwen the page form and the post form
* Fixes the last comments dashboard avatar alignment
* Fixes articles search.
* Fixes an encoding issue in the inbound link plugin.
* Fixes the tag manager display issue.
* Apparently, rendering an empty js.erb file on destroy makes the effective
  destroy work. Not sure why.
* Fixes file upload.
* Fixes dynamic comment state change.
* Removes forgoten debug trace
* Replaces the date picker with datetime picker.
* Updating README and Publify version for 8.0.2 release

Hans de Graaff (1):

* Use a relative image path

Matijs van Zuijlen (13):

* Limit set of allowed comment parameters
* Run db setup inside bundle on Travis CI
* Upgrade to Rails 3.2.18
* Remove useless gems
* Fix indenting
* Remove useless #map
* Make Travis CI validate the rendered feeds
* Avoid symbolizing by stringifying instead
* Ensure RSpec 2.99 gets installed
* Avoid clearing cache that may not be there in test
* Balance tags of Bootstrap theme layout
* CarrierWave automatically sets the mime type now
* Fix Twitter gem deprecations

Soon Van (1):

* Typos and capitals in README [ci skip]

Thomas Lecavelier (2):

* Fix [#423]: stutter article content
* Excerpt is not editable anymore. Drop it even for `full_article_content`
  partial. Close [#423]
* Upgrade to Rails 3.2.17

Tor Helland (2):

* Synchronised Norwegian translation with the English en.yml.
* Revised all of Norwegian translation.

Yannick Francois (11):

* Just a little cleanup of a spec
* Add humans txt settingso
* Really write to humans txt file
* Add a text controller to manage humans.txt (and other later)
* Robots.txt generated by a controller.
* Refactor duplication in notes controller
* Just clean syntax on specs
* Prepare rspec 3 by removing deprecations
* Put back condition on cache for archives page
* Clean code around notes show and url helper
* Fix note helper. Back in application helper.

slainer68 (1):

* Travis build on 2.0 and 2.1

[#423]: https://github.com/publify/publify/issues/423

## 8.0.1

* [#398]: the user-style.css stylesheet is not loaded in the Bootstrap theme
* [#399]: the note style is not applied.
* [#402], [#410], [#411]: deployment crashes on Heroku (thank you @slainer68 for
  fixing that).
* [#412]: the editor locally saves the content of the edited note, which means it
  reloads it when you edit another note, overwriting the legit content.

[#398]: https://github.com/publify/publify/issues/398
[#399]: https://github.com/publify/publify/issues/399
[#402]: https://github.com/publify/publify/issues/402
[#410]: https://github.com/publify/publify/issues/410
[#411]: https://github.com/publify/publify/issues/411
[#412]: https://github.com/publify/publify/issues/412

## Publify 8.0

It's been 5 months since Publify 7.1, and considering the figures, Publify 8.0
is the biggest release we ever pushed in 9 years: 474 commits, 71 issues
closed, 8 contributors, 567 files changed, 60,767 additions and 45,166
deletions.

But you probably don't care about numbers that much, except if you're wondering
whether or not the project is till alive. TL; DR: it is.

The project itself has known one big change, [moving from Fred's personal
Github account to a dedicated organization][1]. We have been thinking about it
for a while, and we believe it's the best we could do for Publify.

### Simpler, better, faster

Last summer, [we started to rethink what we wanted Publify to be][2]. At a time
where online publishing is more or less split between Wordpress, hosted
platforms and static engines, being "only" a blogging platform had no meaning
anymore. We started to extend publishing capabilities, choosing Twitter pushed
short notes as a first step before we add more content type. This led to
Publify 7.0, and once again we knew it was the way to go.

Before adding these feature, we wanted Publify 8.0 to rebuild the whole user
experience. It had to be simpler, clearer and better, far from the MS Word 97
style that prevails in Web publishing since more than 10 years.

This meant a simpler interface with a single, smaller menu, getting out of the
old create / read / update / delete scheme when possible, merging some sections
and finally removing lots of things. This also means using the most of large
screens capabilities, using _responsive_ layouts as much as we could, even
though it made the job more difficult at some point.

The editor, it has been completely revamped, following the way opened by both
Medium and Ghost. We've pushed aside everything that may distract you from
writing. The post settings are 1 click away from the editor so you won't feel
lost anyway. We know how much work is left to get a really classy tool, but
we're working on it.

The notes have got improvement. When replying to a tweet, Publify now displays
the original tweet so readers can keep the context this was done.

Users profiles have been improved to. Each user now has its own detailed page
with avatar, contact links, short bio and indeed the published content.

### Missing in action

The old categories VS tags separation is no more. We merged the first into the
seconds as a strict categorization has no real meaning on most blogs. Don't
worry about your URLs, we took care of everything, eventually creating the
redirects you needed.

The _excerpt_ has been removed. Excerpt was meant to display a different
content on the listing page and on the post itself. It was an interesting
feature, but only a handful of people, if none was using it, and it made the
editor more complicated than necessary.

The old [Typographic theme][3] is not part of the core anymore. It has moved to
its own project and will still be maintained.

The old XMLRPC backend has been discontinued. This means Publify does not
support desktop clients anymore. This choice has been motivated by the fact
that the APIs it was relying had not been updated for 10 years, and that most
desktop editors are not maintained anymore either. Web browsers capabilities
have evolved, and you can now have a fairly decent editor with local saving
without the need of a desktop application.

### Under the hood

Publify has been around for 9 years now. Rails was not 1.0 yet, and some of our
code was older than you can ever imagine.

Publify 8.0 got rid of most of that legacy code. The old Prototype based
helpers that made Rails famous back then left the building. Prototype itself
has finally been replaced by Jquery, and Rails i18n allowed the _Globalize_
based translation system to enjoy a deserved retirement. Most helpers have been
removed too, as most of them were only used in one place.

This should not affect you unless you're running custom themes and plugins. If
so, have a look at the Bootstrap theme to see how we're now working.

That's all folks, you can now download Publify, or give it a try on [our demo
platform][4].

[1]: http://t37.net/here-comes-the-time-to-hand-over-your-open-source-project.html
[2]: http://t37.net/is-coding-a-blogging-engine-still-worth-the-effort-in-2013-and-other-thoughts-about-content-publishing-tools.html
[3]: https://github.com/publify/typographic
[4]: https://demo-publify.herokuapp.com/


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Publify

We welcome contributions to Publify. Please follow the guidelines below to help the
process of handling issues and pull requests go smoothly.

## Issues

When creating an issue, please provide as much information as possible, and
follow the guidelines below to make it easier for us to figure out what's going
on. If you miss any of these points we will probably ask you to improve the
ticket.

- Include a clear title describing the problem
- Describe what you are trying to achieve
- Describe what you did, including the URLs of the pages you visited
- Describe what you expected to happen
- Describe what happened instead, including any relevant output, error logs or screenshots
- State the version of Publify you are using
- Use [code blocks](https://github.github.com/gfm/#fenced-code-blocks) to
  format any code and output in your ticket to make it readable.

## Pull Requests

We welcome pull requests. Please check first if the problem you're solving is
fixed in master, or if the desired feature is already in development. Before
starting a large feature, please open a ticket first so we can discuss it.

When sending a pull request, please follow **all of** the instructions below:

- Make sure `bundle exec rake` runs without reporting any failures. See
  *Testing your changes* below for more details.
- Add tests for your feature. Otherwise, I can't see if it works or if I break
  it later.
- Create a separate branch for your feature based off of latest master.
- Write [good commit messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- Do not include changes that are irrelevant to your feature in the same
  commit.
- Keep an eye on the build results in GitHub Actions. If the build fails and it
  seems due to your changes, please update your pull request with a fix.

If you're not sure how to test the problem, or what the best solution is, or
get stuck on something else, please open an issue first so that we can discuss
the best approach.

### Testing your changes

You can run the test suite with the latest version of all dependencies by running the following:

- Run `bundle install` if you haven't done so already, or `bundle update` to update the dependencies
- Run `bundle exec rake` to run the tests

To run the tests suite for **TODO** a particular version of Rails, use
[appraisal](https://github.com/thoughtbot/appraisal). For example, to run the
specs with Rails 6.1, run `appraisal rails_6_1 rake`. See appraisal's
documentation for details.

### The review process

- We will try to review your pull request as soon as possible but we can make no
  guarantees. Feel free to ping us now and again.
- I will probably ask you to rebase your branch on current master at some point
  during the review process.
  If you are unsure how to do this,
  [this in-depth guide](https://git-rebase.io/) should help out.
- If you have any unclear commit messages, work-in-progress commits, or commits
  that just fix a mistake in a previous commit, we will ask you to clean up the
  history.
  Again, [the git-rebase guide](https://git-rebase.io/) should help out.
  Note that we will not squash-merge pull requests, since that results in a loss of history.
- **At the end of the review process we may still choose not to merge your pull
  request.** For example, this could happen if we decide the proposed feature
  should not be part of Publify, or if the technical implementation does not
  match where I want to go with the architecture of the project.
- We will generally not merge any pull requests that make the build fail, unless
  it's very clearly not related to the changes in the pull request.


================================================
FILE: Gemfile
================================================
# frozen_string_literal: true

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem "rails", ["~> 7.1.5", ">= 7.1.5.2"]

gem "mysql2"
gem "pg"
gem "sqlite3", "~> 2.9.4"

# Store sessions in the database
gem "activerecord-session_store", "~> 2.2.0"

# Use Puma as the app server
gem "puma", "~> 8.0"

gem "publify_amazon_sidebar", github: "publify/publify_amazon_sidebar"
gem "publify_core", github: "publify/publify_core"
gem "publify_textfilter_code", github: "publify/publify_textfilter_code"

# Use Uglifier as compressor for JavaScript assets
gem "uglifier", ">= 1.3.0"

# Needed for the lightbox and flickr text filters
gem "flickraw", "~> 0.9.8", require: false

gem "non-digest-assets", "~> 2.0"
gem "rake", "~> 13.0"
gem "reverse_markdown", "~> 3.0"

# Force newer sprockets
gem "sprockets", "~> 4.0"

# Allow throttling requests
gem "rack-attack", "~> 6.5"

gem "net-smtp", "~> 0.5.0"

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem "byebug", platforms: [:mri, :windows]

  gem "capybara", "~> 3.9"
  gem "factory_bot", "~> 6.2"
  gem "i18n-tasks", "~> 1.1.0", require: false
  gem "rspec-rails", "~> 7.1"
  gem "rubocop", "~> 1.86.1", require: false
  gem "rubocop-capybara", "~> 2.23.0", require: false
  gem "rubocop-factory_bot", "~> 2.28.0", require: false
  gem "rubocop-performance", "~> 1.26.0", require: false
  gem "rubocop-rails", "~> 2.35.0", require: false
  gem "rubocop-rspec", "~> 3.9.0", require: false
  gem "rubocop-rspec_rails", "~> 2.32.0", require: false
  gem "simplecov", "~> 0.22.0", require: false
end

group :development do
  # Access an interactive console on exception pages or by calling 'console'
  # anywhere in the code.
  gem "web-console", "~> 4.1"

  gem "listen", "~> 3.3"
  # Display performance information such as SQL time and flame graphs for each
  # request in your browser.
  # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md
  gem "rack-mini-profiler", "~> 4.0"
  # Spring speeds up development by keeping your application running in the
  # background. Read more: https://github.com/rails/spring
  gem "spring", "~> 4.5.0"
  gem "spring-commands-rspec", "~> 1.0"

  gem "fast_stack"
  gem "flamegraph"
  gem "memory_profiler"
  gem "stackprof"
end

group :test do
  # TODO: Remove when upgrading rails and/or rspec-rails
  gem "drb", "~> 2.2.3"
  gem "mutex_m", "~> 0.3.0"

  gem "feedjira", "~> 4.0"
  gem "launchy", "~> 3.0"
  gem "rails-controller-testing", "~> 1.0.1"
  gem "shoulda-matchers", "~> 7.0"
  gem "timecop", "~> 0.9.1"
  gem "webmock", "~> 3.3"
end

# Install gems from each theme
Dir.glob(File.join(File.dirname(__FILE__), "themes", "**", "Gemfile")) do |gemfile|
  eval(File.read(gemfile), binding)
end


================================================
FILE: MIT-LICENSE
================================================
Copyright (c) 2005 Tobias Luetke
Copyright (c) 2005-2013 Typo Developers & Contributors
Copyright (c) 2013-2017 Publify Developers & Contributors

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



================================================
FILE: README.md
================================================
# Publify

**The Ruby on Rails publishing software formerly known as Typo**

[![Build status](https://github.com/publify/publify/actions/workflows/ruby.yml/badge.svg)](https://github.com/publify/publify/actions/workflows/ruby.yml)
[![Code Climate](https://codeclimate.com/github/publify/publify.svg)](https://codeclimate.com/github/publify/publify)
[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)

## What's Publify?

Publify is a simple but full featured web publishing software. It's built
around a blogging engine and a small message system connected to Twitter.

Publify follows the principles of the IndieWeb, which are self hosting your Web
site, and Publish On your Own Site, Syndicate Everywhere.

Publify has been around since 2004 and is the oldest Ruby on Rails open source
project alive.

## Features

- A classic multi user blogging engine
- Short messages with a Twitter connection
- Text filters (Markdown, SmartyPants, @mention to link, #hashtag to link)
- A widgets system and a plugin API
- Custom themes
- Advanced SEO capabilities
- Multilingual : Publify is (more or less) translated in English, French,
  German, Danish, Norwegian, Japanese, Hebrew, Simplified Chinese, Mexican
  Spanish, Italian, Lithuanian, Dutch, Polish, Romanian…

## Demo site

You can give Publify a try at [the demo site](https://publify-demo.fly.dev/).

The demo is reset every hour.

## Install

### Download

You can download the latest
Publify [stable release](https://github.com/publify/publify/releases/latest).

If you want to run the master branch, you can [clone the Publify
repository](https://github.com/publify/publify.git). However, random things may
be broken there at any time, so tread carefully!

**Running the master branch in production is not recommended!**

### Install Publify locally

To install Publify you need the following:

- CRuby (MRI) 2.5, 2.6 or 2.7
- Ruby on Rails 5.2.x
- A database engine, MySQL, PgSQL or SQLite3
- A compatible JavaScript installation for asset compilation. See
  [the execjs readme](https://github.com/sstephenson/execjs#readme) for details.
- ImageMagick (used by `mini_magick`).

1.  Unzip Publify archive
2.  Rename database.yml.yourEngine as database.yml
3.  Edit database.yml to add your database name, login and password.

```bash
$ bundle install
$ rake db:setup
$ rake db:migrate
$ rake db:seed
$ rake assets:precompile
$ rails server
```

You can now launch you browser and access 127.0.0.1:3000.

### Install Publify on a server

You can use your preferred installation method (e.g., Capistrano) to install
Publify on a server. You will also need to set up the environment so it
contains at least `SECRET_KEY_BASE`. Your web server may allow you to set this,
or you can consider using a tool like `dotenv`.

### Install Publify on Heroku

In order to install Publify on Heroku, you’ll need to do some minor tweaks.

First of all, you need to set up Amazon S3 storage to be able to upload files on
your blog. Set Heroku config vars.

```bash
heroku config:set PROVIDER=AWS
heroku config:set AWS_ACCESS_KEY_ID=<your_aws_access_key_id>
heroku config:set AWS_SECRET_ACCESS_KEY=<your_aws_secret_access_key>
heroku config:set AWS_BUCKET=<your_aws_bucket_name>
```

Next, you need to update `Gemfile`. You should remove the `mysql2` and
`sqlite3` gems, set the Ruby version, and add `rails_12factor`. The top of your
`Gemfile` should look something like this:

```ruby
source 'https://rubygems.org'

ruby '2.7.4' # Or whichever version you're running
gem 'pg'
gem 'rails_12factor'

gem 'rails', '~> 5.2.6'
```

Next, to regenerate the Gemfile.lock, run:
```bash
bundle install
```

Commit your updated `Gemfile` and `Gemfile.lock`:

```bash
git commit -am 'Update bundle for Heroku'
```

Create a file `Procfile` containing the following:
```
web: bundle exec puma -C config/puma.rb
```

Commit your new `Procfile`:
```bash
git add Procfile
git ci -m 'Tell Heroku how to run Rails'
```

You also need to set Rails' secret key base. Generate one using `rake secret`,
then set the Heroku config var:

```bash
heroku config:set SECRET_KEY_BASE=<your_generated_secret>
```

Push the repository to Heroku.

When deploying for the first time, Heroku will automatically add a Database
plugin to your instance and links it to the application. After the first
deployment, don't forget to run the database migration and seed.

```bash
heroku run rake db:migrate db:seed
```

If application error has occurred after migration, you need to restart Heroku server.

```bash
heroku restart
```

## Resources

- [Sidebar Plugins](https://github.com/publify/publify/wiki/Sidebar-plugins)
- [In page Plugins](https://github.com/publify/publify/wiki/In-Page-Plugins)
- [**Report a bug**](https://github.com/publify/publify/issues)
- [**Frequently Asked Questions**](https://github.com/publify/publify/wiki/frequently-asked-questions)
- [Publify on Twitter](https://twitter.com/getpublify)
- IRC: \#publify on irc.freenode.net

## Maintainers

### Current Maintainers

**Frédéric de Villamil**
blog: http://t37.net

**Matijs van Zuijlen**
blog: http://www.matijs.net/blog/

**Thomas Lecavelier**
blog: http://blog.ookook.fr/

**Yannick François**
blog: http://elsif.fr

### Previous Maintainers & Notable Contributors

**Cyril Mougel**
blog: http://blog.shingara.fr

**Davide D'Agostino**
blog: http://www.lipsiasoft.com

**Piers Cawley**
blog: http://www.bofh.org.uk/

**Scott Laird**

**Kevin Ballard**
blog: kevin.sb.org

**Patrick Lenz**

**Seth Hall**

And [many more cool people who’ve one way or another contributed to
Publify](https://github.com/publify/publify/graphs/contributors).

**Original Author: Tobias Luetke**
blog: http://blog.leetsoft.com/

Enjoy,
The Publify team


================================================
FILE: Rakefile
================================================
# frozen_string_literal: true

# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path("config/application", __dir__)

Rails.application.load_tasks


================================================
FILE: TODO.txt
================================================
AdminSidebar:
- On the fly save of params
- CSS
- Remove on staged/active sidebars
- Maybe some animations


================================================
FILE: app/assets/config/manifest.js
================================================


================================================
FILE: app/assets/images/.keep
================================================


================================================
FILE: app/controllers/application_controller.rb
================================================
# frozen_string_literal: true

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end


================================================
FILE: app/helpers/theme_helper.rb
================================================
# frozen_string_literal: true

module ThemeHelper
  # Adds per theme helpers if file exists. Ugly but at least it works.
  # Use: just add your methods in yourtheme/helpers/theme_helper.rb
  # If your theme is a plugin, it's better to just load relevant helpers in the
  # initialization code instead.
  Theme.find_all.each do |theme|
    filename = File.join(theme.path, "helpers", "theme_helper.rb")
    require filename if File.exist? filename
  end
end


================================================
FILE: app/mailers/application_mailer.rb
================================================
# frozen_string_literal: true

class ApplicationMailer < ActionMailer::Base
end


================================================
FILE: app/models/application_record.rb
================================================
# frozen_string_literal: true

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end


================================================
FILE: app/models/authors_sidebar.rb
================================================
# frozen_string_literal: true

class AuthorsSidebar < Sidebar
  display_name "Authors"
  description "Displays a list of authors ordered by name with links to their" \
              " articles and profile"

  setting :count, true, label: "Show articles number", input_type: :checkbox

  def authors
    @authors = User.where(state: "active").order(:name)
  end
end

SidebarRegistry.register_sidebar AuthorsSidebar


================================================
FILE: app/models/concerns/.keep
================================================


================================================
FILE: app/models/livesearch_sidebar.rb
================================================
# frozen_string_literal: true

class LivesearchSidebar < Sidebar
  description "Adds livesearch to your Publify blog"

  setting :title, "Search"
end

SidebarRegistry.register_sidebar LivesearchSidebar


================================================
FILE: app/models/notes_sidebar.rb
================================================
# frozen_string_literal: true

class NotesSidebar < Sidebar
  description "Displays the latest notes"
  setting :title, "Notes"
  setting :count, 5, label: "Number of notes"

  attr_accessor :notes

  def parse_request(_contents, params)
    @notes = Note.published.page(params[:page]).per(count)
  end
end

SidebarRegistry.register_sidebar NotesSidebar


================================================
FILE: app/models/popular_sidebar.rb
================================================
# frozen_string_literal: true

class PopularSidebar < Sidebar
  description "Displays the most popular posts"
  setting :title, "Most popular"
  setting :count, 5, label: "Number articles"

  attr_accessor :popular

  def parse_request(_contents, _params)
    @popular = Article.bestof.limit(5)
  end
end

SidebarRegistry.register_sidebar PopularSidebar


================================================
FILE: app/models/xml_sidebar.rb
================================================
# frozen_string_literal: true

class XmlSidebar < Sidebar
  display_name "XML Syndication"
  description "RSS and Atom feeds"

  setting :articles, true, input_type: :checkbox
  setting :feedback, true, input_type: :checkbox
  setting :article_comments, true, input_type: :checkbox
  setting :tag_feeds, false, input_type: :checkbox

  setting :format, "atom", input_type: :radio, choices: [%w(rss RSS), %w(atom Atom)]

  def format_strip
    strip_format = +format
    strip_format ||= +"atom"
    strip_format.gsub!(/\d+/, "")
    strip_format.gsub!("1.0", "")
    strip_format.gsub!("2.0", "")
    strip_format
  end
end

SidebarRegistry.register_sidebar XmlSidebar


================================================
FILE: app/views/authors_sidebar/_content.html.erb
================================================
<% cache sidebar.authors do %>
<% unless sidebar.authors.blank? %>
  <h3 class="sidebar-title"><%= t('.authors') %></h3>
  <div class="sidebar-body">
    <ul id="categories">
      <% for user in sidebar.authors %>
        <li>
          <% count = "(#{user.articles.count})" %>
          <%= link_to "#{h(user.name)} #{count if sidebar.count}", author_path(id: user.login) %>
        </li>
      <% end %>
    </ul>
  </div>
<% end %>
<% end %>


================================================
FILE: app/views/livesearch_sidebar/_content.html.erb
================================================
<h3 class="sidebar-title">
  <label for="q"><%= sidebar.title %></label>
</h3>
<div class="sidebar-body">
  <%= form_tag({ controller: 'articles', action: 'search' }, { method: 'get', id: 'sform' }) do %>
    <%= text_field_tag :q, '',
                       id: 'live_search', size: 15, autocomplete: 'off', class: 'observable',
                       data: { url: live_search_articles_url, target: '#search-results', spinner: '#search_spinner' } %>
    <%= image_tag 'spinner-blue.gif', id: 'search_spinner', style: 'display:none;' %>
  <% end %>
  <div id="search-results" class="results"></div>
</div>


================================================
FILE: app/views/notes_sidebar/_content.html.erb
================================================
<% unless sidebar.notes.blank? %>
  <h3 class="sidebar-title"><%= sidebar.title %></h3>
  <div class="sidebar-body">
    <% sidebar.notes.each do |note| %>
      <div class="statuses_sidebar">
        <%= author_picture note %>
        <%= note.html(:body) %>
        <%= link_to_permalink(note, display_date_and_time(note.published_at)) %>
        <% unless note.twitter_id.blank? %>
          <%= " | #{link_to(t('.view_on_twitter'), note.twitter_url, class: 'u-syndication', rel: 'syndication')}" %>
        <% end %>
      </div>
    <% end %>
  </div>
<% end %>


================================================
FILE: app/views/popular_sidebar/_content.html.erb
================================================
<h3 class="sidebar-title"><%= sidebar.title %></h3>
<div class="sidemenu-content">
  <ul class="popular_sidebar">
    <% if sidebar.popular.empty? || sidebar.popular.size == 0 %>
      <li class="alert"><%= t('.nothing_to_show_yet') %> !</li>
    <% else %>
      <% sidebar.popular.each do |article| %>
        <%= sprintf('%s (%s)', link_to_permalink(article, article.title), t('.comments', count: article.comment_count)) %>
      <% end %>
    <% end %>
    </li>
  </ul>
</div>


================================================
FILE: app/views/xml_sidebar/_content.html.erb
================================================
<h3 class="sidebar-title"><%= t('.syndicate') %></h3>
<div class="sidebar-body">
  <ul>
    <% if sidebar.articles %>
      <li>
        <a href="<%= url_for controller: 'articles', action: 'index', format: sidebar.format_strip %>" title="Articles feed">
          <%= t('.articles') %>
        </a>
      </li>
    <% end %>
    <% if sidebar.feedback %>
      <li>
        <a href="<%= feedback_index_path(format: sidebar.format_strip) %>" title="Feedback feed">
          <%= t('.feedback') %>
        </a>
      </li>
    <% end %>
    <% if sidebar.tag_feeds and controller.controller_name == 'tags' and controller.action_name == 'show' %>
      <li>
        <%= t('.tag') %>
        <%= link_to(@tag.display_name, @tag.feed_url(sidebar.format_strip)) %>
      </li>
    <% end %>
    <% if sidebar.article_comments and controller.controller_name == 'articles' and controller.action_name == 'redirect' %>
      <li>
        <%= link_to(@article.title, @article.feed_url(sidebar.format_strip)) %>
      </li>
    <% end %>
  </ul>
</div>


================================================
FILE: bin/bundle
================================================
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
load Gem.bin_path('bundler', 'bundle')


================================================
FILE: bin/i18n-tasks
================================================
#!/usr/bin/env ruby
begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end
require 'bundler/setup'
require 'logger'
load Gem.bin_path('i18n-tasks', 'i18n-tasks')


================================================
FILE: bin/rails
================================================
#!/usr/bin/env ruby
APP_PATH = File.expand_path("../config/application", __dir__)
require_relative "../config/boot"
require "rails/commands"


================================================
FILE: bin/rake
================================================
#!/usr/bin/env ruby
require_relative "../config/boot"
require "rake"
Rake.application.run


================================================
FILE: bin/rspec
================================================
#!/usr/bin/env ruby
begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end
require 'bundler/setup'
load Gem.bin_path('rspec-core', 'rspec')


================================================
FILE: bin/setup
================================================
#!/usr/bin/env ruby
require "fileutils"

# path to your application root.
APP_ROOT = File.expand_path("..", __dir__)

def system!(*args)
  system(*args, exception: true)
end

FileUtils.chdir APP_ROOT do
  # This script is a way to set up or update your development environment automatically.
  # This script is idempotent, so that you can run it at any time and get an expectable outcome.
  # Add necessary setup steps to this file.

  puts "== Installing dependencies =="
  system! "gem install bundler --conservative"
  system("bundle check") || system!("bundle install")

  # puts "\n== Copying sample files =="
  # unless File.exist?("config/database.yml")
  #   FileUtils.cp "config/database.yml.sample", "config/database.yml"
  # end

  puts "\n== Preparing database =="
  system! "bin/rails db:prepare"

  puts "\n== Removing old logs and tempfiles =="
  system! "bin/rails log:clear tmp:clear"

  puts "\n== Restarting application server =="
  system! "bin/rails restart"
end


================================================
FILE: bin/update
================================================
#!/usr/bin/env ruby
require 'fileutils'
include FileUtils

# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)

def system!(*args)
  system(*args) || abort("\n== Command #{args} failed ==")
end

chdir APP_ROOT do
  # This script is a way to update your development environment automatically.
  # Add necessary update steps to this file.

  puts '== Installing dependencies =='
  system! 'gem install bundler --conservative'
  system('bundle check') || system!('bundle install')

  # Install JavaScript dependencies if using Yarn
  # system('bin/yarn')

  puts "\n== Updating database =="
  system! 'bin/rails db:migrate'

  puts "\n== Removing old logs and tempfiles =="
  system! 'bin/rails log:clear tmp:clear'

  puts "\n== Restarting application server =="
  system! 'bin/rails restart'
end


================================================
FILE: bin/yarn
================================================
#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
  yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
    select { |dir| File.expand_path(dir) != __dir__ }.
    product(["yarn", "yarn.cmd", "yarn.ps1"]).
    map { |dir, file| File.expand_path(file, dir) }.
    find { |file| File.executable?(file) }

  if yarn
    exec yarn, *ARGV
  else
    $stderr.puts "Yarn executable was not detected in the system."
    $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
    exit 1
  end
end


================================================
FILE: config/application.rb
================================================
# frozen_string_literal: true

require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Publify
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

    # Please, add to the `ignore` list any other `lib` subdirectories that do
    # not contain `.rb` files, or that should not be reloaded or eager loaded.
    # Common ones are `templates`, `generators`, or `middleware`, for example.
    config.autoload_lib(ignore: %w(assets tasks generators))
    config.add_autoload_paths_to_load_path = false

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("extras")
    config.action_dispatch.cookies_serializer = :hybrid
  end

  Theme.register_themes Rails.root.join("themes")
end


================================================
FILE: config/boot.rb
================================================
# frozen_string_literal: true

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)

require "bundler/setup" # Set up gems listed in the Gemfile.


================================================
FILE: config/cable.yml
================================================
development:
  adapter: async

test:
  adapter: test

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: publify_production


================================================
FILE: config/database.yml.mysql
================================================
login: &login
  adapter: mysql2
  host: 127.0.0.1
  username: root
  password: mysql
  port: 3306


development:
  database: publify_dev
  <<: *login

test:
  database: publify_test
  <<: *login

production:
  database: publify
  <<: *login


================================================
FILE: config/database.yml.postgresql
================================================
login: &login
  adapter: postgresql
  host: localhost
  port: 5432
  username: postgres
  password: postgres

connection: &connection
  encoding: unicode
  pool: 5


development:
  database: publify_dev
  <<: *login
  <<: *connection

test:
  database: publify_test
  <<: *login
  <<: *connection

production:
  database: publify
  <<: *login
  <<: *connection


================================================
FILE: config/environment.rb
================================================
# frozen_string_literal: true

# Load the Rails application.
require_relative "application"

# Initialize the Rails application.
Rails.application.initialize!


================================================
FILE: config/environments/development.rb
================================================
# frozen_string_literal: true

require "active_support/core_ext/integer/time"

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded any time
  # it changes. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.enable_reloading = true

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports.
  config.consider_all_requests_local = true

  # Enable server timing
  config.server_timing = true

  # Enable/disable caching. By default caching is disabled.
  # Run rails dev:cache to toggle caching.
  if Rails.root.join("tmp/caching-dev.txt").exist?
    config.action_controller.perform_caching = true
    config.action_controller.enable_fragment_cache_logging = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      "Cache-Control" => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false

  config.action_mailer.perform_caching = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise exceptions for disallowed deprecations.
  config.active_support.disallowed_deprecation = :raise

  # Tell Active Support which deprecation messages to disallow.
  config.active_support.disallowed_deprecation_warnings = []

  # Raise an error on page load if there are pending migrations.
  config.active_record.migration_error = :page_load

  # Highlight code that triggered database queries in logs.
  config.active_record.verbose_query_logs = true

  # Highlight code that enqueued background job in logs.
  config.active_job.verbose_enqueue_logs = true

  # Suppress logger output for asset requests.
  config.assets.quiet = true

  # Raises error for missing translations.
  # config.i18n.raise_on_missing_translations = true

  # Annotate rendered view with file names.
  # config.action_view.annotate_rendered_view_with_filenames = true

  # Uncomment if you wish to allow Action Cable access from any origin.
  # config.action_cable.disable_request_forgery_protection = true

  # Raise error when a before_action's only/except options reference missing actions
  config.action_controller.raise_on_missing_callback_actions = true
end


================================================
FILE: config/environments/production.rb
================================================
# frozen_string_literal: true

require "active_support/core_ext/integer/time"

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # Code is not reloaded between requests.
  config.enable_reloading = false

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

  # Full error reports are disabled and caching is turned on.
  config.consider_all_requests_local = false
  config.action_controller.perform_caching = true

  # Ensures that a master key has been made available in
  # ENV["RAILS_MASTER_KEY"], config/master.key, or an environment key such as
  # config/credentials/production.key. This key is used to decrypt credentials
  # (and other encrypted files).
  # config.require_master_key = true

  # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
  # config.public_file_server.enabled = false

  # Compress CSS using a preprocessor.
  # config.assets.css_compressor = :sass

  # Do not fall back to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false

  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
  # config.asset_host = "http://assets.example.com"

  # Specifies the header that your server uses for sending files.
  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
  # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX

  # Store uploaded files on the local file system (see config/storage.yml for options).
  config.active_storage.service = :local

  # Mount Action Cable outside main process or domain.
  # config.action_cable.mount_path = nil
  # config.action_cable.url = "wss://example.com/cable"
  # config.action_cable.allowed_request_origins =
  #   [ "http://example.com", /http:\/\/example.*/ ]

  # Assume all access to the app is happening through a SSL-terminating reverse proxy.
  # Can be used together with config.force_ssl for Strict-Transport-Security
  # and secure cookies.
  # config.assume_ssl = true

  # Force all access to the app over SSL, use Strict-Transport-Security, and
  # use secure cookies.
  config.force_ssl = true

  # Log to STDOUT by default
  config.logger = ActiveSupport::Logger.new($stdout)
    .tap  { |logger| logger.formatter = Logger::Formatter.new }
    .then { |logger| ActiveSupport::TaggedLogging.new(logger) }

  # Prepend all log lines with the following tags.
  config.log_tags = [:request_id]

  # "info" includes generic and useful information about system operation, but
  # avoids logging too much information to avoid inadvertent exposure of
  # personally identifiable information (PII). If you want to log everything,
  # set the level to "debug".
  config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")

  # Use a different cache store in production.
  # config.cache_store = :mem_cache_store

  # Use a real queuing backend for Active Job (and separate queues per environment).
  # config.active_job.queue_adapter = :resque
  # config.active_job.queue_name_prefix = "publify_production"

  config.action_mailer.perform_caching = false

  # Ignore bad email addresses and do not raise email delivery errors.
  # Set this to true and configure the email server for immediate delivery to
  # raise delivery errors.
  # config.action_mailer.raise_delivery_errors = false

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation cannot be found).
  config.i18n.fallbacks = true

  # Don't log any deprecations.
  config.active_support.report_deprecations = false

  # Do not dump schema after migrations.
  config.active_record.dump_schema_after_migration = false

  # Enable DNS rebinding protection and other `Host` header attacks.
  # config.hosts = [
  #   "example.com",     # Allow requests from example.com
  #   /.*\.example\.com/ # Allow requests from subdomains like `www.example.com`
  # ]
  # Skip DNS rebinding protection for the default health check endpoint.
  # config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
end


================================================
FILE: config/environments/test.rb
================================================
# frozen_string_literal: true

require "active_support/core_ext/integer/time"

# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # While tests run files are not watched, reloading is not necessary.
  config.enable_reloading = false

  # Eager loading loads your entire application. When running a single test locally,
  # this is usually not necessary, and can slow down your test suite. However, it's
  # recommended that you enable it in continuous integration systems to ensure eager
  # loading is working properly before deploying your code.
  config.eager_load = ENV["CI"].present?

  # Configure public file server for tests with Cache-Control for performance.
  config.public_file_server.enabled = true
  config.public_file_server.headers = {
    "Cache-Control" => "public, max-age=#{1.hour.to_i}"
  }

  # Show full error reports and disable caching.
  config.consider_all_requests_local = true
  config.action_controller.perform_caching = false
  config.cache_store = :null_store

  # Render exception templates for rescuable exceptions and raise for other exceptions.
  config.action_dispatch.show_exceptions = :rescuable

  # Disable request forgery protection in test environment.
  config.action_controller.allow_forgery_protection = false

  # Store uploaded files on the local file system in a temporary directory.
  config.active_storage.service = :test

  config.action_mailer.perform_caching = false

  # Tell Action Mailer not to deliver emails to the real world.
  # The :test delivery method accumulates sent emails in the
  # ActionMailer::Base.deliveries array.
  config.action_mailer.delivery_method = :test

  # Print deprecation notices to the stderr.
  config.active_support.deprecation = :stderr

  # Raise exceptions for disallowed deprecations.
  config.active_support.disallowed_deprecation = :raise

  # Tell Active Support which deprecation messages to disallow.
  config.active_support.disallowed_deprecation_warnings = []

  # Raises error for missing translations.
  # config.i18n.raise_on_missing_translations = true

  # Annotate rendered view with file names.
  # config.action_view.annotate_rendered_view_with_filenames = true

  # Raise error when a before_action's only/except options reference missing actions
  config.action_controller.raise_on_missing_callback_actions = true
end


================================================
FILE: config/filemanager.yml
================================================
image.type: jpg gif png
flash.type: swf
movie.type: mov avi wmv
rm.type: rm rmvb
plain.type: txt ini inf html htm rb jsp php asp
office.type: doc dot xls xla ppt pps ppz pot hlp chm ods
word.type: doc dot
excel.type: xls xla ods
ppt.type: ppt pps ppz pot
help.type: hlp chm
none.type: rar zip
resources.url: /files
resources.path: <%= ::Rails.root.to_s %>/public/files
encoding.to: UTF-8
encoding.from: UTF-8
temp.dir:


================================================
FILE: config/i18n-tasks.yml
================================================
# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks

# The "main" locale.
base_locale: en

# <% publify_core_path = %x[bundle info --path publify_core].chomp %>
# <% rails_i18n_path = %x[bundle info --path rails-i18n].chomp %>

# Read and write translations.
data:
  # Locale files or `File.find` patterns where translations are read from:
  read:
    - config/locales/%{locale}.yml
    - config/locales/sidebars.%{locale}.yml

  # External locale data (e.g. gems).
  # This data is not considered unused and is never written to.
  external:
    - "<%= rails_i18n_path %>/rails/locale/%{locale}.yml"
    - "<%= publify_core_path %>/config/locales/%{locale}.yml"
    - "<%= publify_core_path %>/config/locales/sidebars.%{locale}.yml"

  # Locale files to write new keys to, based on a list of key pattern => file
  # rules. Matched from top to bottom:
  # `i18n-tasks normalize -p` will force move the keys according to these rules
  write:
    - ['*_sidebar.*', 'config/locales/sidebars.%{locale}.yml']
    - config/locales/%{locale}.yml

# Find translate calls
search:
  ## Paths or `File.find` patterns to search in:
  paths:
    - app/
    - lib/
    - themes/bootstrap-2/
    - <%= publify_core_path %>/app/

  ## Root directories for relative keys resolution.
  relative_roots:
    - app/controllers
    - app/helpers
    - app/mailers
    - app/presenters
    - app/views
    - themes/bootstrap-2/views
    - <%= publify_core_path %>/app/views/

## Do not consider these keys missing:
ignore_missing:
  - 'devise.*'

## Consider these keys used:
ignore_unused:
  - 'time.formats.*'
  - 'layouts.default.designed_by'
  - 'date.*'
  - 'activerecord.{attributes,errors,models}.*'


================================================
FILE: config/initializers/application_controller_renderer.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# ActiveSupport::Reloader.to_prepare do
#   ApplicationController.renderer.defaults.merge!(
#     http_host: 'example.org',
#     https: false
#   )
# end


================================================
FILE: config/initializers/assets.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = "1.0"

# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path

# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )


================================================
FILE: config/initializers/backtrace_silencers.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# You can add backtrace silencers for libraries that you're using but don't
# wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }

# You can also remove all the silencers if you're trying to debug a problem
# that might stem from framework code by setting BACKTRACE=1 before calling
# your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]


================================================
FILE: config/initializers/carrierwave.rb
================================================
# frozen_string_literal: true

if Rails.env.in?(%(test cucumber))
  CarrierWave.configure do |config|
    config.storage = :file
    config.enable_processing = false
  end
else
  CarrierWave.configure do |config|
    if ENV["provider"] == "AWS"
      config.storage = :fog

      config.fog_credentials = {
        provider: "AWS",
        aws_access_key_id: ENV.fetch("aws_access_key_id"),
        aws_secret_access_key: ENV.fetch("aws_secret_access_key")
      }

      config.fog_directory  = ENV.fetch("aws_bucket")
      config.fog_public     = true
      config.fog_attributes = { "Cache-Control" => "max-age=315576000" }
    else
      config.storage = :file
      config.permissions = 0o666
      config.directory_permissions = 0o777
    end
  end
end


================================================
FILE: config/initializers/content_security_policy.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Define an application-wide content security policy.
# See the Securing Rails Applications Guide for more information:
# https://guides.rubyonrails.org/security.html#content-security-policy-header

# Rails.application.configure do
#   config.content_security_policy do |policy|
#     policy.default_src :self, :https
#     policy.font_src    :self, :https, :data
#     policy.img_src     :self, :https, :data
#     policy.object_src  :none
#     policy.script_src  :self, :https
#     policy.style_src   :self, :https
#     # Specify URI for violation reports
#     # policy.report_uri "/csp-violation-report-endpoint"
#   end
#
#   # Generate session nonces for permitted importmap, inline scripts, and inline styles.
#   config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
#   config.content_security_policy_nonce_directives = %w(script-src style-src)
#
#   # Report violations without enforcing the policy.
#   # config.content_security_policy_report_only = true
# end


================================================
FILE: config/initializers/cookies_serializer.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Specify a serializer for the signed and encrypted cookie jars.
# Valid options are :json, :marshal, and :hybrid.
Rails.application.config.action_dispatch.cookies_serializer = :json


================================================
FILE: config/initializers/filter_parameter_logging.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Configure parameters to be partially matched (e.g. passw matches password)
# and filtered from the log file.
# Use this to limit dissemination of sensitive information.
# See the ActiveSupport::ParameterFilter documentation for supported notations
# and behaviors.
Rails.application.config.filter_parameters += [
  :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
]


================================================
FILE: config/initializers/flickr.rb
================================================
# frozen_string_literal: true

require "flickraw"

# Prepare needed FlickRaw methods
FlickRaw::Flickr.build(["flickr.photos.getInfo", "flickr.photos.getSizes"])

# Please get your own API key for setting up this.
# You can request it at
# https://www.flickr.com/services/api/misc.api_keys.html
FlickRaw.api_key = ""
FlickRaw.shared_secret = ""


================================================
FILE: config/initializers/inflections.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
#   inflect.plural /^(ox)$/i, "\\1en"
#   inflect.singular /^(ox)en/i, "\\1"
#   inflect.irregular "person", "people"
#   inflect.uncountable %w( fish sheep )
# end

# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
#   inflect.acronym "RESTful"
# end


================================================
FILE: config/initializers/mime_types.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf


================================================
FILE: config/initializers/new_framework_defaults_7_1.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.
#
# This file eases your Rails 7.1 framework defaults upgrade.
#
# Uncomment each configuration one by one to switch to the new default.
# Once your application is ready to run with all new defaults, you can remove
# this file and set the `config.load_defaults` to `7.1`.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html

###
# No longer add autoloaded paths into `$LOAD_PATH`. This means that you won't be able
# to manually require files that are managed by the autoloader, which you shouldn't do anyway.
#
# This will reduce the size of the load path, making `require` faster if you don't use bootsnap, or reduce the size
# of the bootsnap cache if you use it.
#
# To set this configuration, add the following line to `config/application.rb` (NOT this file):
#   config.add_autoload_paths_to_load_path = false

###
# Remove the default X-Download-Options headers since it is used only by Internet Explorer.
# If you need to support Internet Explorer, add back `"X-Download-Options" => "noopen"`.
#++
Rails.application.config.action_dispatch.default_headers = {
  "X-Frame-Options" => "SAMEORIGIN",
  "X-XSS-Protection" => "0",
  "X-Content-Type-Options" => "nosniff",
  "X-Permitted-Cross-Domain-Policies" => "none",
  "Referrer-Policy" => "strict-origin-when-cross-origin"
}

###
# Do not treat an `ActionController::Parameters` instance
# as equal to an equivalent `Hash` by default.
#++
Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false

###
# Active Record Encryption now uses SHA-256 as its hash digest algorithm.
#
# There are 3 scenarios to consider.
#
# 1. If you have data encrypted with previous Rails versions, and you have
# +config.active_support.key_generator_hash_digest_class+ configured as SHA1 (the default
# before Rails 7.0), you need to configure SHA-1 for Active Record Encryption too:
#++
# Rails.application.config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1
#
# 2. If you have +config.active_support.key_generator_hash_digest_class+ configured as SHA256 (the new default
# in 7.0), then you need to configure SHA-256 for Active Record Encryption:
#++
# Rails.application.config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA256
#
# 3. If you don't currently have data encrypted with Active Record encryption, you can disable this setting to
# configure the default behavior starting 7.1+:
#++
Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = false

###
# No longer run after_commit callbacks on the first of multiple Active Record
# instances to save changes to the same database row within a transaction.
# Instead, run these callbacks on the instance most likely to have internal
# state which matches what was committed to the database, typically the last
# instance to save.
#++
Rails.application.config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction = false

###
# Configures SQLite with a strict strings mode, which disables double-quoted string literals.
#
# SQLite has some quirks around double-quoted string literals.
# It first tries to consider double-quoted strings as identifier names, but if they don't exist
# it then considers them as string literals. Because of this, typos can silently go unnoticed.
# For example, it is possible to create an index for a non existing column.
# See https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted for more details.
#++
Rails.application.config.active_record.sqlite3_adapter_strict_strings_by_default = true

###
# Disable deprecated singular associations names.
#++
Rails.application.config.active_record.allow_deprecated_singular_associations_name = false

###
# Enable the Active Job `BigDecimal` argument serializer, which guarantees
# roundtripping. Without this serializer, some queue adapters may serialize
# `BigDecimal` arguments as simple (non-roundtrippable) strings.
#
# When deploying an application with multiple replicas, old (pre-Rails 7.1)
# replicas will not be able to deserialize `BigDecimal` arguments from this
# serializer. Therefore, this setting should only be enabled after all replicas
# have been successfully upgraded to Rails 7.1.
#++
# Rails.application.config.active_job.use_big_decimal_serializer = true

###
# Specify if an `ArgumentError` should be raised if `Rails.cache` `fetch` or
# `write` are given an invalid `expires_at` or `expires_in` time.
# Options are `true`, and `false`. If `false`, the exception will be reported
# as `handled` and logged instead.
#++
Rails.application.config.active_support.raise_on_invalid_cache_expiration_time = true

###
# Specify whether Query Logs will format tags using the SQLCommenter format
# (https://open-telemetry.github.io/opentelemetry-sqlcommenter/), or using the legacy format.
# Options are `:legacy` and `:sqlcommenter`.
#++
Rails.application.config.active_record.query_log_tags_format = :sqlcommenter

###
# Specify the default serializer used by `MessageEncryptor` and `MessageVerifier`
# instances.
#
# The legacy default is `:marshal`, which is a potential vector for
# deserialization attacks in cases where a message signing secret has been
# leaked.
#
# In Rails 7.1, the new default is `:json_allow_marshal` which serializes and
# deserializes with `ActiveSupport::JSON`, but can fall back to deserializing
# with `Marshal` so that legacy messages can still be read.
#
# In Rails 7.2, the default will become `:json` which serializes and
# deserializes with `ActiveSupport::JSON` only.
#
# Alternatively, you can choose `:message_pack` or `:message_pack_allow_marshal`,
# which serialize with `ActiveSupport::MessagePack`. `ActiveSupport::MessagePack`
# can roundtrip some Ruby types that are not supported by JSON, and may provide
# improved performance, but it requires the `msgpack` gem.
#
# For more information, see
# https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer
#
# If you are performing a rolling deploy of a Rails 7.1 upgrade, wherein servers
# that have not yet been upgraded must be able to read messages from upgraded
# servers, first deploy without changing the serializer, then set the serializer
# in a subsequent deploy.
#++
Rails.application.config.active_support.message_serializer = :json_allow_marshal

###
# Enable a performance optimization that serializes message data and metadata
# together. This changes the message format, so messages serialized this way
# cannot be read by older versions of Rails. However, messages that use the old
# format can still be read, regardless of whether this optimization is enabled.
#
# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have
# not yet been upgraded must be able to read messages from upgraded servers,
# leave this optimization off on the first deploy, then enable it on a
# subsequent deploy.
#++
Rails.application.config.active_support.use_message_serializer_for_metadata = true

###
# Set the maximum size for Rails log files.
#
# `config.load_defaults 7.1` does not set this value for environments other than
# development and test.
#++
Rails.application.config.log_file_size = 100 * 1024 * 1024 if Rails.env.local?

###
# Enable raising on assignment to attr_readonly attributes. The previous
# behavior would allow assignment but silently not persist changes to the
# database.
#++
Rails.application.config.active_record.raise_on_assign_to_attr_readonly = true

###
# Enable validating only parent-related columns for presence when the parent is mandatory.
# The previous behavior was to validate the presence of the parent record, which performed an extra query
# to get the parent every time the child record was updated, even when parent has not changed.
#++
Rails.application.config.active_record.belongs_to_required_validates_foreign_key = false

###
# Enable precompilation of `config.filter_parameters`. Precompilation can
# improve filtering performance, depending on the quantity and types of filters.
#++
Rails.application.config.precompile_filter_parameters = true

###
# Enable before_committed! callbacks on all enrolled records in a transaction.
# The previous behavior was to only run the callbacks on the first copy of a record
# if there were multiple copies of the same record enrolled in the transaction.
#++
Rails.application.config.active_record.before_committed_on_all_records = true

###
# Disable automatic column serialization into YAML.
# To keep the historic behavior, you can set it to `YAML`, however it is
# recommended to explicitly define the serialization method for each column
# rather than to rely on a global default.
#++
Rails.application.config.active_record.default_column_serializer = nil

###
# Enable a performance optimization that serializes Active Record models
# in a faster and more compact way.
#
# To perform a rolling deploy of a Rails 7.1 upgrade, wherein servers that have
# not yet been upgraded must be able to read caches from upgraded servers,
# leave this optimization off on the first deploy, then enable it on a
# subsequent deploy.
#++
# Rails.application.config.active_record.marshalling_format_version = 7.1

###
# Run `after_commit` and `after_*_commit` callbacks in the order they are defined in a model.
# This matches the behaviour of all other callbacks.
# In previous versions of Rails, they ran in the inverse order.
#++
Rails.application.config.active_record.run_after_transaction_callbacks_in_order_defined = true

###
# Whether a `transaction` block is committed or rolled back when exited via `return`, `break` or `throw`.
#++
Rails.application.config.active_record.commit_transaction_on_non_local_return = true

###
# Controls when to generate a value for <tt>has_secure_token</tt> declarations.
#++
Rails.application.config.active_record.generate_secure_token_on = :initialize

###
# ** Please read carefully, this must be configured in config/application.rb **
#
# Change the format of the cache entry.
#
# Changing this default means that all new cache entries added to the cache
# will have a different format that is not supported by Rails 7.0
# applications.
#
# Only change this value after your application is fully deployed to Rails 7.1
# and you have no plans to rollback.
# When you're ready to change format, add this to `config/application.rb` (NOT
# this file):
#   config.active_support.cache_format_version = 7.1

###
# Configure Action View to use HTML5 standards-compliant sanitizers when they are supported on your
# platform.
#
# `Rails::HTML::Sanitizer.best_supported_vendor` will cause Action View to use HTML5-compliant
# sanitizers if they are supported, else fall back to HTML4 sanitizers.
#
# In previous versions of Rails, Action View always used `Rails::HTML4::Sanitizer` as its vendor.
#++
Rails.application.config.action_view.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor

###
# Configure Action Text to use an HTML5 standards-compliant sanitizer when it is supported on your
# platform.
#
# `Rails::HTML::Sanitizer.best_supported_vendor` will cause Action Text to use HTML5-compliant
# sanitizers if they are supported, else fall back to HTML4 sanitizers.
#
# In previous versions of Rails, Action Text always used `Rails::HTML4::Sanitizer` as its vendor.
#++
Rails.application.config.action_text.sanitizer_vendor = Rails::HTML::Sanitizer.best_supported_vendor

###
# Configure the log level used by the DebugExceptions middleware when logging
# uncaught exceptions during requests.
#++
Rails.application.config.action_dispatch.debug_exception_log_level = :error

###
# Configure the test helpers in Action View, Action Dispatch, and rails-dom-testing to use HTML5
# parsers.
#
# Nokogiri::HTML5 isn't supported on JRuby, so JRuby applications must set this to :html4.
#
# In previous versions of Rails, these test helpers always used an HTML4 parser.
#++
Rails.application.config.dom_testing_default_html_version = :html5


================================================
FILE: config/initializers/non_digest_assets.rb
================================================
# frozen_string_literal: true

NonDigestAssets.asset_selectors = [/\.(?:svg|eot|woff|ttf)$/]


================================================
FILE: config/initializers/permissions_policy.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# Define an application-wide HTTP permissions policy. For further
# information see: https://developers.google.com/web/updates/2018/06/feature-policy

# Rails.application.config.permissions_policy do |policy|
#   policy.camera      :none
#   policy.gyroscope   :none
#   policy.microphone  :none
#   policy.usb         :none
#   policy.fullscreen  :self
#   policy.payment     :self, "https://secure.example.com"
# end


================================================
FILE: config/initializers/rack_attack.rb
================================================
# frozen_string_literal: true

# Throttle login attempts
Rack::Attack.throttle("logins/ip", limit: 20, period: 1.hour) do |req|
  req.ip if req.post? && req.path.start_with?("/users/sign_in")
end

# Throttle password reset attempts
Rack::Attack.throttle("password-reset-requests/ip", limit: 20, period: 1.hour) do |req|
  req.ip if req.post? && req.path.start_with?("/users/password")
end

ActiveSupport::Notifications
  .subscribe("rack.attack") do |_name, _start, _finish, _request_id, req|
  Rails.logger.info "Throttled #{req.env["rack.attack.match_discriminator"]}"
end


================================================
FILE: config/initializers/recaptcha.rb
================================================
# frozen_string_literal: true

Recaptcha.configure do |config|
  config.site_key = "YourAPIkeysHere_yyyyyyyyyyyyyyyyy"
  config.secret_key = "YourAPIkeysHere_xxxxxxxxxxxxxxxxx"
end


================================================
FILE: config/initializers/session_store.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

Rails.application.config.session_store(:active_record_store,
                                       key: "_publify_blog_session",
                                       secure: Rails.env.production?)


================================================
FILE: config/initializers/wrap_parameters.rb
================================================
# frozen_string_literal: true

# Be sure to restart your server when you modify this file.

# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.

# Enable parameter wrapping for JSON. You can disable this by setting :format
# to an empty array.
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end

# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
#   self.include_root_in_json = true
# end


================================================
FILE: config/locales/ar.yml
================================================
---
ar:
  articles:
    comment_counter:
      comments:
        few: بعض التعليقات
        many: أكثر من تعليق
        one: 1 تعليق
        other: "%{count} تعليقات"
        two: تعليقان
        zero: لا توجد تعليقات
    comment_form:
      comment: تعليق
      email_address: عنوان البريد الإلكتروني
      your_website: موقعك
    meta:
      published_on_html: تم النشر في %{publish_date_and_time} بواسطة %{by}, علامات
        %{tags}
    read:
      add_me_to_twitter: تابعني على تويتر
      if_you_liked_this_article_you_can_html: لو أعجبتك هذه المقالة يمكنك %{add_twitter}
      trackbacks_for: التتبع لـ
    search:
      search_results_for: نتائج البحث لـ '%{query}'
  comments:
    comment:
      by: بواسطة
  layouts:
    default:
      archives: أرشيفات
      statuses: حالات
  pagination:
    next: القادم
    previous: السابق


================================================
FILE: config/locales/da.yml
================================================
---
da:
  articles:
    comment_counter:
      comments:
        one: 1 kommentar
        other: "%{count} kommentarer"
        zero: Ingen kommentarer
    comment_form:
      comment: Kommenter
      email_address: Email adresse
      your_website: Din hjemmeside
    meta:
      published_on_html: Udgivet %{publish_date_and_time} af %{by}, tags %{tags}
    read:
      add_me_to_twitter: Tilføj mig på Twitter
      if_you_liked_this_article_you_can_html: Hvis du kan lide denne artikel så %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Søgeresultater for '%{query}'
  comments:
    comment:
      by: af
  layouts:
    default:
      archives: Arkiver
      statuses: Statuser
  pagination:
    next: Næste
    previous: Forrige


================================================
FILE: config/locales/de.yml
================================================
---
de:
  articles:
    comment_counter:
      comments:
        one: 1 kommentar
        other: "%{count} kommentare"
        zero: no kommentare
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: bei
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/en.yml
================================================
---
en:
  articles:
    comment_counter:
      comments:
        one: 1 comment
        other: "%{count} comments"
        zero: no comments
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: follow me on Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: by
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/es-MX.yml
================================================
---
es-MX:
  articles:
    comment_counter:
      comments:
        one: 1 Comentario
        other: "%{count} Comentarios"
        zero: Sin Comentarios
    comment_form:
      comment: comentario
      email_address: Email
      your_website: Tu sitio web
    meta:
      published_on_html: Publicado el %{publish_date_and_time} por %{by}, tags %{tags}
    read:
      add_me_to_twitter: agregame en Twitter
      if_you_liked_this_article_you_can_html: Si le gust&oacute; este art&iacute;culo,
        usted puede %{add_twitter}
      trackbacks_for: Trackbacks para
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: por
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/fr.yml
================================================
---
fr:
  articles:
    comment_counter:
      comments:
        one: 1 commentaire
        other: "%{count} commentaires"
        zero: aucun commentaire
    comment_form:
      comment: commentaire
      email_address: Adresse mail
      your_website: Votre site
    meta:
      published_on_html: Publié le %{publish_date_and_time} par %{by}, tags %{tags}
    read:
      add_me_to_twitter: me suivre sur Twitter
      if_you_liked_this_article_you_can_html: Si vous avez aimé cet article, vous
        pouvez %{add_twitter}
      trackbacks_for: Rétroliens pour
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: par
  layouts:
    default:
      archives: Archives
      statuses: Statuts
  pagination:
    next: Suivant
    previous: Previous


================================================
FILE: config/locales/he.yml
================================================
---
he:
  articles:
    comment_counter:
      comments:
        one: 1 comment
        other: "%{count} comments"
        zero: ללא תגובות
    comment_form:
      comment: תגובה
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: by
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/it.yml
================================================
---
it:
  articles:
    comment_counter:
      comments:
        one: 1 Commento
        other: "%{count} Commenti"
        zero: no comments
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: da
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/ja.yml
================================================
---
ja:
  articles:
    comment_counter:
      comments:
        one: 1 comment
        other: "%{count} comments"
        zero: no comments
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: by
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/lt.yml
================================================
---
lt:
  articles:
    comment_counter:
      comments:
        few: "%{count} Komentarai"
        one: 1 Komentaras
        other: "%{count} Komentarai"
        zero: no comments
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: bei
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/nb.yml
================================================
---
nb:
  articles:
    comment_counter:
      comments:
        one: 1 kommentar
        other: "%{count} kommentarer"
        zero: ingen kommentarer
    comment_form:
      comment: kommentar
      email_address: Epostadresse
      your_website: Din hjemmeside
    meta:
      published_on_html: Publisert den %{publish_date_and_time} av %{by}, tagger %{tags}
    read:
      add_me_to_twitter: legge meg til på Twitter
      if_you_liked_this_article_you_can_html: Hvis du likte denne artikkelen, kan
        du %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: av
  layouts:
    default:
      archives: Archives
      statuses: Statusoppdateringer
  pagination:
    next: Neste
    previous: Forrige


================================================
FILE: config/locales/nl.yml
================================================
---
nl:
  articles:
    comment_counter:
      comments:
        one: 1 comment
        other: "%{count} comments"
        zero: Geen reacties
    comment_form:
      comment: reactie
      email_address: E-mailadres
      your_website: Je website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: by
  layouts:
    default:
      archives: Archieven
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/pl.yml
================================================
---
pl:
  articles:
    comment_counter:
      comments:
        few: "%{count} komentarzy"
        many: "%{count} komentarzy"
        one: 1 komentarz
        other: "%{count} komentarzy"
        zero: brak komentarzy
    comment_form:
      comment: komentarz
      email_address: Adres email
      your_website: Twoja strona www
    meta:
      published_on_html: 'Opublikowano %{publish_date_and_time} przez %{by}, tagi:
        %{tags}'
    read:
      add_me_to_twitter: obserwuj mnie na Twitterze
      if_you_liked_this_article_you_can_html: Jeżeli podobał Ci się ten wpis,  %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Wyniki wyszukiwania dla '%{query}'
  comments:
    comment:
      by: przez
  layouts:
    default:
      archives: Archiwum
      statuses: Statusy
  pagination:
    next: Następne
    previous: Poprzednie


================================================
FILE: config/locales/pt-BR.yml
================================================
---
pt-BR:
  articles:
    comment_counter:
      comments:
        one: 1 comentário
        other: "%{count} comentários"
        zero: nenhum comentário
    comment_form:
      comment: Comentário
      email_address: Endereço de e-mail
      your_website: Seu website
    meta:
      published_on_html: Publicado em %{publish_date_and_time} por %{by}, tags %{tags}
    read:
      add_me_to_twitter: me adicionar no Twitter
      if_you_liked_this_article_you_can_html: Se você gostou deste artigo, você pode
        %{add_twitter}
      trackbacks_for: Trackbacks para
    search:
      search_results_for: Resultados de busca para '%{query}'
  comments:
    comment:
      by: por
  layouts:
    default:
      archives: Arquivos
      statuses: Status
  pagination:
    next: Próxima
    previous: Anterior


================================================
FILE: config/locales/ro.yml
================================================
---
ro:
  articles:
    comment_counter:
      comments:
        few: "%{count} comentarii"
        one: 1 comentariu
        other: "%{count} comentarii"
        zero: no comentarii
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: de
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/ru.yml
================================================
---
ru:
  articles:
    comment_counter:
      comments:
        few: 'Комментариев: %{count}'
        many: 'Комментариев: %{count}'
        one: 1 комментарий
        other: 'Комментариев: %{count}'
        zero: Нет комментариев
    comment_form:
      comment: Ответить на пост
      email_address: Электронная почта
      your_website: Веб-сайт
    meta:
      published_on_html: Опубликовано %{publish_date_and_time} автором %{by} под тегами
        %{tags}
    read:
      add_me_to_twitter: отправить в Twitter
      if_you_liked_this_article_you_can_html: Если Вам понравилась эта статья Вы можете
        %{add_twitter}
      trackbacks_for: Обратные ссылки для
    search:
      search_results_for: Результаты поиска для '%{query}'
  comments:
    comment:
      by: от
  layouts:
    default:
      archives: Архивы
      statuses: Статусы
  pagination:
    next: Следующая
    previous: Предыдущая


================================================
FILE: config/locales/sidebars.ar.yml
================================================
---
ar:
  authors_sidebar:
    content:
      authors: مؤلفين
  notes_sidebar:
    content:
      view_on_twitter: شاهد على تويتر
  popular_sidebar:
    content:
      comments: تعليقات
      nothing_to_show_yet: لا يوجد شئ لعرضه
  xml_sidebar:
    content:
      articles: مقالات
      feedback: ردود الفعل
      syndicate: نقابة
      tag: علامة


================================================
FILE: config/locales/sidebars.da.yml
================================================
---
da:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.de.yml
================================================
---
de:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.en.yml
================================================
---
en:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.es-MX.yml
================================================
---
es-MX:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.fr.yml
================================================
---
fr:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.he.yml
================================================
---
he:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.it.yml
================================================
---
it:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.ja.yml
================================================
---
ja:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.lt.yml
================================================
---
lt:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.nb.yml
================================================
---
nb:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.nl.yml
================================================
---
nl:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.pl.yml
================================================
---
pl:
  authors_sidebar:
    content:
      authors: Autorzy
  notes_sidebar:
    content:
      view_on_twitter: Zobacz na Twitterze
  popular_sidebar:
    content:
      comments: Komentarze
      nothing_to_show_yet: Brak komentarzy
  xml_sidebar:
    content:
      articles: Artykuły
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.pt-BR.yml
================================================
---
pt-BR:
  authors_sidebar:
    content:
      authors: Autores
  notes_sidebar:
    content:
      view_on_twitter: Ver no Twitter
  popular_sidebar:
    content:
      comments: Comentários
      nothing_to_show_yet: Nada a exibir no momento
  xml_sidebar:
    content:
      articles: Artigos
      feedback: Feedback
      syndicate: Sindicato
      tag: Tag


================================================
FILE: config/locales/sidebars.ro.yml
================================================
---
ro:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.ru.yml
================================================
---
ru:
  authors_sidebar:
    content:
      authors: Авторы
  notes_sidebar:
    content:
      view_on_twitter: Просмотреть в Twitter
  popular_sidebar:
    content:
      comments: Комментарии
      nothing_to_show_yet: Пока что тут ничего нет
  xml_sidebar:
    content:
      articles: Статьи
      feedback: Отзыв
      syndicate: Синдикат
      tag: Тег


================================================
FILE: config/locales/sidebars.zh-CN.yml
================================================
---
zh-CN:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/sidebars.zh-TW.yml
================================================
---
zh-TW:
  authors_sidebar:
    content:
      authors: Authors
  notes_sidebar:
    content:
      view_on_twitter: View on Twitter
  popular_sidebar:
    content:
      comments: Comments
      nothing_to_show_yet: Nothing to show yet
  xml_sidebar:
    content:
      articles: Articles
      feedback: Feedback
      syndicate: Syndicate
      tag: Tag


================================================
FILE: config/locales/zh-CN.yml
================================================
---
zh-CN:
  articles:
    comment_counter:
      comments:
        one: 1 comment
        other: "%{count} comments"
        zero: no comments
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: by
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/locales/zh-TW.yml
================================================
---
zh-TW:
  articles:
    comment_counter:
      comments:
        one: 1 comment
        other: "%{count} comments"
        zero: no comments
    comment_form:
      comment: comment
      email_address: Email address
      your_website: Your website
    meta:
      published_on_html: Published on %{publish_date_and_time} by %{by}, tags %{tags}
    read:
      add_me_to_twitter: add me to Twitter
      if_you_liked_this_article_you_can_html: If you liked this article you can %{add_twitter}
      trackbacks_for: Trackbacks for
    search:
      search_results_for: Search results for '%{query}'
  comments:
    comment:
      by: by
  layouts:
    default:
      archives: Archives
      statuses: Statuses
  pagination:
    next: Next
    previous: Previous


================================================
FILE: config/mail.yml.example
================================================
delivery_method: :smtp
settings:
  :address: mail.example.com
  :port:    25
  :domain:  example.com
# :authentication:  :login
# :user_name: bob
# :password: bobsyouruncle
sendmail_settings:
  :location: /usr/bin/sendmail


================================================
FILE: config/puma.rb
================================================
# frozen_string_literal: true

# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5)
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port        ENV.fetch("PORT", 3000)

# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV", "development")

# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch("PIDFILE", "tmp/pids/server.pid")

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
# preload_app!

# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart


================================================
FILE: config/routes.rb
================================================
# frozen_string_literal: true

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end


================================================
FILE: config/secrets.yml
================================================
# Be sure to restart your server when you modify this file.

# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!

# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rails secret` to generate a secure secret key.

# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.

development:
  secret_key_base: 189eafa373f70c3f770798b832dd5e48e3042c03639a6a1dc952c6b88eaed9b418d010874932a5f1b1d1d0453102160190729d1a04c453f9eb3639073c645311

test:
  secret_key_base: 81a64773cabdd99b20a666b0d1cbe69b27cd3eb6ea3213740016c8dff97f69d56ac092fb50c9a20b6c64e32b066d4970e4a1dc2d44c87b0dd86b5eea98a0a181

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>


================================================
FILE: config/spring.rb
================================================
# frozen_string_literal: true

%w(
  .ruby-version
  .rbenv-vars
  tmp/restart.txt
  tmp/caching-dev.txt
).each { |path| Spring.watch(path) }


================================================
FILE: config/storage.yml
================================================
test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
# amazon:
#   service: S3
#   access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
#   secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
#   region: us-east-1
#   bucket: your_own_bucket

# Remember not to checkin your GCS keyfile to a repository
# google:
#   service: GCS
#   project: your_project
#   credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
#   bucket: your_own_bucket

# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
# microsoft:
#   service: AzureStorage
#   storage_account_name: your_account_name
#   storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
#   container: your_container_name

# mirror:
#   service: Mirror
#   primary: local
#   mirrors: [ amazon, google, microsoft ]


================================================
FILE: config.ru
================================================
# frozen_string_literal: true

# This file is used by Rack-based servers to start the application.

require_relative "config/environment"

run Rails.application
Rails.application.load_server


================================================
FILE: db/converters/README
================================================
These are converters for migrating from other blog systems to Publify. In
general, you're best off using the converter that best-matches your blog
system, and then falling back to the RSS or Feed converter if the others fail.
These converters aren't always well tested, so please back up your data before
converting, and please file bugs at https://github.com/publify/publify.

Available converters:

* feed.rb: Converts from any RSS or Atom feed.  Requires the 'feed_tools' gem.
* blogger.rb: Converts from an exported Blogger XML.  Requires the 'feedzirra' gem.


================================================
FILE: db/converters/blogger.rb
================================================
#!/usr/bin/env ruby

# Blogger converter to publify
# Shamelessly copied from the RSS/Atom converter by Lennon Day-Reynolds

require File.dirname(__FILE__) + '/../../config/environment'
require 'optparse'
require 'feedzirra'

class BloggerConverter
  BLOGGER_POST = 'http://schemas.google.com/blogger/2008/kind#post'.freeze

  attr_accessor :options

  def initialize
    self.options = {}
    parse_options
    convert_entries
  end

  def convert_entries
    feed = Feedzirra::Feed.fetch_and_parse(options[:url])
    puts "Converting #{feed.entries.length} entries..."

    # TODO: Allow setting the blog to be used.
    blog = Blog.first
    ping_store = blog.send_outbound_pings
    blog.send_outbound_pings = false # pings have to be diabled or the script crashes because too many connections are opened
    blog.save

    feed.entries.each do |item|
      create_article item if item.categories.include? BLOGGER_POST
    end

    blog.send_outbound_pings = ping_store
    blog.save
  end

  # FIXME: This is probably broken
  def create_article(entry)
    a = Article.new
    entry_author = create_author entry.author
    a.set_author entry_author
    a.title = entry.title
    a.body = entry.content
    a.created_at = entry.published
    a.published_at = entry.published
    a.text_filter_id = 1
    a.add_category Category.first
    a.keywords = entry.categories - [BLOGGER_POST]
    a.allow_pings = false
    a.allow_comments = false

    puts "Converted '#{entry.title}'" if a.save
  end

  def create_author(name)
    unless User.exists? name: name
      user = User.new
      para = { 'login' => name,
               'name'  => name,
               'nickname' => name,
               'email' => name + '@fake.com',
               'password' => 'password',
               'profile_id' => 2,
               'notify_via_email' => false,
               'notify_on_comments' => false,
               'notify_on_new_articles' => false,
               'text_filter_id' => 1 }
      user.attributes = para
      user.save
    end

    User.where(name: name).first
  end

  def parse_options
    OptionParser.new do |opt|
      opt.banner = 'Usage: feed.rb [options]'

      opt.on('-u', '--url URL', 'URL of RSS feed to import.') do |u|
        options[:url] = u
      end

      opt.on_tail('-h', '--help', 'Show this message.') do
        puts opt
        exit
      end

      opt.parse!(ARGV)
    end

    unless options.include?(:url)
      puts 'See feed.rb --help for help.'
      exit
    end
  end
end

BloggerConverter.new


================================================
FILE: db/converters/feed.rb
================================================
#!/usr/bin/env ruby

# RSS 0.2/2.0/Atom converter to publify by Lennon Day-Reynolds <rcoder@gmail.com>
# Shamelessly copied from RSS-only converter by Chris Lee

require File.dirname(__FILE__) + '/../../config/environment'
require 'optparse'
begin
  require 'feed_tools'
rescue LoadError
  STDERR.puts <<-EOF.strip_heredoc
    This converter requires feedtools to be installed.
    Please run `gem install feedtools` and try again.
EOF
  exit 1
end

class FeedMigrate
  attr_accessor :options

  def initialize
    self.options = {}
    parse_options
    convert_entries
  end

  def convert_entries
    feed = FeedTools::Feed.open(options[:url])
    puts "Converting #{feed.items.length} entries..."
    feed.items.each do |item|
      puts "Converting '#{item.title}'"
      a = Article.new
      a.author = options[:author]
      a.title = item.title
      a.body = item.description
      a.created_at = item.published
      a.save
    end
  end

  def parse_options
    OptionParser.new do |opt|
      opt.banner = 'Usage: feed.rb [options]'

      opt.on('-a', '--author AUTHOR', 'Username of author in publify') do |a|
        options[:author] = a
      end

      opt.on('-u', '--url URL', 'URL of RSS feed to import.') do |u|
        options[:url] = u
      end

      opt.on_tail('-h', '--help', 'Show this message.') do
        puts opt
        exit
      end

      opt.parse!(ARGV)
    end

    unless options.include?(:author) && options.include?(:url)
      puts 'See feed.rb --help for help.'
      exit
    end
  end
end

FeedMigrate.new


================================================
FILE: db/converters/rss.rb
================================================
#!/usr/bin/env ruby

# RSS 0.9/2.0 converter for publify by Chris Lee <clee@kde.org>
#
# No need to make a backup of the original blog, really. This takes a URL for a
# read-only import, so there's not really any chance of it munging the original
# blog's data, unless somehow an HTTP GET causes your blog server to ignite.
#
# Even so, this script is still PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.

require File.dirname(__FILE__) + '/../../config/environment'
require 'optparse'
require 'net/http'
require 'rss/2.0'

class RSSMigrate
  attr_accessor :options

  def initialize
    self.options = {}
    parse_options
    convert_entries
  end

  def convert_entries
    feed = Net::HTTP.get(URI.parse(options[:url]))
    rss = RSS::Parser.parse(feed)
    puts "Converting #{rss.items.length} entries..."
    rss.items.each do |item|
      puts "Converting '#{item.title}'"
      a = Article.new
      a.author = options[:author]
      a.title = item.title
      a.body = item.description
      a.created_at = item.pubDate
      a.save
    end
  end

  def parse_options
    OptionParser.new do |opt|
      opt.banner = 'Usage: rss.rb [options]'

      opt.on('-a', '--author AUTHOR', 'Username of author in publify') do |a|
        options[:author] = a
      end

      opt.on('-u', '--url URL', 'URL of RSS feed to import.') do |u|
        options[:url] = u
      end

      opt.on_tail('-h', '--help', 'Show this message.') do
        puts opt
        exit
      end

      opt.parse!(ARGV)
    end

    unless options.include?(:author) && options.include?(:url)
      puts 'See rss.rb --help for help.'
      exit
    end
  end
end

RSSMigrate.new


================================================
FILE: db/migrate/113_initial_schema.publify_core_engine.rb
================================================
# frozen_string_literal: true

class InitialSchema < ActiveRecord::Migration[4.2]
  def change
    create_table "articles_tags", id: false, force: true do |t|
      t.integer "article_id"
      t.integer "tag_id"
    end

    create_table "blogs", force: true do |t|
      t.text   "settings"
      t.string "base_url"
    end

    create_table "categories", force: true do |t|
      t.string  "name"
      t.integer "position"
      t.string  "permalink"
      t.text    "keywords"
      t.text    "description"
      t.integer "parent_id"
    end

    add_index "categories", ["permalink"]

    create_table "categorizations", force: true do |t|
      t.integer "article_id"
      t.integer "category_id"
      t.boolean "is_primary"
    end

    create_table "contents", force: true do |t|
      t.string   "type"
      t.string   "title"
      t.string   "author"
      t.text     "body"
      t.text     "extended"
      t.text     "excerpt"
      t.datetime "created_at"
      t.datetime "updated_at"
      t.integer  "user_id"
      t.string   "permalink"
      t.string   "guid"
      t.integer  "text_filter_id"
      t.text     "whiteboard"
      t.string   "name"
      t.boolean  "published", default: false
      t.boolean  "allow_pings"
      t.boolean  "allow_comments"
      t.datetime "published_at"
      t.string   "state"
      t.integer  "parent_id"
      t.text     "settings"
      t.string   "post_type", default: "read"
    end

    add_index "contents", ["published"]
    add_index "contents", ["text_filter_id"]

    create_table "feedback", force: true do |t|
      t.string   "type"
      t.string   "title"
      t.string   "author"
      t.text     "body"
      t.text     "excerpt"
      t.datetime "created_at"
      t.datetime "updated_at"
      t.integer  "user_id"
      t.string   "guid"
      t.integer  "text_filter_id"
      t.text     "whiteboard"
      t.integer  "article_id"
      t.string   "email"
      t.string   "url"
      t.string   "ip", limit: 40
      t.string   "blog_name"
      t.boolean  "published", default: false
      t.datetime "published_at"
      t.string   "state"
      t.boolean  "status_confirmed"
      t.string   "user_agent"
    end

    add_index "feedback", ["article_id"]
    add_index "feedback", ["text_filter_id"]

    create_table "page_caches", force: true do |t|
      t.string "name"
    end

    add_index "page_caches", ["name"]

    create_table "pings", force: true do |t|
      t.integer  "article_id"
      t.string   "url"
      t.datetime "created_at"
    end

    add_index "pings", ["article_id"]

    create_table "post_types", force: true do |t|
      t.string "name"
      t.string "permalink"
      t.string "description"
    end

    create_table "profiles", force: true do |t|
      t.string "label"
      t.string "nicename"
      t.text   "modules"
    end

    create_table "profiles_rights", id: false, force: true do |t|
      t.integer "profile_id"
      t.integer "right_id"
    end

    create_table "redirections", force: true do |t|
      t.integer "content_id"
      t.integer "redirect_id"
    end

    create_table "redirects", force: true do |t|
      t.string   "from_path"
      t.string   "to_path"
      t.string   "origin"
      t.datetime "created_at"
      t.datetime "updated_at"
    end

    create_table "resources", force: true do |t|
      t.integer  "size"
      t.string   "upload"
      t.string   "mime"
      t.datetime "created_at"
      t.datetime "updated_at"
      t.integer  "article_id"
      t.boolean  "itunes_metadata"
      t.string   "itunes_author"
      t.string   "itunes_subtitle"
      t.integer  "itunes_duration"
      t.text     "itunes_summary"
      t.string   "itunes_keywords"
      t.string   "itunes_category"
      t.boolean  "itunes_explicit"
    end

    create_table "sidebars", force: true do |t|
      t.integer "active_position"
      t.text    "config"
      t.integer "staged_position"
      t.string  "type"
    end

    create_table "sitealizer", force: true do |t|
      t.string   "path"
      t.string   "ip"
      t.string   "referer"
      t.string   "language"
      t.string   "user_agent"
      t.datetime "created_at"
      t.date     "created_on"
    end

    create_table "tags", force: true do |t|
      t.string   "name"
      t.datetime "created_at"
      t.datetime "updated_at"
      t.string   "display_name"
    end

    create_table "text_filters", force: true do |t|
      t.string "name"
      t.string "description"
      t.string "markup"
      t.text   "filters"
      t.text   "params"
    end

    create_table "triggers", force: true do |t|
      t.integer  "pending_item_id"
      t.string   "pending_item_type"
      t.datetime "due_at"
      t.string   "trigger_method"
    end

    create_table "users", force: true do |t|
      t.string   "login"
      t.string   "password"
      t.text     "email"
      t.text     "name"
      t.boolean  "notify_via_email"
      t.boolean  "notify_on_new_articles"
      t.boolean  "notify_on_comments"
      t.integer  "profile_id"
      t.string   "remember_token"
      t.datetime "remember_token_expires_at"
      t.string   "text_filter_id",            default: "1"
      t.string   "state",                     default: "active"
      t.datetime "last_connection"
      t.text     "settings"
      t.integer  "resource_id"
    end
  end
end


================================================
FILE: db/migrate/114_fixes_buggy_articles_and_notes.publify_core_engine.rb
================================================
# frozen_string_literal: true

class FixesBuggyArticlesAndNotes < ActiveRecord::Migration[4.2]
  class Content < ActiveRecord::Base
  end

  class Article < Content
    def set_permalink
      return if state == "draft" || permalink.present?

      self.permalink = title.to_permalink
    end
  end

  class Note < Content
    def set_permalink
      self.permalink = "#{id}-#{body.to_permalink[0..79]}" if permalink.blank?
      save
    end

    def create_guid
      return true if guid.present?

      self.guid = UUIDTools::UUID.random_create.to_s
    end
  end

  class Page < Content
    def set_permalink
      self.name = title.to_permalink if name.blank?
    end
  end

  def self.up
    say "Fixing contents permalinks, this may take some time"

    contents = Content.where("permalink is ? or permalink = ?", nil, "")
    contents.each do |c|
      c.set_permalink
      c.save
    end

    say "Fixes empty notes GUID"
    notes = Note.where("guid is ? or guid = ?", nil, "")
    notes.each do |n|
      n.create_guid
      n.save
    end
  end

  def self.down
    say "Nothing to do here"
  end
end


================================================
FILE: db/migrate/115_drops_categories_for_tags.publify_core_engine.rb
================================================
# frozen_string_literal: true

class DropsCategoriesForTags < ActiveRecord::Migration[4.2]
  class Categorization < ActiveRecord::Base
    belongs_to :article
    belongs_to :category
  end

  class Category < ActiveRecord::Base
    has_many :categorizations
    has_many :articles, through: :categorizations
  end

  def up
    # First, we migrate categories into tags
    Category.find_each do |cat|
      # Does a tag with the same permalink exist?
      tag = Tag.find_or_create_by(name: cat.permalink) do |tg|
        tg.display_name = cat.name
      end

      Redirect.create(from_path: "category/#{cat.permalink}",
                      to_path: File.join(Blog.first.base_url, "tag", tag.name))
      cat.articles.each do |article|
        article.tags << tag
        article.save
      end
    end

    drop_table :categorizations
    drop_table :categories
  end

  def down; end
end


================================================
FILE: db/migrate/20150207131657_add_missing_indexes.publify_core_engine.rb
================================================
# frozen_string_literal: true

class AddMissingIndexes < ActiveRecord::Migration[4.2]
  def change
    add_index :feedback, [:id, :type]
    add_index :feedback, :user_id
    add_index :sidebars, [:id, :type]
    add_index :contents, :user_id
    add_index :contents, [:id, :type]
    add_index :articles_tags, :tag_id
    add_index :articles_tags, :article_id
    add_index :profiles_rights, :profile_id
    add_index :users, :profile_id
    add_index :users, :text_filter_id
    add_index :users, :resource_id
    add_index :triggers, [:pending_item_id, :pending_item_type]
    add_index :redirections, :content_id
    add_index :redirections, :redirect_id
    add_index :resources, :article_id
  end
end


================================================
FILE: db/migrate/20150807134129_simplify_redirect_relations.publify_core_engine.rb
================================================
# frozen_string_literal: true

class SimplifyRedirectRelations < ActiveRecord::Migration[4.2]
  class Redirect < ActiveRecord::Base; end

  class Redirection < ActiveRecord::Base; end

  def up
    add_column :redirects, :content_id, :integer
    Redirect.find_each do |redirect|
      redirections = Redirection.where(redirect_id: redirect.id)
      if redirections.many?
        raise "Expected zero or one redirections, found #{redirections.count}"
      end

      redirection = redirections.first
      next unless redirection

      redirect.content_id = redirection.content_id
      redirect.save!
    end
    remove_column :redirects, :origin
    drop_table :redirections
  end

  def down
    create_table :redirections do |t|
      t.integer :content_id
      t.integer :redirect_id
    end

    add_index :redirections, [:content_id]
    add_index :redirections, [:redirect_id]

    add_column :redirects, :origin, :string

    Redirect.find_each do |redirect|
      next unless redirect.content_id

      Redirection.create(redirect_id: redirect.id, content_id: redirect.content_id)
    end
    remove_column :redirects, :content_id
  end
end


================================================
FILE: db/migrate/20150808052637_add_blog_ids.publify_core_engine.rb
================================================
# frozen_string_literal: true

class AddBlogIds < ActiveRecord::Migration[4.2]
  class Blog < ActiveRecord::Base; end

  class Content < ActiveRecord::Base; end

  class Sidebar < ActiveRecord::Base; end

  def up
    add_column :contents, :blog_id, :integer
    add_column :sidebars, :blog_id, :integer

    if Content.any? || Sidebar.any?
      default_blog_id = Blog.order(:id).first.id

      Content.update_all("blog_id = #{default_blog_id}")
      Sidebar.update_all("blog_id = #{default_blog_id}")
    end

    change_column :sidebars, :blog_id, :integer, null: false
  end

  def down
    if adapter_name == "PostgreSQL"
      indexes(:contents).each do |index|
        remove_index(:contents, name: index.name) if index.name.include?("blog_id")
      end
    else
      begin
        remove_index :contents, :blog_id
      rescue
        nil
      end
    end
    remove_column :contents, :blog_id
    remove_column :sidebars, :blog_id
  end
end


================================================
FILE: db/migrate/20150808191127_add_blog_id_to_redirects.publify_core_engine.rb
================================================
# frozen_string_literal: true

class AddBlogIdToRedirects < ActiveRecord::Migration[4.2]
  class Redirect < ActiveRecord::Base; end

  def up
    add_column :redirects, :blog_id, :integer
    if Redirect.any?
      default_blog_id = Blog.order(:id).first.id
      Redirect.update_all("blog_id = #{default_blog_id}")
    end
  end

  def down
    remove_column :redirects, :blog_id
  end
end


================================================
FILE: db/migrate/20150810094754_add_blog_id_to_tags.publify_core_engine.rb
================================================
# frozen_string_literal: true

class AddBlogIdToTags < ActiveRecord::Migration[4.2]
  class Tag < ActiveRecord::Base; end

  def up
    add_column :tags, :blog_id, :integer
    if Tag.any?
      default_blog_id = Blog.order(:id).first.id
      Tag.update_all("blog_id = #{default_blog_id}")
    end
  end

  def down
    remove_column :tags, :blog_id
  end
end


================================================
FILE: db/migrate/20160108111120_add_devise_to_users.publify_core_engine.rb
================================================
# frozen_string_literal: true

class AddDeviseToUsers < ActiveRecord::Migration[4.2]
  def self.up
    ## Database authenticatable
    change_column :users, :email, :string, null: false, default: ""
    rename_column :users, :password, :encrypted_password
    change_column :users, :encrypted_password, :string, null: false, default: ""

    change_table(:users) do |t|
      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      # Timestamps were not included in our original model.
      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
  end

  def self.down
    remove_index :users, :email
    remove_index :users, :reset_password_token

    remove_column :users, :created_at
    remove_column :users, :updated_at

    remove_column :users, :sign_in_count
    remove_column :users, :current_sign_in_at
    remove_column :users, :last_sign_in_at
    remove_column :users, :current_sign_in_ip
    remove_column :users, :last_sign_in_ip

    remove_column :users, :remember_created_at

    remove_column :users, :reset_password_token
    remove_column :users, :reset_password_sent_at

    change_column :users, :encrypted_password, :string, null: true, default: nil
    rename_column :users, :encrypted_password, :password
    change_column :users, :email, :text, null: true, default: nil
  end
end


================================================
FILE: db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.publify_core_engine.rb
================================================
# frozen_string_literal: true

class MoveLastConnectionToLastSignInAt < ActiveRecord::Migration[4.2]
  class User < ActiveRecord::Base
  end

  def up
    User.find_each do |user|
      user.update_attribute(:last_sign_in_at, user.last_connection)
    end
  end

  def down
    User.find_each do |user|
      user.update_attribute(:last_connection, user.last_sign_in_at)
    end
  end
end


================================================
FILE: db/migrate/20160110094906_remove_profiles_rights.publify_core_engine.rb
================================================
# frozen_string_literal: true

class RemoveProfilesRights < ActiveRecord::Migration[4.2]
  def up
    drop_table :profiles_rights
  end

  def down
    create_table :profiles_rights, id: false do |t|
      t.integer :profile_id
      t.integer :right_id
    end

    add_index :profiles_rights, [:profile_id]
  end
end


================================================
FILE: db/migrate/20160605103918_replace_profile_id_with_string.publify_core_engine.rb
================================================
# frozen_string_literal: true

class ReplaceProfileIdWithString < ActiveRecord::Migration[4.2]
  class Profile < ActiveRecord::Base
  end

  class User < ActiveRecord::Base
  end

  def up
    add_column :users, :profile, :string

    User.reset_column_information
    User.find_each do |user|
      user.update_attribute(:profile, Profile.find(user.profile_id).label)
    end

    remove_column :users, :profile_id
  end

  def down
    add_column :users, :profile_id, :integer

    User.reset_column_information
    User.find_each do |user|
      user.update_attribute(:profile_id, Profile.find_by(label: user.profile).id)
    end

    remove_column :users, :profile
  end
end


================================================
FILE: db/migrate/20160605154632_remove_profiles.publify_core_engine.rb
================================================
# frozen_string_literal: true

class RemoveProfiles < ActiveRecord::Migration[4.2]
  class Profile < ActiveRecord::Base
    serialize :modules, coder: YAML
  end

  def up
    drop_table :profiles
  end

  def down
    create_table :profiles do |t|
      t.string :label
      t.string :nicename
      t.text   :modules
    end

    Profile.create!(label: "admin", nicename: "Publify administrator",
                    modules: [:dashboard, :articles, :notes, :pages, :feedback,
                              :media, :themes, :sidebar, :profile, :users,
                              :settings, :seo])
    Profile.create!(label: "publisher", nicename: "Blog publisher",
                    modules: [:dashboard, :articles, :notes, :pages, :feedback,
                              :media, :profile])
    Profile.create!(label: "contributor", nicename: "Contributor",
                    modules: [:dashboard, :profile])
  end
end


================================================
FILE: db/migrate/20160701061851_demand_blog_id_on_contents.publify_core_engine.rb
================================================
# frozen_string_literal: true

class DemandBlogIdOnContents < ActiveRecord::Migration[4.2]
  def up
    change_column :contents, :blog_id, :integer, null: false
  end

  def down
    change_column :contents, :blog_id, :integer, null: true
  end
end


================================================
FILE: db/migrate/20160701062604_add_blog_id_to_resources.publify_core_engine.rb
================================================
# frozen_string_literal: true

class AddBlogIdToResources < ActiveRecord::Migration[4.2]
  class Blog < ActiveRecord::Base; end

  class Content < ActiveRecord::Base; end

  class Resource < ActiveRecord::Base; end

  def up
    add_column :resources, :blog_id, :integer

    if Resource.any?
      default_blog_id = Blog.order(:id).first.id
      Resource.find_each do |resource|
        content_id = resource.article_id
        blog_id = if content_id
                    Content.find(content_id).blog_id
                  else
                    default_blog_id
                  end
        resource.update_column(:blog_id, blog_id)
      end
    end

    change_column :resources, :blog_id, :integer, null: false
  end

  def down
    remove_column :resources, :blog_id
  end
end


================================================
FILE: db/migrate/20161030121548_add_sessions_table.rb
================================================
# frozen_string_literal: true

class AddSessionsTable < ActiveRecord::Migration[4.2]
  def change
    create_table :sessions do |t|
      t.string :session_id, null: false
      t.text :data
      t.timestamps null: false
    end

    add_index :sessions, :session_id, unique: true
    add_index :sessions, :updated_at
  end
end


================================================
FILE: db/migrate/20170528093428_move_resources_to_content.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20170528093024)
class MoveResourcesToContent < ActiveRecord::Migration[5.0]
  def change
    rename_column :resources, :article_id, :content_id
  end
end


================================================
FILE: db/migrate/20170528120220_move_tags_to_content.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20170528094923)
class MoveTagsToContent < ActiveRecord::Migration[5.0]
  def change
    rename_column :articles_tags, :article_id, :content_id
    rename_table :articles_tags, :contents_tags
  end
end


================================================
FILE: db/migrate/20170530063901_remove_separate_published_flag.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20170528201606)
class RemoveSeparatePublishedFlag < ActiveRecord::Migration[5.0]
  def change
    remove_column :contents, :published, :boolean, default: false
  end
end


================================================
FILE: db/migrate/20170605103539_remove_extra_state_columns_from_feedback.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20170605071626)
class RemoveExtraStateColumnsFromFeedback < ActiveRecord::Migration[5.0]
  def change
    remove_column :feedback, :published, :boolean, default: false
    remove_column :feedback, :status_confirmed, :boolean
  end
end


================================================
FILE: db/migrate/20170702105518_remove_published_at_from_feedback.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20170702105201)
class RemovePublishedAtFromFeedback < ActiveRecord::Migration[5.0]
  def change
    remove_column :feedback, :published_at, :datetime
  end
end


================================================
FILE: db/migrate/20190210121314_add_text_filter_name_fields.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20190208151235)
class AddTextFilterNameFields < ActiveRecord::Migration[5.2]
  def change
    add_column :contents, :text_filter_name, :string
    add_column :feedback, :text_filter_name, :string
    add_column :users, :text_filter_name, :string
  end
end


================================================
FILE: db/migrate/20190210121315_move_text_filter_to_name.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20190208152646)
class MoveTextFilterToName < ActiveRecord::Migration[5.2]
  class Content < ActiveRecord::Base
    self.inheritance_column = :bogus

    belongs_to :text_filter, optional: true
  end

  class Feedback < ActiveRecord::Base
    self.table_name = "feedback"
    self.inheritance_column = :bogus

    belongs_to :text_filter, optional: true
  end

  class User < ActiveRecord::Base
    belongs_to :text_filter, optional: true
  end

  class TextFilter < ActiveRecord::Base
    serialize :filters, Array, coder: YAML
    serialize :params, Hash, coder: YAML
  end

  def up
    Content.find_each do |content|
      filter = content.text_filter
      filter_name = filter&.name || "none"
      content.update!(text_filter_name: filter_name, text_filter_id: nil)
    end

    Feedback.find_each do |feedback|
      filter = feedback.text_filter
      filter_name = filter&.name || "none"
      feedback.update!(text_filter_name: filter_name, text_filter_id: nil)
    end

    User.find_each do |user|
      filter = user.text_filter
      filter_name = filter&.name || "none"
      user.update!(text_filter_name: filter_name, text_filter_id: nil)
    end

    TextFilter.destroy_all
  end

  def down
    TextFilter
      .create_with(description: "None", markup: "none", filters: [], params: {})
      .find_or_create_by!(name: "none")
    TextFilter
      .create_with(description: "Markdown", markup: "markdown", filters: [], params: {})
      .find_or_create_by!(name: "markdown")
    TextFilter
      .create_with(description: "SmartyPants", markup: "none",
                   filters: [:smartypants], params: {})
      .find_or_create_by!(name: "smartypants")
    TextFilter
      .create_with(description: "Markdown with SmartyPants", markup: "markdown",
                   filters: [:smartypants], params: {})
      .find_or_create_by!(name: "markdown smartypants")
    TextFilter
      .create_with(description: "Textile", markup: "textile", filters: [], params: {})
      .find_or_create_by!(name: "textile")

    Content.find_each do |content|
      filter_name = content.text_filter_name
      next unless filter_name

      filter = TextFilter.find(name: filter_name)
      raise "Filter #{filter_name} not found" unless filter

      content.update!(text_filter: filter)
    end

    Feedback.find_each do |feedback|
      filter_name = feedback.text_filter_name
      next unless filter_name

      filter = TextFilter.find(name: filter_name)
      raise "Filter #{filter_name} not found" unless filter

      feedback.update!(text_filter: filter)
    end

    User.find_each do |user|
      filter_name = user.text_filter_name
      next unless filter_name

      filter = TextFilter.find(name: filter_name)
      raise "Filter #{filter_name} not found" unless filter

      user.update!(text_filter: filter)
    end
  end
end


================================================
FILE: db/migrate/20190210121316_remove_text_filter_ids.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20190209155717)
class RemoveTextFilterIds < ActiveRecord::Migration[5.2]
  def up
    remove_column :contents, :text_filter_id
    remove_column :feedback, :text_filter_id
    remove_column :users, :text_filter_id
  end

  def down
    add_column :contents, :text_filter_id, :integer
    add_column :feedback, :text_filter_id, :integer
    add_column :users, :text_filter_id, :string, default: "1"

    add_index :contents, [:text_filter_id]
    add_index :feedback, [:text_filter_id]
    add_index :users, [:text_filter_id]
  end
end


================================================
FILE: db/migrate/20190210121317_remove_text_filters.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20190209160610)
class RemoveTextFilters < ActiveRecord::Migration[5.2]
  def up
    drop_table :text_filters
  end

  def down
    create_table :text_filters do |t|
      t.string :name
      t.string :description
      t.string :markup
      t.text :filters
      t.text :params
    end
  end
end


================================================
FILE: db/migrate/20200413141133_add_unique_indexes.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20200413140440)

class AddUniqueIndexes < ActiveRecord::Migration[5.2]
  def change
    add_index :post_types, :name, unique: true
    add_index :redirects, :from_path, unique: true
    add_index :tags, [:blog_id, :name], unique: true
    add_index :users, :login, unique: true
  end
end


================================================
FILE: db/migrate/20221007091118_remove_table_sitealizer.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20221007091049)
class RemoveTableSitealizer < ActiveRecord::Migration[6.1]
  def up
    drop_table :sitealizer
  end

  def down
    create_table :sitealizer do |t|
      t.string :path
      t.string :ip
      t.string :referer
      t.string :language
      t.string :user_agent
      t.datetime :created_at
      t.date :created_on
    end
  end
end


================================================
FILE: db/migrate/20221010170801_remove_page_caches_table.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20221010092846)
class RemovePageCachesTable < ActiveRecord::Migration[6.1]
  def up
    drop_table :page_caches
  end

  def down
    create_table :page_caches do |t|
      t.string :name
    end

    add_index :page_caches, :name
  end
end


================================================
FILE: db/migrate/20221012164027_remove_itunes_fields_from_resources.publify_core_engine.rb
================================================
# frozen_string_literal: true

# This migration comes from publify_core_engine (originally 20221012163214)
class RemoveItunesFieldsFromResources < ActiveRecord::Migration[6.1]
  def change
    remove_column :resources, :itunes_metadata, :boolean
    remove_column :resources, :itunes_author, :string
    remove_column :resources, :itunes_subtitle, :string
    remove_column :resources, :itunes_duration, :integer
    remove_column :resources, :itunes_summary, :text
    remove_column :resources, :itunes_keywords, :string
    remove_column :resources, :itunes_category, :string
    remove_column :resources, :itunes_explicit, :boolean
  end
end


================================================
FILE: db/schema.rb
================================================
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2022_10_12_164027) do
  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "blogs", id: :serial, force: :cascade do |t|
    t.text "settings"
    t.string "base_url"
  end

  create_table "contents", id: :serial, force: :cascade do |t|
    t.string "type"
    t.string "title"
    t.string "author"
    t.text "body"
    t.text "extended"
    t.text "excerpt"
    t.datetime "created_at", precision: nil
    t.datetime "updated_at", precision: nil
    t.integer "user_id"
    t.string "permalink"
    t.string "guid"
    t.text "whiteboard"
    t.string "name"
    t.boolean "allow_pings"
    t.boolean "allow_comments"
    t.datetime "published_at", precision: nil
    t.string "state"
    t.integer "parent_id"
    t.text "settings"
    t.string "post_type", default: "read"
    t.integer "blog_id", null: false
    t.string "text_filter_name"
    t.index ["id", "type"], name: "index_contents_on_id_and_type"
    t.index ["user_id"], name: "index_contents_on_user_id"
  end

  create_table "contents_tags", id: false, force: :cascade do |t|
    t.integer "content_id"
    t.integer "tag_id"
    t.index ["content_id"], name: "index_contents_tags_on_content_id"
    t.index ["tag_id"], name: "index_contents_tags_on_tag_id"
  end

  create_table "feedback", id: :serial, force: :cascade do |t|
    t.string "type"
    t.string "title"
    t.string "author"
    t.text "body"
    t.text "excerpt"
    t.datetime "created_at", precision: nil
    t.datetime "updated_at", precision: nil
    t.integer "user_id"
    t.string "guid"
    t.text "whiteboard"
    t.integer "article_id"
    t.string "email"
    t.string "url"
    t.string "ip", limit: 40
    t.string "blog_name"
    t.string "state"
    t.string "user_agent"
    t.string "text_filter_name"
    t.index ["article_id"], name: "index_feedback_on_article_id"
    t.index ["id", "type"], name: "index_feedback_on_id_and_type"
    t.index ["user_id"], name: "index_feedback_on_user_id"
  end

  create_table "pings", id: :serial, force: :cascade do |t|
    t.integer "article_id"
    t.string "url"
    t.datetime "created_at", precision: nil
    t.index ["article_id"], name: "index_pings_on_article_id"
  end

  create_table "post_types", id: :serial, force: :cascade do |t|
    t.string "name"
    t.string "permalink"
    t.string "description"
    t.index ["name"], name: "index_post_types_on_name", unique: true
  end

  create_table "redirects", id: :serial, force: :cascade do |t|
    t.string "from_path"
    t.string "to_path"
    t.datetime "created_at", precision: nil
    t.datetime "updated_at", precision: nil
    t.integer "content_id"
    t.integer "blog_id"
    t.index ["from_path"], name: "index_redirects_on_from_path", unique: true
  end

  create_table "resources", id: :serial, force: :cascade do |t|
    t.integer "size"
    t.string "upload"
    t.string "mime"
    t.datetime "created_at", precision: nil
    t.datetime "updated_at", precision: nil
    t.integer "content_id"
    t.integer "blog_id", null: false
    t.index ["content_id"], name: "index_resources_on_content_id"
  end

  create_table "sessions", id: :serial, force: :cascade do |t|
    t.string "session_id", null: false
    t.text "data"
    t.datetime "created_at", precision: nil, null: false
    t.datetime "updated_at", precision: nil, null: false
    t.index ["session_id"], name: "index_sessions_on_session_id", unique: true
    t.index ["updated_at"], name: "index_sessions_on_updated_at"
  end

  create_table "sidebars", id: :serial, force: :cascade do |t|
    t.integer "active_position"
    t.text "config"
    t.integer "staged_position"
    t.string "type"
    t.integer "blog_id", null: false
    t.index ["id", "type"], name: "index_sidebars_on_id_and_type"
  end

  create_table "tags", id: :serial, force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", precision: nil
    t.datetime "updated_at", precision: nil
    t.string "display_name"
    t.integer "blog_id"
    t.index ["blog_id", "name"], name: "index_tags_on_blog_id_and_name", unique: true
  end

  create_table "triggers", id: :serial, force: :cascade do |t|
    t.integer "pending_item_id"
    t.string "pending_item_type"
    t.datetime "due_at", precision: nil
    t.string "trigger_method"
    t.index ["pending_item_id", "pending_item_type"], name: "index_triggers_on_pending_item_id_and_pending_item_type"
  end

  create_table "users", id: :serial, force: :cascade do |t|
    t.string "login"
    t.string "encrypted_password", default: "", null: false
    t.string "email", default: "", null: false
    t.text "name"
    t.boolean "notify_via_email"
    t.boolean "notify_on_new_articles"
    t.boolean "notify_on_comments"
    t.string "remember_token"
    t.datetime "remember_token_expires_at", precision: nil
    t.string "state", default: "active"
    t.datetime "last_connection", precision: nil
    t.text "settings"
    t.integer "resource_id"
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at", precision: nil
    t.datetime "remember_created_at", precision: nil
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at", precision: nil
    t.datetime "last_sign_in_at", precision: nil
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.datetime "created_at", precision: nil
    t.datetime "updated_at", precision: nil
    t.string "profile"
    t.string "text_filter_name"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["login"], name: "index_users_on_login", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["resource_id"], name: "index_users_on_resource_id"
  end

end


================================================
FILE: db/seeds.rb
================================================
# frozen_string_literal: true

PublifyCore::Engine.load_seed


================================================
FILE: doc/CACHE.SETUP.README
================================================
To fully profit from Publify static caching capabilities, you need to add the
following rewrite rules to either your .htaccess or your virtualhost after
declaring the document root.

== Rewrite Rules For Apache

=== If Publify is installed at your URL root.
  
  RewriteEngine On

  RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f
  RewriteRule ^/$ /cache/index.html [PT]

  RewriteCond %{DOCUMENT_ROOT}/cache/%{REQUEST_FILENAME} -f
  RewriteRule ^/(.*)$ /cache/$1 [PT]

  RewriteCond %{DOCUMENT_ROOT}/cache/%{REQUEST_FILENAME}.html -f
  RewriteRule ^/(.*)$ /cache/$1.html [PT]

=== If Publify is installed in a sub-URL, e.g., /blog:

  # Note that 'blog' appears twice in the rewritten URL.

  RewriteEngine On

  RewriteCond %{DOCUMENT_ROOT}/blog/cache/blog.html -f
  RewriteRule ^/blog$ /blog/cache/blog.html [PT]

  RewriteCond %{DOCUMENT_ROOT}/blog/cache/%{REQUEST_FILENAME} -f
  RewriteRule ^/blog/(.*)$ /blog/cache/blog/$1 [PT]

  RewriteCond %{DOCUMENT_ROOT}/blog/cache/%{REQUEST_FILENAME}.html -f
  RewriteRule ^/blog/(.*)$ /blog/cache/blog/$1.html [PT]

== Rewrite Rules For Nginx

  if (-f $request_filename) {
    break;
  }

  if (-f $document_root/cache/index.html) {
    rewrite ^/$ /cache/index.html break;
  }

  if (-f $document_root/cache$uri) {
    rewrite (.*) /cache$1 break;
    break;
  }

  if (-f $document_root/cache$uri.html) {
    rewrite (.*) /cache$1.html break;
    break;
  }


================================================
FILE: doc/dependency_decisions.yml
================================================
---
- - :permit
  - MIT
  - :who: 
    :why: 
    :versions: []
    :when: 2017-07-22 20:10:47.517185110 Z
- - :permit
  - New BSD
  - :who: 
    :why: 
    :versions: []
    :when: 2017-07-22 20:10:58.423002290 Z
- - :permit
  - ruby
  - :who: 
    :why: 
    :versions: []
    :when: 2017-07-28 12:17:13.166276946 Z
- - :permit
  - Apache 2.0
  - :who: 
    :why: 
    :versions: []
    :when: 2017-07-28 12:17:23.516443145 Z
- - :permit
  - Simplified BSD
  - :who: 
    :why: 
    :versions: []
    :when: 2017-07-28 12:17:39.295508085 Z
- - :approve
  - easy_translate
  - :who: 
    :why: Licensed under the MIT License
    :versions:
    - 0.5.0
    :when: 2017-07-28 12:37:43.703529091 Z
- - :approve
  - bluecloth
  - :who: 
    :why: 
    :versions: []
    :when: 2018-08-31 11:04:41.169889983 Z
- - :approve
  - unf
  - :who: 
    :why: 
    :versions: []
    :when: 2018-08-31 11:04:56.051894107 Z
- - :permit
  - ISC
  - :who: 
    :why: 
    :versions: []
    :when: 2018-08-31 11:05:29.553665934 Z
- - :permit
  - WTFPL
  - :who: 
    :why: 
    :versions: []
    :when: 2020-09-13 15:15:06.072195607 Z


================================================
FILE: lib/generators/sidebar/USAGE
================================================
Description:
    Generate Sidebar plugin for Typo

Example:
    rails generate sidebar ThingSidebar

    This will create:
        lib/thing_sidebar/lib/thing_sidebar.rb
        lib/thing_sidebar/app/views/thing_sidebar/_content.html.erb
        spec/models/thing_sidebar_spec.rb


================================================
FILE: lib/generators/sidebar/sidebar_generator.rb
================================================
# frozen_string_literal: true

class SidebarGenerator < Rails::Generators::NamedBase
  source_root File.expand_path("templates", __dir__)

  def copy_stuff
    template "sidebar.rb.erb", "#{plugin_path}/lib/#{file_name}.rb"
    template "_content.html.erb.erb",
             "#{plugin_path}/app/views/#{file_name}/_content.html.erb"
    template "model_spec.rb.erb", "spec/models/#{file_name}_spec.rb"
  end

  private

  def plugin_path
    @plugin_path ||= "lib/#{file_name}"
  end
end


================================================
FILE: lib/generators/sidebar/templates/_content.html.erb.erb
================================================
<h3 class='sidebar-title'><%= class_name %></h3>
<div class='<%= file_name.sub(/_sidebar/, '') %>'-body>
<p>Replace this text with the real sidebar view code</p>
<p>You should be able to access <code>request</code>,
  <code>controller</code>, <code>params</code> etc,
  as well as local variables set from the sidebar settings. So if you've done
  <code>setting :title, 'Whatever'</code>, you can use &lt;%= title %&gt;
  to get at its value. The current sidebar object is accessible as
  <code>sidebar</code>.</p>
</div>


================================================
FILE: lib/generators/sidebar/templates/model_spec.rb.erb
================================================
require 'rails_helper'

RSpec.describe <%= class_name %> do
  it 'is available' do
    expect(SidebarRegistry.available_sidebars).to include(<%= class_name %>)
  end
end


================================================
FILE: lib/generators/sidebar/templates/sidebar.rb.erb
================================================
class <%= class_name %> < Sidebar
  # display_name "<%= class_name.underscore.humanize %>" # Default
  description "Describe your sidebar here"

  # Check the other sidebars for the sort of thing you can do with setting
  # declarations

  def parse_request(contents, params)
    # contents is a list of the items being rendered on the current page
    # params is the params hash for the current request

    # Take a look at (eg) the amazon sidebar for examples of what gets done here
    # If your sidebar doesn't depend on the request or the contents, you don't
    # need to do anything here.
  end
end


================================================
FILE: lib/publify_app/textfilter/flickr.rb
================================================
# frozen_string_literal: true

class PublifyApp
  class Textfilter
    class Flickr < TextFilterPlugin::MacroPost
      plugin_display_name "Flickr"
      plugin_description "Automatically generate image tags for Flickr images"

      def self.help_text
        <<~TXT
          You can use `<publify:flickr>` to display images from
          [Flickr](http://flickr.com). Example:

              <publify:flickr img="31367273" size="small"/>

          will produce an `<img>` tag showing image number 31367273 from
          Flickr. This image will be linked to the Flickr page for this image,
          so you can zoom in and see larger versions. It will also have a
          comment block attached if a description has been attached to the
          picture in Flickr.

          This macro takes a number of parameters:

          * **img** The Flickr image ID of the picture that you wish to use.
            This shows up in the URL whenever you're viewing a picture in
            Flickr; for example, the image ID for
            <http://flickr.com/photos/scottlaird/31367273> is 31367273.
          * **size** The image size that you'd like to display.  Options are:
            * square (75x75)
            * thumbnail (maximum size 100 pixels)
            * small (maximum size 240 pixels)
            * medium (maximum size 500 pixels)
            * large (maximum size 1024 pixels)
            * original
          * **style** This is passed through to the enclosing `<div>` that this
            macro generates. To float the flickr image on the right, use
            `style="float:right"`.
          * **caption** The caption displayed below the image. By default, this
            is Flickr's description of the image. to disable, use `caption=""`.
          * **title** The tooltip title associated with the image. Defaults to
            Flickr's image title.
          * **alt** The alt text associated with the image. By default, this is
            the same as the title.
        TXT
      end

      def self.macrofilter(attrib, _text = "")
        img = attrib["img"]
        size = attrib["size"] || "square"
        style = attrib["style"]
        caption = attrib["caption"]
        title = attrib["title"]
        alt = attrib["alt"]

        begin
          flickrimage = flickr.photos.getInfo(photo_id: img)
          sizes = flickr.photos.getSizes(photo_id: img)

          details =
            sizes.find { |s| s["label"].casecmp(size.downcase).zero? } || sizes.first
          width = details["width"]
          height = details["height"]
          # use protocol-relative URL after getting the source address
          # so not to break HTTPS support
          imageurl = details["source"].sub(/^https?:/, "")
          imagelink = flickrimage.urls.find { |u| u.type == "photopage" }.to_s

          description = flickrimage.description
          caption ||= sanitize(CGI.unescapeHTML(description)) if description.present?
          title ||= flickrimage.title
          alt ||= title

          captioncode = if caption.blank?
                          ""
                        else
                          "<p class=\"caption\" style=\"width:#{width}px\">#{caption}</p>"
                        end

          "<div style=\"#{style}\" class=\"flickrplugin\"><a href=\"#{imagelink}\">" \
            "<img src=\"#{imageurl}\" width=\"#{width}\" height=\"#{height}\"" \
            " alt=\"#{alt}\" title=\"#{title}\"/></a>#{captioncode}</div>"
        rescue StandardError => e
          logger.info e.message
          "<div class='broken_flickr_link'>`#{img}' could not be displayed because:" \
            " <br />#{CGI.escapeHTML(e.message)}</div>"
        end
      end
    end
  end
end


================================================
FILE: lib/publify_app/textfilter/htmlfilter.rb
================================================
# frozen_string_literal: true

class PublifyApp
  class Textfilter
    class Htmlfilter < TextFilterPlugin
      plugin_display_name "HTML Filter"
      plugin_description "Strip HTML tags"

      def self.filtertext(text)
        text.to_s.gsub("<", "&lt;").gsub(">", "&gt;")
      end
    end
  end
end


================================================
FILE: lib/publify_app/textfilter/lightbox.rb
================================================
# frozen_string_literal: true

class PublifyApp
  class Textfilter
    class Lightbox < TextFilterPlugin::MacroPost
      plugin_display_name "Lightbox"
      plugin_description "Automatically generate tags for images displayed in a lightbox"

      def self.help_text
        <<~TXT
          You can use `<publify:lightbox>` to display images from [Flickr](http://flickr.com)
          or a provided URL which, when clicked, will be shown in a lightbox using Lokesh Dhakar's
          [Lightbox](http://www.huddletogether.com/projects/lightbox/) Javascript

          Example:

              <publify:lightbox img="31367273" thumbsize="thumbnail" displaysize="original"/>
              <publify:lightbox src="/files/myimage.png" thumbsrc="/files/myimage-thumb.png"/>

          The first will produce an `<img>` tag showing image number 31367273
          from Flickr using the thumbnail image size.  The image will be linked
          to the original image file from Flickr.  When the link is clicked,
          the larger picture will be overlaid on top of the existing page
          instead of taking you over to the Flickr site.
          The second will do the same but use the `src` URL as the large
          picture and the `thumbsrc` URL as the thumbnail image. To understand
          what this looks like, have a peek at Lokesh Dhakar's
          [examples](http://www.huddletogether.com/projects/lightbox/).
          It will also have a comment block attached if a description has been
          attached to the picture in Flickr or the caption attribute is used.

          For theme writers, the link is enclosed in a div tag with a "lightboxplugin"
          class.  Because this filter requires javascript and css include files, it
          will only work with themes using the `<%= page_header %>` convenience function
          in their layouts. As of this writing only Azure does this.

          This macro takes a number of parameters:

          Flickr attributes:

          * **img** The Flickr image ID of the picture that you wish to use.
            This shows up in the URL whenever you're viewing a picture in Flickr;
            for example, the image ID for
            <http://flickr.com/photos/scottlaird/31367273> is 31367273.
          * **thumbsize** The image size that you'd like to display. Typically
            you would use square, thumbnail or small. Options are:
            * square (75x75)
            * thumbnail (maximum size 100 pixels)
            * small (maximum size 240 pixels)
            * medium (maximum size 500 pixels)
            * large (maximum size 1024 pixels)
            * original
          * **displaysize** The image size for the lightbox overlay shown when
            the user clicks the thumbnail.  Options are the same as for
            thumbsize, but typically you would use medium or large.  If your
            image files are quite large on Flickr you probably want to avoid
            using original.

          Direct URL attributes:

          * **src** The URL to the picture you wish to use.
          * **thumbsrc** The URL to the thumbnail you would like to use. If
            this is not provided, the original picture will be used with the
            width and height properties of the `<img>` tag set to 100x100.

          Common attributes:

          * **style** This is passed through to the enclosing `<div>` that this
            macro generates. To float the image on the right, use
            `style="float:right"`.
          * **caption** The caption displayed below the image. By default,
            this is Flickr's description of the image. to disable, use
            `caption=""`.
          * **title** The tooltip title associated with the image. Defaults to
            Flickr's image title.
          * **alt** The alt text associated with the image. By default, this is
            the same as the title.
          * **set** Add image to a set
          * **class** adds an existing CSS class
        TXT
      end

      def self.macrofilter(attrib, _text = "")
        # FIXME: style is not used
        # style = attrib['style']
        caption = attrib["caption"]
        title = attrib["title"]
        alt = attrib["alt"]
        theclass = attrib["class"]
        set = attrib["set"]
        thumburl = ""
        displayurl = ""

        img = attrib["img"]
        if img
          thumbsize = attrib["thumbsize"] || "square"
          displaysize = attrib["displaysize"] || "original"

          flickrimage = flickr.photos.getInfo(photo_id: img)
          sizes = flickr.photos.getSizes(photo_id: img)

          thumbdetails =
            sizes.find { |s| s["label"].casecmp(thumbsize.downcase).zero? } || sizes.first
          displaydetails =
            sizes.find { |s| s["label"].casecmp(displaysize.downcase).zero? } || sizes.first

          width = thumbdetails["width"]
          height = thumbdetails["height"]

          # use protocol-relative URL after getting the source address
          # so not to break HTTPS support
          thumburl = thumbdetails["source"].sub(/^https?:/, "")
          displayurl = displaydetails["source"].sub(/^https?:/, "")

          caption ||= flickrimage.description
          title ||= flickrimage.title
          alt ||= title
        else
          thumburl = attrib["thumbsrc"] unless attrib["thumbsrc"].nil?
          displayurl = attrib["src"] unless attrib["src"].nil?

          if thumburl.empty?
            thumburl = displayurl
            width = 100
            height = 100
          else
            width = height = nil
          end
        end

        rel = set.blank? ? "lightbox" : "lightbox[#{set}]"

        captioncode = if caption.blank?
                        ""
                      else
                        "<p class=\"caption\" style=\"width:#{width}px\">#{caption}</p>"
                      end

        img_attrs = %(src="#{thumburl}")
        img_attrs << %( class="#{theclass}") if theclass
        img_attrs << %( width="#{width}") if width
        img_attrs << %( height="#{height}") if height
        img_attrs << %( alt="#{alt}" title="#{title}")
        "<a href=\"#{displayurl}\" data-toggle=\"#{rel}\" title=\"#{title}\">" \
          "<img #{img_attrs}/></a>#{captioncode}"
      end
    end
  end
end


================================================
FILE: lib/publify_plugins/avatar_plugin.rb
================================================
# frozen_string_literal: true

require "publify_plugins"

module PublifyPlugins
  class AvatarPlugin < Base
    def self.kind
      :avatar
    end

    def self.get_avatar(_options = {})
      raise NotImplementedError
    end

    def self.name
      raise NotImplementedError
    end
  end
end


================================================
FILE: lib/publify_plugins/gravatar.rb
================================================
# frozen_string_literal: true

require "publify_plugins"
require "publify_plugins/avatar_plugin"

# PublifyAvatarGravatar
module PublifyPlugins
  class Gravatar < AvatarPlugin
    extend ActionView::Helpers::TagHelper

    @description = "Provide user avatar image throught the http://gravatar.com service."

    class << self
      def get_avatar(options = {})
        email = options.delete(:email) || ""
        gravatar_tag(email, options)
      end

      def name
        "Gravatar"
      end

      private

      # Generate the image tag for a commenters gravatar based on their email address
      # Valid options are described at http://www.gravatar.com/implement.php
      def gravatar_tag(email, options = {})
        opts = {}
        opts[:gravatar_id] = Digest::MD5.hexdigest(email.strip)
        opts[:default] = CGI.escape(options[:default]) if options.include?(:default)
        opts[:size] = options[:size] || 48
        klass = options[:class] || "avatar gravatar"

        url = +"https://www.gravatar.com/avatar.php?"
        url << opts.map { |key, value| "#{key}=#{value}" }.sort.join("&")
        tag.img(src: url, class: klass, alt: "Gravatar")
      end
    end
  end
end

PublifyPlugins::Keeper.register(PublifyPlugins::Gravatar)


================================================
FILE: lib/tasks/i18n.rake
================================================
# frozen_string_literal: true

require "English"

namespace :i18n do
  desc "Check translation health"
  task :health do
    `bin/i18n-tasks health`
    abort("Translation problems found") unless $CHILD_STATUS.success?
  end
end

task lint: "i18n:health"


================================================
FILE: lib/tasks/rubocop.rake
================================================
# frozen_string_literal: true

begin
  require "rubocop/rake_task"

  RuboCop::RakeTask.new do |task|
    task.options << "--display-cop-names"
  end

  task lint: :rubocop

  desc "Regenerate RuboCop to-do file"
  task "rubocop:regenerate_todos" do
    sh "rubocop --regenerate-todo"
  end
rescue LoadError
  # No rubocop available
  nil
end


================================================
FILE: log/.keep
================================================


================================================
FILE: public/404.html
================================================
<!DOCTYPE html>
<html>
<head>
  <title>The page you were looking for doesn't exist (404)</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <style>
  body {
    background-color: #EFEFEF;
    color: #2E2F30;
    text-align: center;
    font-family: arial, sans-serif;
    margin: 0;
  }

  div.dialog {
    width: 95%;
    max-width: 33em;
    margin: 4em auto 0;
  }

  div.dialog > div {
    border: 1px solid #CCC;
    border-right-color: #999;
    border-left-color: #999;
    border-bottom-color: #BBB;
    border-top: #B00100 solid 4px;
    border-top-left-radius: 9px;
    border-top-right-radius: 9px;
    background-color: white;
    padding: 7px 12% 0;
    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
  }

  h1 {
    font-size: 100%;
    color: #730E15;
    line-height: 1.5em;
  }

  div.dialog > p {
    margin: 0 0 1em;
    padding: 1em;
    background-color: #F7F7F7;
    border: 1px solid #CCC;
    border-right-color: #999;
    border-left-color: #999;
    border-bottom-color: #999;
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
    border-top-color: #DADADA;
    color: #666;
    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
  }
  </style>
</head>

<body>
  <!-- This file lives in public/404.html -->
  <div class="dialog">
    <div>
      <h1>The page you were looking for doesn't exist.</h1>
      <p>You may have mistyped the address or the page may have moved.</p>
    </div>
    <p>If you are the application owner check the logs for more information.</p>
  </div>
</body>
</html>


================================================
FILE: public/422.html
================================================
<!DOCTYPE html>
<html>
<head>
  <title>The change you wanted was rejected (422)</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <style>
  body {
    background-color: #EFEFEF;
    color: #2E2F30;
    text-align: center;
    font-family: arial, sans-serif;
    margin: 0;
  }

  div.dialog {
    width: 95%;
    max-width: 33em;
    margin: 4em auto 0;
  }

  div.dialog > div {
    border: 1px solid #CCC;
    border-right-color: #999;
    border-left-color: #999;
    border-bottom-color: #BBB;
    border-top: #B00100 solid 4px;
    border-top-left-radius: 9px;
    border-top-right-radius: 9px;
    background-color: white;
    padding: 7px 12% 0;
    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
  }

  h1 {
    font-size: 100%;
    color: #730E15;
    line-height: 1.5em;
  }

  div.dialog > p {
    margin: 0 0 1em;
    padding: 1em;
    background-color: #F7F7F7;
    border: 1px solid #CCC;
    border-right-color: #999;
    border-left-color: #999;
    border-bottom-color: #999;
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
    border-top-color: #DADADA;
    color: #666;
    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
  }
  </style>
</head>

<body>
  <!-- This file lives in public/422.html -->
  <div class="dialog">
    <div>
      <h1>The change you wanted was rejected.</h1>
      <p>Maybe you tried to change something you didn't have access to.</p>
    </div>
    <p>If you are the application owner check the logs for more information.</p>
  </div>
</body>
</html>


================================================
FILE: public/500.html
================================================
<!DOCTYPE html>
<html>
Download .txt
gitextract_oagz7ovf/

├── .erb-lint.yml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       └── ruby.yml
├── .gitignore
├── .hound.yml
├── .metrics
├── .reek.yml
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── TODO.txt
├── app/
│   ├── assets/
│   │   ├── config/
│   │   │   └── manifest.js
│   │   └── images/
│   │       └── .keep
│   ├── controllers/
│   │   └── application_controller.rb
│   ├── helpers/
│   │   └── theme_helper.rb
│   ├── mailers/
│   │   └── application_mailer.rb
│   ├── models/
│   │   ├── application_record.rb
│   │   ├── authors_sidebar.rb
│   │   ├── concerns/
│   │   │   └── .keep
│   │   ├── livesearch_sidebar.rb
│   │   ├── notes_sidebar.rb
│   │   ├── popular_sidebar.rb
│   │   └── xml_sidebar.rb
│   └── views/
│       ├── authors_sidebar/
│       │   └── _content.html.erb
│       ├── livesearch_sidebar/
│       │   └── _content.html.erb
│       ├── notes_sidebar/
│       │   └── _content.html.erb
│       ├── popular_sidebar/
│       │   └── _content.html.erb
│       └── xml_sidebar/
│           └── _content.html.erb
├── bin/
│   ├── bundle
│   ├── i18n-tasks
│   ├── rails
│   ├── rake
│   ├── rspec
│   ├── setup
│   ├── update
│   └── yarn
├── config/
│   ├── application.rb
│   ├── boot.rb
│   ├── cable.yml
│   ├── database.yml.mysql
│   ├── database.yml.postgresql
│   ├── environment.rb
│   ├── environments/
│   │   ├── development.rb
│   │   ├── production.rb
│   │   └── test.rb
│   ├── filemanager.yml
│   ├── i18n-tasks.yml
│   ├── initializers/
│   │   ├── application_controller_renderer.rb
│   │   ├── assets.rb
│   │   ├── backtrace_silencers.rb
│   │   ├── carrierwave.rb
│   │   ├── content_security_policy.rb
│   │   ├── cookies_serializer.rb
│   │   ├── filter_parameter_logging.rb
│   │   ├── flickr.rb
│   │   ├── inflections.rb
│   │   ├── mime_types.rb
│   │   ├── new_framework_defaults_7_1.rb
│   │   ├── non_digest_assets.rb
│   │   ├── permissions_policy.rb
│   │   ├── rack_attack.rb
│   │   ├── recaptcha.rb
│   │   ├── session_store.rb
│   │   └── wrap_parameters.rb
│   ├── locales/
│   │   ├── ar.yml
│   │   ├── da.yml
│   │   ├── de.yml
│   │   ├── en.yml
│   │   ├── es-MX.yml
│   │   ├── fr.yml
│   │   ├── he.yml
│   │   ├── it.yml
│   │   ├── ja.yml
│   │   ├── lt.yml
│   │   ├── nb.yml
│   │   ├── nl.yml
│   │   ├── pl.yml
│   │   ├── pt-BR.yml
│   │   ├── ro.yml
│   │   ├── ru.yml
│   │   ├── sidebars.ar.yml
│   │   ├── sidebars.da.yml
│   │   ├── sidebars.de.yml
│   │   ├── sidebars.en.yml
│   │   ├── sidebars.es-MX.yml
│   │   ├── sidebars.fr.yml
│   │   ├── sidebars.he.yml
│   │   ├── sidebars.it.yml
│   │   ├── sidebars.ja.yml
│   │   ├── sidebars.lt.yml
│   │   ├── sidebars.nb.yml
│   │   ├── sidebars.nl.yml
│   │   ├── sidebars.pl.yml
│   │   ├── sidebars.pt-BR.yml
│   │   ├── sidebars.ro.yml
│   │   ├── sidebars.ru.yml
│   │   ├── sidebars.zh-CN.yml
│   │   ├── sidebars.zh-TW.yml
│   │   ├── zh-CN.yml
│   │   └── zh-TW.yml
│   ├── mail.yml.example
│   ├── puma.rb
│   ├── routes.rb
│   ├── secrets.yml
│   ├── spring.rb
│   └── storage.yml
├── config.ru
├── db/
│   ├── converters/
│   │   ├── README
│   │   ├── blogger.rb
│   │   ├── feed.rb
│   │   └── rss.rb
│   ├── migrate/
│   │   ├── 113_initial_schema.publify_core_engine.rb
│   │   ├── 114_fixes_buggy_articles_and_notes.publify_core_engine.rb
│   │   ├── 115_drops_categories_for_tags.publify_core_engine.rb
│   │   ├── 20150207131657_add_missing_indexes.publify_core_engine.rb
│   │   ├── 20150807134129_simplify_redirect_relations.publify_core_engine.rb
│   │   ├── 20150808052637_add_blog_ids.publify_core_engine.rb
│   │   ├── 20150808191127_add_blog_id_to_redirects.publify_core_engine.rb
│   │   ├── 20150810094754_add_blog_id_to_tags.publify_core_engine.rb
│   │   ├── 20160108111120_add_devise_to_users.publify_core_engine.rb
│   │   ├── 20160108184201_move_last_connection_to_last_sign_in_at.publify_core_engine.rb
│   │   ├── 20160110094906_remove_profiles_rights.publify_core_engine.rb
│   │   ├── 20160605103918_replace_profile_id_with_string.publify_core_engine.rb
│   │   ├── 20160605154632_remove_profiles.publify_core_engine.rb
│   │   ├── 20160701061851_demand_blog_id_on_contents.publify_core_engine.rb
│   │   ├── 20160701062604_add_blog_id_to_resources.publify_core_engine.rb
│   │   ├── 20161030121548_add_sessions_table.rb
│   │   ├── 20170528093428_move_resources_to_content.publify_core_engine.rb
│   │   ├── 20170528120220_move_tags_to_content.publify_core_engine.rb
│   │   ├── 20170530063901_remove_separate_published_flag.publify_core_engine.rb
│   │   ├── 20170605103539_remove_extra_state_columns_from_feedback.publify_core_engine.rb
│   │   ├── 20170702105518_remove_published_at_from_feedback.publify_core_engine.rb
│   │   ├── 20190210121314_add_text_filter_name_fields.publify_core_engine.rb
│   │   ├── 20190210121315_move_text_filter_to_name.publify_core_engine.rb
│   │   ├── 20190210121316_remove_text_filter_ids.publify_core_engine.rb
│   │   ├── 20190210121317_remove_text_filters.publify_core_engine.rb
│   │   ├── 20200413141133_add_unique_indexes.publify_core_engine.rb
│   │   ├── 20221007091118_remove_table_sitealizer.publify_core_engine.rb
│   │   ├── 20221010170801_remove_page_caches_table.publify_core_engine.rb
│   │   └── 20221012164027_remove_itunes_fields_from_resources.publify_core_engine.rb
│   ├── schema.rb
│   └── seeds.rb
├── doc/
│   ├── CACHE.SETUP.README
│   └── dependency_decisions.yml
├── lib/
│   ├── generators/
│   │   └── sidebar/
│   │       ├── USAGE
│   │       ├── sidebar_generator.rb
│   │       └── templates/
│   │           ├── _content.html.erb.erb
│   │           ├── model_spec.rb.erb
│   │           └── sidebar.rb.erb
│   ├── publify_app/
│   │   └── textfilter/
│   │       ├── flickr.rb
│   │       ├── htmlfilter.rb
│   │       └── lightbox.rb
│   ├── publify_plugins/
│   │   ├── avatar_plugin.rb
│   │   └── gravatar.rb
│   └── tasks/
│       ├── i18n.rake
│       └── rubocop.rake
├── log/
│   └── .keep
├── public/
│   ├── 404.html
│   ├── 422.html
│   └── 500.html
├── spec/
│   ├── controllers/
│   │   ├── articles_controller_spec.rb
│   │   ├── feedback_controller_spec.rb
│   │   ├── tags_controller_spec.rb
│   │   └── xml_controller_spec.rb
│   ├── features/
│   │   └── switch_theme_spec.rb
│   ├── lib/
│   │   ├── publify_plugins/
│   │   │   └── gravatar_spec.rb
│   │   ├── publify_textfilter_flickr_spec.rb
│   │   ├── publify_textfilter_lightbox_spec.rb
│   │   └── text_filter_plugin_spec.rb
│   ├── models/
│   │   ├── authors_sidebar_spec.rb
│   │   ├── notes_sidebar_spec.rb
│   │   ├── popular_sidebar_spec.rb
│   │   ├── sidebar_registry_spec.rb
│   │   └── xml_sidebar_spec.rb
│   ├── rails_helper.rb
│   ├── spec_helper.rb
│   └── views/
│       ├── comments/
│       │   └── html_sanitization_spec.rb
│       ├── layouts/
│       │   └── default_spec.rb
│       └── xml_sidebar/
│           └── _content.html.erb_spec.rb
├── themes/
│   └── bootstrap-2/
│       ├── about.markdown
│       ├── javascripts/
│       │   └── bootstrap.js
│       ├── less/
│       │   ├── .csscomb.json
│       │   ├── .csslintrc
│       │   ├── alerts.less
│       │   ├── badges.less
│       │   ├── bootstrap.less
│       │   ├── breadcrumbs.less
│       │   ├── button-groups.less
│       │   ├── buttons.less
│       │   ├── carousel.less
│       │   ├── close.less
│       │   ├── code.less
│       │   ├── component-animations.less
│       │   ├── dropdowns.less
│       │   ├── forms.less
│       │   ├── glyphicons.less
│       │   ├── grid.less
│       │   ├── input-groups.less
│       │   ├── jumbotron.less
│       │   ├── labels.less
│       │   ├── list-group.less
│       │   ├── media.less
│       │   ├── mixins/
│       │   │   ├── alerts.less
│       │   │   ├── background-variant.less
│       │   │   ├── border-radius.less
│       │   │   ├── buttons.less
│       │   │   ├── center-block.less
│       │   │   ├── clearfix.less
│       │   │   ├── forms.less
│       │   │   ├── gradients.less
│       │   │   ├── grid-framework.less
│       │   │   ├── grid.less
│       │   │   ├── hide-text.less
│       │   │   ├── image.less
│       │   │   ├── labels.less
│       │   │   ├── list-group.less
│       │   │   ├── nav-divider.less
│       │   │   ├── nav-vertical-align.less
│       │   │   ├── opacity.less
│       │   │   ├── pagination.less
│       │   │   ├── panels.less
│       │   │   ├── progress-bar.less
│       │   │   ├── reset-filter.less
│       │   │   ├── resize.less
│       │   │   ├── responsive-visibility.less
│       │   │   ├── size.less
│       │   │   ├── tab-focus.less
│       │   │   ├── table-row.less
│       │   │   ├── text-emphasis.less
│       │   │   ├── text-overflow.less
│       │   │   └── vendor-prefixes.less
│       │   ├── mixins.less
│       │   ├── modals.less
│       │   ├── navbar.less
│       │   ├── navs.less
│       │   ├── normalize.less
│       │   ├── pager.less
│       │   ├── pagination.less
│       │   ├── panels.less
│       │   ├── popovers.less
│       │   ├── print.less
│       │   ├── progress-bars.less
│       │   ├── responsive-embed.less
│       │   ├── responsive-utilities.less
│       │   ├── scaffolding.less
│       │   ├── tables.less
│       │   ├── theme.less
│       │   ├── thumbnails.less
│       │   ├── tooltip.less
│       │   ├── type.less
│       │   ├── utilities.less
│       │   ├── variables.less
│       │   └── wells.less
│       ├── stylesheets/
│       │   ├── bootstrap.css
│       │   └── style.css
│       └── views/
│           ├── articles/
│           │   ├── _article.html.erb
│           │   ├── _comment_counter.html.erb
│           │   ├── _comment_form.html.erb
│           │   ├── _comment_list.html.erb
│           │   ├── _meta.html.erb
│           │   ├── _trackback.html.erb
│           │   ├── index.html.erb
│           │   ├── read.html.erb
│           │   ├── search.html.erb
│           │   └── view_page.html.erb
│           ├── comments/
│           │   └── _comment.html.erb
│           ├── layouts/
│           │   └── default.html.erb
│           └── tags/
│               └── show.html.erb
└── vendor/
    └── .keep
Download .txt
SYMBOL INDEX (198 symbols across 51 files)

FILE: app/controllers/application_controller.rb
  class ApplicationController (line 3) | class ApplicationController < ActionController::Base

FILE: app/helpers/theme_helper.rb
  type ThemeHelper (line 3) | module ThemeHelper

FILE: app/mailers/application_mailer.rb
  class ApplicationMailer (line 3) | class ApplicationMailer < ActionMailer::Base

FILE: app/models/application_record.rb
  class ApplicationRecord (line 3) | class ApplicationRecord < ActiveRecord::Base

FILE: app/models/authors_sidebar.rb
  class AuthorsSidebar (line 3) | class AuthorsSidebar < Sidebar
    method authors (line 10) | def authors

FILE: app/models/livesearch_sidebar.rb
  class LivesearchSidebar (line 3) | class LivesearchSidebar < Sidebar

FILE: app/models/notes_sidebar.rb
  class NotesSidebar (line 3) | class NotesSidebar < Sidebar
    method parse_request (line 10) | def parse_request(_contents, params)

FILE: app/models/popular_sidebar.rb
  class PopularSidebar (line 3) | class PopularSidebar < Sidebar
    method parse_request (line 10) | def parse_request(_contents, _params)

FILE: app/models/xml_sidebar.rb
  class XmlSidebar (line 3) | class XmlSidebar < Sidebar
    method format_strip (line 14) | def format_strip

FILE: config/application.rb
  type Publify (line 11) | module Publify
    class Application (line 12) | class Application < Rails::Application

FILE: db/converters/blogger.rb
  class BloggerConverter (line 10) | class BloggerConverter
    method initialize (line 15) | def initialize
    method convert_entries (line 21) | def convert_entries
    method create_article (line 40) | def create_article(entry)
    method create_author (line 57) | def create_author(name)
    method parse_options (line 77) | def parse_options

FILE: db/converters/feed.rb
  class FeedMigrate (line 18) | class FeedMigrate
    method initialize (line 21) | def initialize
    method convert_entries (line 27) | def convert_entries
    method parse_options (line 41) | def parse_options

FILE: db/converters/rss.rb
  class RSSMigrate (line 16) | class RSSMigrate
    method initialize (line 19) | def initialize
    method convert_entries (line 25) | def convert_entries
    method parse_options (line 40) | def parse_options

FILE: db/migrate/113_initial_schema.publify_core_engine.rb
  class InitialSchema (line 3) | class InitialSchema < ActiveRecord::Migration[4.2]
    method change (line 4) | def change

FILE: db/migrate/114_fixes_buggy_articles_and_notes.publify_core_engine.rb
  class FixesBuggyArticlesAndNotes (line 3) | class FixesBuggyArticlesAndNotes < ActiveRecord::Migration[4.2]
    class Content (line 4) | class Content < ActiveRecord::Base
    class Article (line 7) | class Article < Content
      method set_permalink (line 8) | def set_permalink
    class Note (line 15) | class Note < Content
      method set_permalink (line 16) | def set_permalink
      method create_guid (line 21) | def create_guid
    class Page (line 28) | class Page < Content
      method set_permalink (line 29) | def set_permalink
    method up (line 34) | def self.up
    method down (line 51) | def self.down

FILE: db/migrate/115_drops_categories_for_tags.publify_core_engine.rb
  class DropsCategoriesForTags (line 3) | class DropsCategoriesForTags < ActiveRecord::Migration[4.2]
    class Categorization (line 4) | class Categorization < ActiveRecord::Base
    class Category (line 9) | class Category < ActiveRecord::Base
    method up (line 14) | def up
    method down (line 34) | def down; end

FILE: db/migrate/20150207131657_add_missing_indexes.publify_core_engine.rb
  class AddMissingIndexes (line 3) | class AddMissingIndexes < ActiveRecord::Migration[4.2]
    method change (line 4) | def change

FILE: db/migrate/20150807134129_simplify_redirect_relations.publify_core_engine.rb
  class SimplifyRedirectRelations (line 3) | class SimplifyRedirectRelations < ActiveRecord::Migration[4.2]
    class Redirect (line 4) | class Redirect < ActiveRecord::Base; end
    class Redirection (line 6) | class Redirection < ActiveRecord::Base; end
    method up (line 8) | def up
    method down (line 26) | def down

FILE: db/migrate/20150808052637_add_blog_ids.publify_core_engine.rb
  class AddBlogIds (line 3) | class AddBlogIds < ActiveRecord::Migration[4.2]
    class Blog (line 4) | class Blog < ActiveRecord::Base; end
    class Content (line 6) | class Content < ActiveRecord::Base; end
    class Sidebar (line 8) | class Sidebar < ActiveRecord::Base; end
    method up (line 10) | def up
    method down (line 24) | def down

FILE: db/migrate/20150808191127_add_blog_id_to_redirects.publify_core_engine.rb
  class AddBlogIdToRedirects (line 3) | class AddBlogIdToRedirects < ActiveRecord::Migration[4.2]
    class Redirect (line 4) | class Redirect < ActiveRecord::Base; end
    method up (line 6) | def up
    method down (line 14) | def down

FILE: db/migrate/20150810094754_add_blog_id_to_tags.publify_core_engine.rb
  class AddBlogIdToTags (line 3) | class AddBlogIdToTags < ActiveRecord::Migration[4.2]
    class Tag (line 4) | class Tag < ActiveRecord::Base; end
    method up (line 6) | def up
    method down (line 14) | def down

FILE: db/migrate/20160108111120_add_devise_to_users.publify_core_engine.rb
  class AddDeviseToUsers (line 3) | class AddDeviseToUsers < ActiveRecord::Migration[4.2]
    method up (line 4) | def self.up
    method down (line 33) | def self.down

FILE: db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.publify_core_engine.rb
  class MoveLastConnectionToLastSignInAt (line 3) | class MoveLastConnectionToLastSignInAt < ActiveRecord::Migration[4.2]
    class User (line 4) | class User < ActiveRecord::Base
    method up (line 7) | def up
    method down (line 13) | def down

FILE: db/migrate/20160110094906_remove_profiles_rights.publify_core_engine.rb
  class RemoveProfilesRights (line 3) | class RemoveProfilesRights < ActiveRecord::Migration[4.2]
    method up (line 4) | def up
    method down (line 8) | def down

FILE: db/migrate/20160605103918_replace_profile_id_with_string.publify_core_engine.rb
  class ReplaceProfileIdWithString (line 3) | class ReplaceProfileIdWithString < ActiveRecord::Migration[4.2]
    class Profile (line 4) | class Profile < ActiveRecord::Base
    class User (line 7) | class User < ActiveRecord::Base
    method up (line 10) | def up
    method down (line 21) | def down

FILE: db/migrate/20160605154632_remove_profiles.publify_core_engine.rb
  class RemoveProfiles (line 3) | class RemoveProfiles < ActiveRecord::Migration[4.2]
    class Profile (line 4) | class Profile < ActiveRecord::Base
    method up (line 8) | def up
    method down (line 12) | def down

FILE: db/migrate/20160701061851_demand_blog_id_on_contents.publify_core_engine.rb
  class DemandBlogIdOnContents (line 3) | class DemandBlogIdOnContents < ActiveRecord::Migration[4.2]
    method up (line 4) | def up
    method down (line 8) | def down

FILE: db/migrate/20160701062604_add_blog_id_to_resources.publify_core_engine.rb
  class AddBlogIdToResources (line 3) | class AddBlogIdToResources < ActiveRecord::Migration[4.2]
    class Blog (line 4) | class Blog < ActiveRecord::Base; end
    class Content (line 6) | class Content < ActiveRecord::Base; end
    class Resource (line 8) | class Resource < ActiveRecord::Base; end
    method up (line 10) | def up
    method down (line 29) | def down

FILE: db/migrate/20161030121548_add_sessions_table.rb
  class AddSessionsTable (line 3) | class AddSessionsTable < ActiveRecord::Migration[4.2]
    method change (line 4) | def change

FILE: db/migrate/20170528093428_move_resources_to_content.publify_core_engine.rb
  class MoveResourcesToContent (line 4) | class MoveResourcesToContent < ActiveRecord::Migration[5.0]
    method change (line 5) | def change

FILE: db/migrate/20170528120220_move_tags_to_content.publify_core_engine.rb
  class MoveTagsToContent (line 4) | class MoveTagsToContent < ActiveRecord::Migration[5.0]
    method change (line 5) | def change

FILE: db/migrate/20170530063901_remove_separate_published_flag.publify_core_engine.rb
  class RemoveSeparatePublishedFlag (line 4) | class RemoveSeparatePublishedFlag < ActiveRecord::Migration[5.0]
    method change (line 5) | def change

FILE: db/migrate/20170605103539_remove_extra_state_columns_from_feedback.publify_core_engine.rb
  class RemoveExtraStateColumnsFromFeedback (line 4) | class RemoveExtraStateColumnsFromFeedback < ActiveRecord::Migration[5.0]
    method change (line 5) | def change

FILE: db/migrate/20170702105518_remove_published_at_from_feedback.publify_core_engine.rb
  class RemovePublishedAtFromFeedback (line 4) | class RemovePublishedAtFromFeedback < ActiveRecord::Migration[5.0]
    method change (line 5) | def change

FILE: db/migrate/20190210121314_add_text_filter_name_fields.publify_core_engine.rb
  class AddTextFilterNameFields (line 4) | class AddTextFilterNameFields < ActiveRecord::Migration[5.2]
    method change (line 5) | def change

FILE: db/migrate/20190210121315_move_text_filter_to_name.publify_core_engine.rb
  class MoveTextFilterToName (line 4) | class MoveTextFilterToName < ActiveRecord::Migration[5.2]
    class Content (line 5) | class Content < ActiveRecord::Base
    class Feedback (line 11) | class Feedback < ActiveRecord::Base
    class User (line 18) | class User < ActiveRecord::Base
    class TextFilter (line 22) | class TextFilter < ActiveRecord::Base
    method up (line 27) | def up
    method down (line 49) | def down

FILE: db/migrate/20190210121316_remove_text_filter_ids.publify_core_engine.rb
  class RemoveTextFilterIds (line 4) | class RemoveTextFilterIds < ActiveRecord::Migration[5.2]
    method up (line 5) | def up
    method down (line 11) | def down

FILE: db/migrate/20190210121317_remove_text_filters.publify_core_engine.rb
  class RemoveTextFilters (line 4) | class RemoveTextFilters < ActiveRecord::Migration[5.2]
    method up (line 5) | def up
    method down (line 9) | def down

FILE: db/migrate/20200413141133_add_unique_indexes.publify_core_engine.rb
  class AddUniqueIndexes (line 5) | class AddUniqueIndexes < ActiveRecord::Migration[5.2]
    method change (line 6) | def change

FILE: db/migrate/20221007091118_remove_table_sitealizer.publify_core_engine.rb
  class RemoveTableSitealizer (line 4) | class RemoveTableSitealizer < ActiveRecord::Migration[6.1]
    method up (line 5) | def up
    method down (line 9) | def down

FILE: db/migrate/20221010170801_remove_page_caches_table.publify_core_engine.rb
  class RemovePageCachesTable (line 4) | class RemovePageCachesTable < ActiveRecord::Migration[6.1]
    method up (line 5) | def up
    method down (line 9) | def down

FILE: db/migrate/20221012164027_remove_itunes_fields_from_resources.publify_core_engine.rb
  class RemoveItunesFieldsFromResources (line 4) | class RemoveItunesFieldsFromResources < ActiveRecord::Migration[6.1]
    method change (line 5) | def change

FILE: lib/generators/sidebar/sidebar_generator.rb
  class SidebarGenerator (line 3) | class SidebarGenerator < Rails::Generators::NamedBase
    method copy_stuff (line 6) | def copy_stuff
    method plugin_path (line 15) | def plugin_path

FILE: lib/publify_app/textfilter/flickr.rb
  class PublifyApp (line 3) | class PublifyApp
    class Textfilter (line 4) | class Textfilter
      class Flickr (line 5) | class Flickr < TextFilterPlugin::MacroPost
        method help_text (line 9) | def self.help_text
        method macrofilter (line 47) | def self.macrofilter(attrib, _text = "")

FILE: lib/publify_app/textfilter/htmlfilter.rb
  class PublifyApp (line 3) | class PublifyApp
    class Textfilter (line 4) | class Textfilter
      class Htmlfilter (line 5) | class Htmlfilter < TextFilterPlugin
        method filtertext (line 9) | def self.filtertext(text)

FILE: lib/publify_app/textfilter/lightbox.rb
  class PublifyApp (line 3) | class PublifyApp
    class Textfilter (line 4) | class Textfilter
      class Lightbox (line 5) | class Lightbox < TextFilterPlugin::MacroPost
        method help_text (line 9) | def self.help_text
        method macrofilter (line 83) | def self.macrofilter(attrib, _text = "")

FILE: lib/publify_plugins/avatar_plugin.rb
  type PublifyPlugins (line 5) | module PublifyPlugins
    class AvatarPlugin (line 6) | class AvatarPlugin < Base
      method kind (line 7) | def self.kind
      method get_avatar (line 11) | def self.get_avatar(_options = {})
      method name (line 15) | def self.name

FILE: lib/publify_plugins/gravatar.rb
  type PublifyPlugins (line 7) | module PublifyPlugins
    class Gravatar (line 8) | class Gravatar < AvatarPlugin
      method get_avatar (line 14) | def get_avatar(options = {})
      method name (line 19) | def name
      method gravatar_tag (line 27) | def gravatar_tag(email, options = {})

FILE: spec/rails_helper.rb
  class ActionView::TestCase::TestController (line 48) | class ActionView::TestCase::TestController
  function with_each_theme (line 104) | def with_each_theme

FILE: spec/views/comments/html_sanitization_spec.rb
  function comment_options (line 67) | def comment_options
  function comment_options (line 75) | def comment_options
  function comment_options (line 83) | def comment_options
  function comment_options (line 91) | def comment_options
  function comment_options (line 101) | def comment_options
  function comment_options (line 109) | def comment_options
  function comment_options (line 117) | def comment_options
  function comment_options (line 125) | def comment_options
  function comment_options (line 133) | def comment_options
  function comment_options (line 200) | def comment_options
  function comment_options (line 208) | def comment_options
  function comment_options (line 216) | def comment_options
  function comment_options (line 224) | def comment_options
  function comment_options (line 234) | def comment_options
  function comment_options (line 242) | def comment_options
  function comment_options (line 250) | def comment_options
  function comment_options (line 258) | def comment_options
  function comment_options (line 266) | def comment_options

FILE: themes/bootstrap-2/javascripts/bootstrap.js
  function transitionEnd (line 24) | function transitionEnd() {
  function removeElement (line 114) | function removeElement() {
  function Plugin (line 130) | function Plugin(option) {
  function Plugin (line 233) | function Plugin(option) {
  function Plugin (line 438) | function Plugin(option) {
  function Plugin (line 616) | function Plugin(option) {
  function clearMenus (line 754) | function clearMenus(e) {
  function getParent (line 767) | function getParent($this) {
  function Plugin (line 784) | function Plugin(option) {
  function Plugin (line 1052) | function Plugin(option, _relatedTarget) {
  function complete (line 1384) | function complete() {
  function Plugin (line 1531) | function Plugin(option) {
  function Plugin (line 1645) | function Plugin(option) {
  function ScrollSpy (line 1688) | function ScrollSpy(element, options) {
  function Plugin (line 1806) | function Plugin(option) {
  function next (line 1903) | function next() {
  function Plugin (line 1938) | function Plugin(option) {
  function Plugin (line 2071) | function Plugin(option) {
Condensed preview — 275 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (685K chars).
[
  {
    "path": ".erb-lint.yml",
    "chars": 562,
    "preview": "---\nlinters:\n  ErbSafety:\n    enabled: true\n  Rubocop:\n    enabled: true\n    rubocop_config:\n      inherit_from:\n       "
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 483,
    "preview": "# Documentation for all configuration options:\n# https://help.github.com/github/administering-a-repository/configuration"
  },
  {
    "path": ".github/workflows/ruby.yml",
    "chars": 2681,
    "preview": "# This workflow will download a prebuilt Ruby version, install dependencies and\n# run tests with Rake\n# For more informa"
  },
  {
    "path": ".gitignore",
    "chars": 616,
    "preview": "config/database.yml\nconfig/mail.yml\nconfig/timezone.yml\n*.log\n*~\ndb/db*\ndb/*.sqlite*\n.*.swp\n.*.swo\n.DS_Store\n.byebug_his"
  },
  {
    "path": ".hound.yml",
    "chars": 34,
    "preview": "ruby:\n  config_file: .rubocop.yml\n"
  },
  {
    "path": ".metrics",
    "chars": 169,
    "preview": "MetricFu::Configuration.run do |config|\n  config.rcov[:test_files] = 'spec/**/*_spec.rb'\n  config.rcov[:rcov_opts] << '-"
  },
  {
    "path": ".reek.yml",
    "chars": 508,
    "preview": "exclude_paths:\n  - 'db/migrate'\n  - 'publify_amazon_sidebar/spec/dummy/db/migrate'\n  - 'publify_textfilter_code/spec/dum"
  },
  {
    "path": ".rspec",
    "chars": 30,
    "preview": "--color\n--require spec_helper\n"
  },
  {
    "path": ".rubocop.yml",
    "chars": 4211,
    "preview": "inherit_from: .rubocop_todo.yml\n\ninherit_mode:\n  merge:\n    - Exclude\n\nplugins:\n  - rubocop-capybara\n  - rubocop-factory"
  },
  {
    "path": ".rubocop_todo.yml",
    "chars": 3454,
    "preview": "# This configuration was generated by\n# `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp`\n# using "
  },
  {
    "path": "CHANGELOG.md",
    "chars": 25153,
    "preview": "# Changelog\n\nSee the changelogs for the individual engines for more details for releases 9.0\nand up.\n\n## 10.0.1 / 2024-0"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3689,
    "preview": "# Contributing to Publify\n\nWe welcome contributions to Publify. Please follow the guidelines below to help the\nprocess o"
  },
  {
    "path": "Gemfile",
    "chars": 2872,
    "preview": "# frozen_string_literal: true\n\nsource \"https://rubygems.org\"\ngit_source(:github) { |repo| \"https://github.com/#{repo}.gi"
  },
  {
    "path": "MIT-LICENSE",
    "chars": 1171,
    "preview": "Copyright (c) 2005 Tobias Luetke\nCopyright (c) 2005-2013 Typo Developers & Contributors\nCopyright (c) 2013-2017 Publify "
  },
  {
    "path": "README.md",
    "chars": 5773,
    "preview": "# Publify\n\n**The Ruby on Rails publishing software formerly known as Typo**\n\n[![Build status](https://github.com/publify"
  },
  {
    "path": "Rakefile",
    "chars": 276,
    "preview": "# frozen_string_literal: true\n\n# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/task"
  },
  {
    "path": "TODO.txt",
    "chars": 107,
    "preview": "AdminSidebar:\n- On the fly save of params\n- CSS\n- Remove on staged/active sidebars\n- Maybe some animations\n"
  },
  {
    "path": "app/assets/config/manifest.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "app/assets/images/.keep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "app/controllers/application_controller.rb",
    "chars": 128,
    "preview": "# frozen_string_literal: true\n\nclass ApplicationController < ActionController::Base\n  protect_from_forgery with: :except"
  },
  {
    "path": "app/helpers/theme_helper.rb",
    "chars": 457,
    "preview": "# frozen_string_literal: true\n\nmodule ThemeHelper\n  # Adds per theme helpers if file exists. Ugly but at least it works."
  },
  {
    "path": "app/mailers/application_mailer.rb",
    "chars": 80,
    "preview": "# frozen_string_literal: true\n\nclass ApplicationMailer < ActionMailer::Base\nend\n"
  },
  {
    "path": "app/models/application_record.rb",
    "chars": 109,
    "preview": "# frozen_string_literal: true\n\nclass ApplicationRecord < ActiveRecord::Base\n  self.abstract_class = true\nend\n"
  },
  {
    "path": "app/models/authors_sidebar.rb",
    "chars": 414,
    "preview": "# frozen_string_literal: true\n\nclass AuthorsSidebar < Sidebar\n  display_name \"Authors\"\n  description \"Displays a list of"
  },
  {
    "path": "app/models/concerns/.keep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "app/models/livesearch_sidebar.rb",
    "chars": 202,
    "preview": "# frozen_string_literal: true\n\nclass LivesearchSidebar < Sidebar\n  description \"Adds livesearch to your Publify blog\"\n\n "
  },
  {
    "path": "app/models/notes_sidebar.rb",
    "chars": 354,
    "preview": "# frozen_string_literal: true\n\nclass NotesSidebar < Sidebar\n  description \"Displays the latest notes\"\n  setting :title, "
  },
  {
    "path": "app/models/popular_sidebar.rb",
    "chars": 354,
    "preview": "# frozen_string_literal: true\n\nclass PopularSidebar < Sidebar\n  description \"Displays the most popular posts\"\n  setting "
  },
  {
    "path": "app/models/xml_sidebar.rb",
    "chars": 669,
    "preview": "# frozen_string_literal: true\n\nclass XmlSidebar < Sidebar\n  display_name \"XML Syndication\"\n  description \"RSS and Atom f"
  },
  {
    "path": "app/views/authors_sidebar/_content.html.erb",
    "chars": 446,
    "preview": "<% cache sidebar.authors do %>\n<% unless sidebar.authors.blank? %>\n  <h3 class=\"sidebar-title\"><%= t('.authors') %></h3>"
  },
  {
    "path": "app/views/livesearch_sidebar/_content.html.erb",
    "chars": 606,
    "preview": "<h3 class=\"sidebar-title\">\n  <label for=\"q\"><%= sidebar.title %></label>\n</h3>\n<div class=\"sidebar-body\">\n  <%= form_tag"
  },
  {
    "path": "app/views/notes_sidebar/_content.html.erb",
    "chars": 567,
    "preview": "<% unless sidebar.notes.blank? %>\n  <h3 class=\"sidebar-title\"><%= sidebar.title %></h3>\n  <div class=\"sidebar-body\">\n   "
  },
  {
    "path": "app/views/popular_sidebar/_content.html.erb",
    "chars": 482,
    "preview": "<h3 class=\"sidebar-title\"><%= sidebar.title %></h3>\n<div class=\"sidemenu-content\">\n  <ul class=\"popular_sidebar\">\n    <%"
  },
  {
    "path": "app/views/xml_sidebar/_content.html.erb",
    "chars": 1042,
    "preview": "<h3 class=\"sidebar-title\"><%= t('.syndicate') %></h3>\n<div class=\"sidebar-body\">\n  <ul>\n    <% if sidebar.articles %>\n  "
  },
  {
    "path": "bin/bundle",
    "chars": 125,
    "preview": "#!/usr/bin/env ruby\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)\nload Gem.bin_path('bundler', 'bund"
  },
  {
    "path": "bin/i18n-tasks",
    "chars": 230,
    "preview": "#!/usr/bin/env ruby\nbegin\n  load File.expand_path('../spring', __FILE__)\nrescue LoadError => e\n  raise unless e.message."
  },
  {
    "path": "bin/rails",
    "chars": 141,
    "preview": "#!/usr/bin/env ruby\nAPP_PATH = File.expand_path(\"../config/application\", __dir__)\nrequire_relative \"../config/boot\"\nrequ"
  },
  {
    "path": "bin/rake",
    "chars": 90,
    "preview": "#!/usr/bin/env ruby\nrequire_relative \"../config/boot\"\nrequire \"rake\"\nRake.application.run\n"
  },
  {
    "path": "bin/rspec",
    "chars": 208,
    "preview": "#!/usr/bin/env ruby\nbegin\n  load File.expand_path('../spring', __FILE__)\nrescue LoadError => e\n  raise unless e.message."
  },
  {
    "path": "bin/setup",
    "chars": 984,
    "preview": "#!/usr/bin/env ruby\nrequire \"fileutils\"\n\n# path to your application root.\nAPP_ROOT = File.expand_path(\"..\", __dir__)\n\nde"
  },
  {
    "path": "bin/update",
    "chars": 819,
    "preview": "#!/usr/bin/env ruby\nrequire 'fileutils'\ninclude FileUtils\n\n# path to your application root.\nAPP_ROOT = File.expand_path("
  },
  {
    "path": "bin/yarn",
    "chars": 533,
    "preview": "#!/usr/bin/env ruby\nAPP_ROOT = File.expand_path('..', __dir__)\nDir.chdir(APP_ROOT) do\n  yarn = ENV[\"PATH\"].split(File::P"
  },
  {
    "path": "config/application.rb",
    "chars": 1191,
    "preview": "# frozen_string_literal: true\n\nrequire_relative \"boot\"\n\nrequire \"rails/all\"\n\n# Require the gems listed in Gemfile, inclu"
  },
  {
    "path": "config/boot.rb",
    "chars": 159,
    "preview": "# frozen_string_literal: true\n\nENV[\"BUNDLE_GEMFILE\"] ||= File.expand_path(\"../Gemfile\", __dir__)\n\nrequire \"bundler/setup"
  },
  {
    "path": "config/cable.yml",
    "chars": 188,
    "preview": "development:\n  adapter: async\n\ntest:\n  adapter: test\n\nproduction:\n  adapter: redis\n  url: <%= ENV.fetch(\"REDIS_URL\") { \""
  },
  {
    "path": "config/database.yml.mysql",
    "chars": 241,
    "preview": "login: &login\n  adapter: mysql2\n  host: 127.0.0.1\n  username: root\n  password: mysql\n  port: 3306\n\n\ndevelopment:\n  datab"
  },
  {
    "path": "config/database.yml.postgresql",
    "chars": 361,
    "preview": "login: &login\n  adapter: postgresql\n  host: localhost\n  port: 5432\n  username: postgres\n  password: postgres\n\nconnection"
  },
  {
    "path": "config/environment.rb",
    "chars": 159,
    "preview": "# frozen_string_literal: true\n\n# Load the Rails application.\nrequire_relative \"application\"\n\n# Initialize the Rails appl"
  },
  {
    "path": "config/environments/development.rb",
    "chars": 2703,
    "preview": "# frozen_string_literal: true\n\nrequire \"active_support/core_ext/integer/time\"\n\nRails.application.configure do\n  # Settin"
  },
  {
    "path": "config/environments/production.rb",
    "chars": 4350,
    "preview": "# frozen_string_literal: true\n\nrequire \"active_support/core_ext/integer/time\"\n\nRails.application.configure do\n  # Settin"
  },
  {
    "path": "config/environments/test.rb",
    "chars": 2674,
    "preview": "# frozen_string_literal: true\n\nrequire \"active_support/core_ext/integer/time\"\n\n# The test environment is used exclusivel"
  },
  {
    "path": "config/filemanager.yml",
    "chars": 419,
    "preview": "image.type: jpg gif png\nflash.type: swf\nmovie.type: mov avi wmv\nrm.type: rm rmvb\nplain.type: txt ini inf html htm rb jsp"
  },
  {
    "path": "config/i18n-tasks.yml",
    "chars": 1731,
    "preview": "# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks\n\n# The \"main\" locale"
  },
  {
    "path": "config/initializers/application_controller_renderer.rb",
    "chars": 247,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# ActiveSupport::Reloader.to"
  },
  {
    "path": "config/initializers/assets.rb",
    "chars": 533,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Version of your assets, ch"
  },
  {
    "path": "config/initializers/backtrace_silencers.rb",
    "chars": 575,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# You can add backtrace sile"
  },
  {
    "path": "config/initializers/carrierwave.rb",
    "chars": 760,
    "preview": "# frozen_string_literal: true\n\nif Rails.env.in?(%(test cucumber))\n  CarrierWave.configure do |config|\n    config.storage"
  },
  {
    "path": "config/initializers/content_security_policy.rb",
    "chars": 1102,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Define an application-wide"
  },
  {
    "path": "config/initializers/cookies_serializer.rb",
    "chars": 275,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Specify a serializer for t"
  },
  {
    "path": "config/initializers/filter_parameter_logging.rb",
    "chars": 483,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Configure parameters to be"
  },
  {
    "path": "config/initializers/flickr.rb",
    "chars": 344,
    "preview": "# frozen_string_literal: true\n\nrequire \"flickraw\"\n\n# Prepare needed FlickRaw methods\nFlickRaw::Flickr.build([\"flickr.pho"
  },
  {
    "path": "config/initializers/inflections.rb",
    "chars": 680,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules u"
  },
  {
    "path": "config/initializers/mime_types.rb",
    "chars": 187,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use"
  },
  {
    "path": "config/initializers/new_framework_defaults_7_1.rb",
    "chars": 12146,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n#\n# This file eases your Rail"
  },
  {
    "path": "config/initializers/non_digest_assets.rb",
    "chars": 93,
    "preview": "# frozen_string_literal: true\n\nNonDigestAssets.asset_selectors = [/\\.(?:svg|eot|woff|ttf)$/]\n"
  },
  {
    "path": "config/initializers/permissions_policy.rb",
    "chars": 511,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# Define an application-wide"
  },
  {
    "path": "config/initializers/rack_attack.rb",
    "chars": 575,
    "preview": "# frozen_string_literal: true\n\n# Throttle login attempts\nRack::Attack.throttle(\"logins/ip\", limit: 20, period: 1.hour) d"
  },
  {
    "path": "config/initializers/recaptcha.rb",
    "chars": 181,
    "preview": "# frozen_string_literal: true\n\nRecaptcha.configure do |config|\n  config.site_key = \"YourAPIkeysHere_yyyyyyyyyyyyyyyyy\"\n "
  },
  {
    "path": "config/initializers/session_store.rb",
    "chars": 292,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\nRails.application.config.ses"
  },
  {
    "path": "config/initializers/wrap_parameters.rb",
    "chars": 518,
    "preview": "# frozen_string_literal: true\n\n# Be sure to restart your server when you modify this file.\n\n# This file contains setting"
  },
  {
    "path": "config/locales/ar.yml",
    "chars": 838,
    "preview": "---\nar:\n  articles:\n    comment_counter:\n      comments:\n        few: بعض التعليقات\n        many: أكثر من تعليق\n        "
  },
  {
    "path": "config/locales/da.yml",
    "chars": 776,
    "preview": "---\nda:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 kommentar\n        other: \"%{count} kommentarer\"\n"
  },
  {
    "path": "config/locales/de.yml",
    "chars": 770,
    "preview": "---\nde:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 kommentar\n        other: \"%{count} kommentare\"\n "
  },
  {
    "path": "config/locales/en.yml",
    "chars": 766,
    "preview": "---\nen:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comment\n        other: \"%{count} comments\"\n     "
  },
  {
    "path": "config/locales/es-MX.yml",
    "chars": 803,
    "preview": "---\nes-MX:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 Comentario\n        other: \"%{count} Comentari"
  },
  {
    "path": "config/locales/fr.yml",
    "chars": 801,
    "preview": "---\nfr:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 commentaire\n        other: \"%{count} commentaire"
  },
  {
    "path": "config/locales/he.yml",
    "chars": 760,
    "preview": "---\nhe:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comment\n        other: \"%{count} comments\"\n     "
  },
  {
    "path": "config/locales/it.yml",
    "chars": 764,
    "preview": "---\nit:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 Commento\n        other: \"%{count} Commenti\"\n    "
  },
  {
    "path": "config/locales/ja.yml",
    "chars": 763,
    "preview": "---\nja:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comment\n        other: \"%{count} comments\"\n     "
  },
  {
    "path": "config/locales/lt.yml",
    "chars": 804,
    "preview": "---\nlt:\n  articles:\n    comment_counter:\n      comments:\n        few: \"%{count} Komentarai\"\n        one: 1 Komentaras\n  "
  },
  {
    "path": "config/locales/nb.yml",
    "chars": 811,
    "preview": "---\nnb:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 kommentar\n        other: \"%{count} kommentarer\"\n"
  },
  {
    "path": "config/locales/nl.yml",
    "chars": 762,
    "preview": "---\nnl:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comment\n        other: \"%{count} comments\"\n     "
  },
  {
    "path": "config/locales/pl.yml",
    "chars": 881,
    "preview": "---\npl:\n  articles:\n    comment_counter:\n      comments:\n        few: \"%{count} komentarzy\"\n        many: \"%{count} kome"
  },
  {
    "path": "config/locales/pt-BR.yml",
    "chars": 814,
    "preview": "---\npt-BR:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comentário\n        other: \"%{count} comentári"
  },
  {
    "path": "config/locales/ro.yml",
    "chars": 805,
    "preview": "---\nro:\n  articles:\n    comment_counter:\n      comments:\n        few: \"%{count} comentarii\"\n        one: 1 comentariu\n  "
  },
  {
    "path": "config/locales/ru.yml",
    "chars": 911,
    "preview": "---\nru:\n  articles:\n    comment_counter:\n      comments:\n        few: 'Комментариев: %{count}'\n        many: 'Комментари"
  },
  {
    "path": "config/locales/sidebars.ar.yml",
    "chars": 348,
    "preview": "---\nar:\n  authors_sidebar:\n    content:\n      authors: مؤلفين\n  notes_sidebar:\n    content:\n      view_on_twitter: شاهد "
  },
  {
    "path": "config/locales/sidebars.da.yml",
    "chars": 356,
    "preview": "---\nda:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.de.yml",
    "chars": 356,
    "preview": "---\nde:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.en.yml",
    "chars": 356,
    "preview": "---\nen:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.es-MX.yml",
    "chars": 359,
    "preview": "---\nes-MX:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: V"
  },
  {
    "path": "config/locales/sidebars.fr.yml",
    "chars": 356,
    "preview": "---\nfr:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.he.yml",
    "chars": 356,
    "preview": "---\nhe:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.it.yml",
    "chars": 356,
    "preview": "---\nit:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.ja.yml",
    "chars": 356,
    "preview": "---\nja:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.lt.yml",
    "chars": 356,
    "preview": "---\nlt:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.nb.yml",
    "chars": 356,
    "preview": "---\nnb:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.nl.yml",
    "chars": 356,
    "preview": "---\nnl:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.pl.yml",
    "chars": 358,
    "preview": "---\npl:\n  authors_sidebar:\n    content:\n      authors: Autorzy\n  notes_sidebar:\n    content:\n      view_on_twitter: Zoba"
  },
  {
    "path": "config/locales/sidebars.pt-BR.yml",
    "chars": 365,
    "preview": "---\npt-BR:\n  authors_sidebar:\n    content:\n      authors: Autores\n  notes_sidebar:\n    content:\n      view_on_twitter: V"
  },
  {
    "path": "config/locales/sidebars.ro.yml",
    "chars": 356,
    "preview": "---\nro:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: View"
  },
  {
    "path": "config/locales/sidebars.ru.yml",
    "chars": 362,
    "preview": "---\nru:\n  authors_sidebar:\n    content:\n      authors: Авторы\n  notes_sidebar:\n    content:\n      view_on_twitter: Просм"
  },
  {
    "path": "config/locales/sidebars.zh-CN.yml",
    "chars": 359,
    "preview": "---\nzh-CN:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: V"
  },
  {
    "path": "config/locales/sidebars.zh-TW.yml",
    "chars": 359,
    "preview": "---\nzh-TW:\n  authors_sidebar:\n    content:\n      authors: Authors\n  notes_sidebar:\n    content:\n      view_on_twitter: V"
  },
  {
    "path": "config/locales/zh-CN.yml",
    "chars": 766,
    "preview": "---\nzh-CN:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comment\n        other: \"%{count} comments\"\n  "
  },
  {
    "path": "config/locales/zh-TW.yml",
    "chars": 766,
    "preview": "---\nzh-TW:\n  articles:\n    comment_counter:\n      comments:\n        one: 1 comment\n        other: \"%{count} comments\"\n  "
  },
  {
    "path": "config/mail.yml.example",
    "chars": 223,
    "preview": "delivery_method: :smtp\nsettings:\n  :address: mail.example.com\n  :port:    25\n  :domain:  example.com\n# :authentication: "
  },
  {
    "path": "config/puma.rb",
    "chars": 1604,
    "preview": "# frozen_string_literal: true\n\n# Puma can serve each request in a thread from an internal thread pool.\n# The `threads` m"
  },
  {
    "path": "config/routes.rb",
    "chars": 171,
    "preview": "# frozen_string_literal: true\n\nRails.application.routes.draw do\n  # For details on the DSL available within this file, s"
  },
  {
    "path": "config/secrets.yml",
    "chars": 965,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key is used for verifying the integrity of si"
  },
  {
    "path": "config/spring.rb",
    "chars": 142,
    "preview": "# frozen_string_literal: true\n\n%w(\n  .ruby-version\n  .rbenv-vars\n  tmp/restart.txt\n  tmp/caching-dev.txt\n).each { |path|"
  },
  {
    "path": "config/storage.yml",
    "chars": 1093,
    "preview": "test:\n  service: Disk\n  root: <%= Rails.root.join(\"tmp/storage\") %>\n\nlocal:\n  service: Disk\n  root: <%= Rails.root.join("
  },
  {
    "path": "config.ru",
    "chars": 191,
    "preview": "# frozen_string_literal: true\n\n# This file is used by Rack-based servers to start the application.\n\nrequire_relative \"co"
  },
  {
    "path": "db/converters/README",
    "chars": 564,
    "preview": "These are converters for migrating from other blog systems to Publify. In\ngeneral, you're best off using the converter t"
  },
  {
    "path": "db/converters/blogger.rb",
    "chars": 2538,
    "preview": "#!/usr/bin/env ruby\n\n# Blogger converter to publify\n# Shamelessly copied from the RSS/Atom converter by Lennon Day-Reyno"
  },
  {
    "path": "db/converters/feed.rb",
    "chars": 1554,
    "preview": "#!/usr/bin/env ruby\n\n# RSS 0.2/2.0/Atom converter to publify by Lennon Day-Reynolds <rcoder@gmail.com>\n# Shamelessly cop"
  },
  {
    "path": "db/converters/rss.rb",
    "chars": 1659,
    "preview": "#!/usr/bin/env ruby\n\n# RSS 0.9/2.0 converter for publify by Chris Lee <clee@kde.org>\n#\n# No need to make a backup of the"
  },
  {
    "path": "db/migrate/113_initial_schema.publify_core_engine.rb",
    "chars": 5381,
    "preview": "# frozen_string_literal: true\n\nclass InitialSchema < ActiveRecord::Migration[4.2]\n  def change\n    create_table \"article"
  },
  {
    "path": "db/migrate/114_fixes_buggy_articles_and_notes.publify_core_engine.rb",
    "chars": 1114,
    "preview": "# frozen_string_literal: true\n\nclass FixesBuggyArticlesAndNotes < ActiveRecord::Migration[4.2]\n  class Content < ActiveR"
  },
  {
    "path": "db/migrate/115_drops_categories_for_tags.publify_core_engine.rb",
    "chars": 894,
    "preview": "# frozen_string_literal: true\n\nclass DropsCategoriesForTags < ActiveRecord::Migration[4.2]\n  class Categorization < Acti"
  },
  {
    "path": "db/migrate/20150207131657_add_missing_indexes.publify_core_engine.rb",
    "chars": 707,
    "preview": "# frozen_string_literal: true\n\nclass AddMissingIndexes < ActiveRecord::Migration[4.2]\n  def change\n    add_index :feedba"
  },
  {
    "path": "db/migrate/20150807134129_simplify_redirect_relations.publify_core_engine.rb",
    "chars": 1155,
    "preview": "# frozen_string_literal: true\n\nclass SimplifyRedirectRelations < ActiveRecord::Migration[4.2]\n  class Redirect < ActiveR"
  },
  {
    "path": "db/migrate/20150808052637_add_blog_ids.publify_core_engine.rb",
    "chars": 955,
    "preview": "# frozen_string_literal: true\n\nclass AddBlogIds < ActiveRecord::Migration[4.2]\n  class Blog < ActiveRecord::Base; end\n\n "
  },
  {
    "path": "db/migrate/20150808191127_add_blog_id_to_redirects.publify_core_engine.rb",
    "chars": 391,
    "preview": "# frozen_string_literal: true\n\nclass AddBlogIdToRedirects < ActiveRecord::Migration[4.2]\n  class Redirect < ActiveRecord"
  },
  {
    "path": "db/migrate/20150810094754_add_blog_id_to_tags.publify_core_engine.rb",
    "chars": 361,
    "preview": "# frozen_string_literal: true\n\nclass AddBlogIdToTags < ActiveRecord::Migration[4.2]\n  class Tag < ActiveRecord::Base; en"
  },
  {
    "path": "db/migrate/20160108111120_add_devise_to_users.publify_core_engine.rb",
    "chars": 1717,
    "preview": "# frozen_string_literal: true\n\nclass AddDeviseToUsers < ActiveRecord::Migration[4.2]\n  def self.up\n    ## Database authe"
  },
  {
    "path": "db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.publify_core_engine.rb",
    "chars": 389,
    "preview": "# frozen_string_literal: true\n\nclass MoveLastConnectionToLastSignInAt < ActiveRecord::Migration[4.2]\n  class User < Acti"
  },
  {
    "path": "db/migrate/20160110094906_remove_profiles_rights.publify_core_engine.rb",
    "chars": 319,
    "preview": "# frozen_string_literal: true\n\nclass RemoveProfilesRights < ActiveRecord::Migration[4.2]\n  def up\n    drop_table :profil"
  },
  {
    "path": "db/migrate/20160605103918_replace_profile_id_with_string.publify_core_engine.rb",
    "chars": 679,
    "preview": "# frozen_string_literal: true\n\nclass ReplaceProfileIdWithString < ActiveRecord::Migration[4.2]\n  class Profile < ActiveR"
  },
  {
    "path": "db/migrate/20160605154632_remove_profiles.publify_core_engine.rb",
    "chars": 930,
    "preview": "# frozen_string_literal: true\n\nclass RemoveProfiles < ActiveRecord::Migration[4.2]\n  class Profile < ActiveRecord::Base\n"
  },
  {
    "path": "db/migrate/20160701061851_demand_blog_id_on_contents.publify_core_engine.rb",
    "chars": 249,
    "preview": "# frozen_string_literal: true\n\nclass DemandBlogIdOnContents < ActiveRecord::Migration[4.2]\n  def up\n    change_column :c"
  },
  {
    "path": "db/migrate/20160701062604_add_blog_id_to_resources.publify_core_engine.rb",
    "chars": 786,
    "preview": "# frozen_string_literal: true\n\nclass AddBlogIdToResources < ActiveRecord::Migration[4.2]\n  class Blog < ActiveRecord::Ba"
  },
  {
    "path": "db/migrate/20161030121548_add_sessions_table.rb",
    "chars": 329,
    "preview": "# frozen_string_literal: true\n\nclass AddSessionsTable < ActiveRecord::Migration[4.2]\n  def change\n    create_table :sess"
  },
  {
    "path": "db/migrate/20170528093428_move_resources_to_content.publify_core_engine.rb",
    "chars": 245,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20170528093024)\nclass MoveRes"
  },
  {
    "path": "db/migrate/20170528120220_move_tags_to_content.publify_core_engine.rb",
    "chars": 292,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20170528094923)\nclass MoveTag"
  },
  {
    "path": "db/migrate/20170530063901_remove_separate_published_flag.publify_core_engine.rb",
    "chars": 261,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20170528201606)\nclass RemoveS"
  },
  {
    "path": "db/migrate/20170605103539_remove_extra_state_columns_from_feedback.publify_core_engine.rb",
    "chars": 326,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20170605071626)\nclass RemoveE"
  },
  {
    "path": "db/migrate/20170702105518_remove_published_at_from_feedback.publify_core_engine.rb",
    "chars": 251,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20170702105201)\nclass RemoveP"
  },
  {
    "path": "db/migrate/20190210121314_add_text_filter_name_fields.publify_core_engine.rb",
    "chars": 347,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20190208151235)\nclass AddText"
  },
  {
    "path": "db/migrate/20190210121315_move_text_filter_to_name.publify_core_engine.rb",
    "chars": 2943,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20190208152646)\nclass MoveTex"
  },
  {
    "path": "db/migrate/20190210121316_remove_text_filter_ids.publify_core_engine.rb",
    "chars": 626,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20190209155717)\nclass RemoveT"
  },
  {
    "path": "db/migrate/20190210121317_remove_text_filters.publify_core_engine.rb",
    "chars": 389,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20190209160610)\nclass RemoveT"
  },
  {
    "path": "db/migrate/20200413141133_add_unique_indexes.publify_core_engine.rb",
    "chars": 379,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20200413140440)\n\nclass AddUni"
  },
  {
    "path": "db/migrate/20221007091118_remove_table_sitealizer.publify_core_engine.rb",
    "chars": 444,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20221007091049)\nclass RemoveT"
  },
  {
    "path": "db/migrate/20221010170801_remove_page_caches_table.publify_core_engine.rb",
    "chars": 332,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20221010092846)\nclass RemoveP"
  },
  {
    "path": "db/migrate/20221012164027_remove_itunes_fields_from_resources.publify_core_engine.rb",
    "chars": 645,
    "preview": "# frozen_string_literal: true\n\n# This migration comes from publify_core_engine (originally 20221012163214)\nclass RemoveI"
  },
  {
    "path": "db/schema.rb",
    "chars": 6545,
    "preview": "# This file is auto-generated from the current state of the database. Instead\n# of editing this file, please use the mig"
  },
  {
    "path": "db/seeds.rb",
    "chars": 61,
    "preview": "# frozen_string_literal: true\n\nPublifyCore::Engine.load_seed\n"
  },
  {
    "path": "doc/CACHE.SETUP.README",
    "chars": 1410,
    "preview": "To fully profit from Publify static caching capabilities, you need to add the\nfollowing rewrite rules to either your .ht"
  },
  {
    "path": "doc/dependency_decisions.yml",
    "chars": 1118,
    "preview": "---\n- - :permit\n  - MIT\n  - :who: \n    :why: \n    :versions: []\n    :when: 2017-07-22 20:10:47.517185110 Z\n- - :permit\n "
  },
  {
    "path": "lib/generators/sidebar/USAGE",
    "chars": 280,
    "preview": "Description:\n    Generate Sidebar plugin for Typo\n\nExample:\n    rails generate sidebar ThingSidebar\n\n    This will creat"
  },
  {
    "path": "lib/generators/sidebar/sidebar_generator.rb",
    "chars": 488,
    "preview": "# frozen_string_literal: true\n\nclass SidebarGenerator < Rails::Generators::NamedBase\n  source_root File.expand_path(\"tem"
  },
  {
    "path": "lib/generators/sidebar/templates/_content.html.erb.erb",
    "chars": 522,
    "preview": "<h3 class='sidebar-title'><%= class_name %></h3>\n<div class='<%= file_name.sub(/_sidebar/, '') %>'-body>\n<p>Replace this"
  },
  {
    "path": "lib/generators/sidebar/templates/model_spec.rb.erb",
    "chars": 170,
    "preview": "require 'rails_helper'\n\nRSpec.describe <%= class_name %> do\n  it 'is available' do\n    expect(SidebarRegistry.available_"
  },
  {
    "path": "lib/generators/sidebar/templates/sidebar.rb.erb",
    "chars": 608,
    "preview": "class <%= class_name %> < Sidebar\n  # display_name \"<%= class_name.underscore.humanize %>\" # Default\n  description \"Desc"
  },
  {
    "path": "lib/publify_app/textfilter/flickr.rb",
    "chars": 3735,
    "preview": "# frozen_string_literal: true\n\nclass PublifyApp\n  class Textfilter\n    class Flickr < TextFilterPlugin::MacroPost\n      "
  },
  {
    "path": "lib/publify_app/textfilter/htmlfilter.rb",
    "chars": 305,
    "preview": "# frozen_string_literal: true\n\nclass PublifyApp\n  class Textfilter\n    class Htmlfilter < TextFilterPlugin\n      plugin_"
  },
  {
    "path": "lib/publify_app/textfilter/lightbox.rb",
    "chars": 6327,
    "preview": "# frozen_string_literal: true\n\nclass PublifyApp\n  class Textfilter\n    class Lightbox < TextFilterPlugin::MacroPost\n    "
  },
  {
    "path": "lib/publify_plugins/avatar_plugin.rb",
    "chars": 297,
    "preview": "# frozen_string_literal: true\n\nrequire \"publify_plugins\"\n\nmodule PublifyPlugins\n  class AvatarPlugin < Base\n    def self"
  },
  {
    "path": "lib/publify_plugins/gravatar.rb",
    "chars": 1258,
    "preview": "# frozen_string_literal: true\n\nrequire \"publify_plugins\"\nrequire \"publify_plugins/avatar_plugin\"\n\n# PublifyAvatarGravata"
  },
  {
    "path": "lib/tasks/i18n.rake",
    "chars": 255,
    "preview": "# frozen_string_literal: true\n\nrequire \"English\"\n\nnamespace :i18n do\n  desc \"Check translation health\"\n  task :health do"
  },
  {
    "path": "lib/tasks/rubocop.rake",
    "chars": 343,
    "preview": "# frozen_string_literal: true\n\nbegin\n  require \"rubocop/rake_task\"\n\n  RuboCop::RakeTask.new do |task|\n    task.options <"
  },
  {
    "path": "log/.keep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "public/404.html",
    "chars": 1564,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <title>The page you were looking for doesn't exist (404)</title>\n  <meta name=\"viewport\""
  },
  {
    "path": "public/422.html",
    "chars": 1547,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <title>The change you wanted was rejected (422)</title>\n  <meta name=\"viewport\" content="
  },
  {
    "path": "public/500.html",
    "chars": 1477,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <title>We're sorry, but something went wrong (500)</title>\n  <meta name=\"viewport\" conte"
  },
  {
    "path": "spec/controllers/articles_controller_spec.rb",
    "chars": 13019,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\n# Test article rendering for installed themes\nRSpec.describe Arti"
  },
  {
    "path": "spec/controllers/feedback_controller_spec.rb",
    "chars": 1394,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe FeedbackController, type: :controller do\n  render_"
  },
  {
    "path": "spec/controllers/tags_controller_spec.rb",
    "chars": 2127,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe TagsController, type: :controller do\n  render_view"
  },
  {
    "path": "spec/controllers/xml_controller_spec.rb",
    "chars": 457,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe XmlController, type: :controller do\n  render_views"
  },
  {
    "path": "spec/features/switch_theme_spec.rb",
    "chars": 600,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.feature \"Changing themes\", type: :feature do\n  let(:admin) "
  },
  {
    "path": "spec/lib/publify_plugins/gravatar_spec.rb",
    "chars": 705,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe PublifyPlugins::Gravatar do\n  describe \".get_avata"
  },
  {
    "path": "spec/lib/publify_textfilter_flickr_spec.rb",
    "chars": 5253,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe \"the Flickr text filter plugin\", type: :model do\n "
  },
  {
    "path": "spec/lib/publify_textfilter_lightbox_spec.rb",
    "chars": 4670,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe \"the Lightbox text filter plugin\", type: :model do"
  },
  {
    "path": "spec/lib/text_filter_plugin_spec.rb",
    "chars": 954,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe TextFilterPlugin do\n  describe \".available_filters"
  },
  {
    "path": "spec/models/authors_sidebar_spec.rb",
    "chars": 445,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe AuthorsSidebar do\n  let(:sidebar) { described_clas"
  },
  {
    "path": "spec/models/notes_sidebar_spec.rb",
    "chars": 194,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe NotesSidebar do\n  it \"is available\" do\n    expect("
  },
  {
    "path": "spec/models/popular_sidebar_spec.rb",
    "chars": 196,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe PopularSidebar do\n  it \"is available\" do\n    expec"
  },
  {
    "path": "spec/models/sidebar_registry_spec.rb",
    "chars": 658,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe SidebarRegistry do\n  describe \"#available_sidebars"
  },
  {
    "path": "spec/models/xml_sidebar_spec.rb",
    "chars": 192,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe XmlSidebar do\n  it \"is available\" do\n    expect(Si"
  },
  {
    "path": "spec/rails_helper.rb",
    "chars": 4731,
    "preview": "# frozen_string_literal: true\n\n# This file is copied to spec/ when you run 'rails generate rspec:install'\nrequire \"spec_"
  },
  {
    "path": "spec/spec_helper.rb",
    "chars": 5070,
    "preview": "# frozen_string_literal: true\n\n# This file was generated by the `rails generate rspec:install` command. Conventionally, "
  },
  {
    "path": "spec/views/comments/html_sanitization_spec.rb",
    "chars": 8063,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe \"comments/_comment.html.erb\", type: :view do\n  sha"
  },
  {
    "path": "spec/views/layouts/default_spec.rb",
    "chars": 881,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe \"layouts/default.html.erb\", type: :view do\n  with_"
  },
  {
    "path": "spec/views/xml_sidebar/_content.html.erb_spec.rb",
    "chars": 1487,
    "preview": "# frozen_string_literal: true\n\nrequire \"rails_helper\"\n\nRSpec.describe \"xml_sidebar/_content.html.erb\", type: :view do\n  "
  },
  {
    "path": "themes/bootstrap-2/about.markdown",
    "chars": 638,
    "preview": "#### Bootstrap theme for Publify\n\nBootstrap 2 is a theme designed for the [Publify][1] blogging engine by [Frédéric\nde V"
  },
  {
    "path": "themes/bootstrap-2/javascripts/bootstrap.js",
    "chars": 60681,
    "preview": "/*!\n * Bootstrap v3.2.0 (http://getbootstrap.com)\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://gi"
  },
  {
    "path": "themes/bootstrap-2/less/.csscomb.json",
    "chars": 7842,
    "preview": "{\n  \"always-semicolon\": true,\n  \"block-indent\": 2,\n  \"colon-space\": [0, 1],\n  \"color-case\": \"lower\",\n  \"color-shorthand\""
  },
  {
    "path": "themes/bootstrap-2/less/.csslintrc",
    "chars": 456,
    "preview": "{\n  \"adjoining-classes\": false,\n  \"box-sizing\": false,\n  \"box-model\": false,\n  \"compatible-vendor-prefixes\": false,\n  \"f"
  },
  {
    "path": "themes/bootstrap-2/less/alerts.less",
    "chars": 1513,
    "preview": "//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert"
  },
  {
    "path": "themes/bootstrap-2/less/badges.less",
    "chars": 1069,
    "preview": "//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n  display: inline-block;\n  m"
  },
  {
    "path": "themes/bootstrap-2/less/bootstrap.less",
    "chars": 1121,
    "preview": "// Core variables and mixins\n@import \"variables.less\";\n@import \"mixins.less\";\n\n// Reset and dependencies\n@import \"normal"
  },
  {
    "path": "themes/bootstrap-2/less/breadcrumbs.less",
    "chars": 594,
    "preview": "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: @breadcrumb-padding-v"
  },
  {
    "path": "themes/bootstrap-2/less/button-groups.less",
    "chars": 5484,
    "preview": "//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-gro"
  },
  {
    "path": "themes/bootstrap-2/less/buttons.less",
    "chars": 3500,
    "preview": "//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------"
  },
  {
    "path": "themes/bootstrap-2/less/carousel.less",
    "chars": 4759,
    "preview": "//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators"
  },
  {
    "path": "themes/bootstrap-2/less/close.less",
    "chars": 683,
    "preview": "//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: (@font-s"
  },
  {
    "path": "themes/bootstrap-2/less/code.less",
    "chars": 1378,
    "preview": "//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\nco"
  },
  {
    "path": "themes/bootstrap-2/less/component-animations.less",
    "chars": 585,
    "preview": "//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `."
  },
  {
    "path": "themes/bootstrap-2/less/dropdowns.less",
    "chars": 4782,
    "preview": "//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n  display:"
  }
]

// ... and 75 more files (download for full content)

About this extraction

This page contains the full source code of the fdv/typo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 275 files (621.7 KB), approximately 178.4k tokens, and a symbol index with 198 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!