publify_core 10.0.0 → 10.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/app/controllers/admin/articles_controller.rb +1 -1
- data/app/controllers/admin/post_types_controller.rb +1 -1
- data/app/controllers/articles_controller.rb +2 -2
- data/app/controllers/setup_controller.rb +20 -11
- data/app/helpers/base_helper.rb +1 -1
- data/app/models/article.rb +1 -2
- data/app/models/note.rb +1 -1
- data/app/uploaders/resource_uploader.rb +3 -9
- data/app/views/notes/show_in_reply.html.erb +1 -1
- data/app/views/setup/index.html.erb +42 -11
- data/db/seeds.rb +5 -5
- data/lib/publify_core/string_ext.rb +52 -0
- data/lib/publify_core/text_filter/markdown.rb +53 -0
- data/lib/{publify_textfilter_markdown_smartquotes.rb → publify_core/text_filter/markdown_smartquotes.rb} +3 -3
- data/lib/publify_core/text_filter/none.rb +14 -0
- data/lib/publify_core/text_filter/smartypants.rb +14 -0
- data/lib/publify_core/text_filter/twitterfilter.rb +55 -0
- data/lib/publify_core/version.rb +1 -1
- data/lib/publify_core.rb +6 -6
- data/lib/text_filter_plugin.rb +23 -11
- metadata +45 -25
- data/lib/publify_textfilter_markdown.rb +0 -56
- data/lib/publify_textfilter_none.rb +0 -16
- data/lib/publify_textfilter_smartypants.rb +0 -16
- data/lib/publify_textfilter_twitterfilter.rb +0 -57
- data/lib/transforms.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f07659f73a5dbeb0204128c9d42e6fcec4092ed7d4e920dceac39f1d104531f3
|
4
|
+
data.tar.gz: cef962bcdc17d957b1824f6e529534c48fdadb473280c910a33198cbcb49d2e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f1262b50e741c94cf9bfcf2cc9d30dade5ae00fccbb5a33206789e7a900af47d280246b204b4f6671f2baaf18547fa1c98aad558d890500347ce58cf97d14f6
|
7
|
+
data.tar.gz: 58e3228983425a5a802714855453184d726f351b81475c0f36f63acf19486c61c0be3f54b26a5cb205f0db48924158840a978fb83888c33cbbcaeaddc9d65b98
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 10.0.1 / 2023-10-28
|
4
|
+
|
5
|
+
* Update CarrierWave dependency to version 3.0 ([#102] by [mvz])
|
6
|
+
* Move String monkey-patches into a module under PublifyCore ([#115] by [mvz])
|
7
|
+
* Remove text filter plugin naming requirements ([#109], [#110], [#117] by [mvz])
|
8
|
+
* Fix name and description of Twitterfilter ([#118] by [mvz])
|
9
|
+
* Fix link to pull request in CHANGELOG ([#116] by [mvz])
|
10
|
+
* Provide proper validation feedback during setup ([#119] by [mvz])
|
11
|
+
|
12
|
+
[#102]: https://github.com/publify/publify_core/pull/102
|
13
|
+
[#109]: https://github.com/publify/publify_core/pull/109
|
14
|
+
[#110]: https://github.com/publify/publify_core/pull/110
|
15
|
+
[#115]: https://github.com/publify/publify_core/pull/115
|
16
|
+
[#116]: https://github.com/publify/publify_core/pull/116
|
17
|
+
[#117]: https://github.com/publify/publify_core/pull/117
|
18
|
+
[#118]: https://github.com/publify/publify_core/pull/118
|
19
|
+
[#119]: https://github.com/publify/publify_core/pull/119
|
20
|
+
[mvz]: https://github.com/mvz
|
21
|
+
[dependabot]: https://github.com/apps/dependabot
|
22
|
+
|
3
23
|
## 10.0.0 / 2023-06-25
|
4
24
|
|
5
25
|
### Updated dependencies
|
@@ -37,7 +57,7 @@
|
|
37
57
|
* Remove `sitealizer` table [publify#1089](https://github.com/publify/publify/pull/1089) by [SupriyaMedankar](https://github.com/SupriyaMedankar)
|
38
58
|
* Remove itunes fields from resources [publify#1092](https://github.com/publify/publify/pull/1092) by [SupriyaMedankar](https://github.com/SupriyaMedankar)
|
39
59
|
* Remove `page_caches` table [publify#1090](https://github.com/publify/publify/pull/1090) by [SupriyaMedankar](https://github.com/SupriyaMedankar)
|
40
|
-
* Remove obsolete Sidebar code [
|
60
|
+
* Remove obsolete Sidebar code [publify_core#58](https://github.com/publify/publify_core/pull/58)
|
41
61
|
|
42
62
|
## 9.2.10 / 2023-01-08
|
43
63
|
|
@@ -93,7 +93,7 @@ class Admin::ArticlesController < Admin::BaseController
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def auto_complete_for_article_keywords
|
96
|
-
@items = Tag.
|
96
|
+
@items = Tag.order(:display_name).pluck(:display_name)
|
97
97
|
render json: @items
|
98
98
|
end
|
99
99
|
|
@@ -38,7 +38,7 @@ class Admin::PostTypesController < Admin::BaseController
|
|
38
38
|
# Reset all Articles from the PostType we're destroying to the default PostType
|
39
39
|
# Wrap it in a transaction for safety
|
40
40
|
@post_type.transaction do
|
41
|
-
Article.where(post_type: @post_type.permalink).
|
41
|
+
Article.where(post_type: @post_type.permalink).find_each do |article|
|
42
42
|
article.post_type = "read"
|
43
43
|
article.save
|
44
44
|
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
class ArticlesController < ContentController
|
4
4
|
before_action :login_required, only: [:preview, :preview_page]
|
5
|
-
before_action :auto_discovery_feed, only: [:show, :index]
|
6
5
|
before_action :verify_config
|
6
|
+
before_action :auto_discovery_feed, only: [:show, :index]
|
7
7
|
|
8
8
|
layout :theme_layout, except: [:trackback]
|
9
9
|
|
@@ -201,7 +201,7 @@ class ArticlesController < ContentController
|
|
201
201
|
case from
|
202
202
|
when /^.*\.rss$/
|
203
203
|
request.format = "rss"
|
204
|
-
from = from.gsub(/\.rss
|
204
|
+
from = from.gsub(/\.rss$/, "")
|
205
205
|
when /^.*\.atom$/
|
206
206
|
request.format = "atom"
|
207
207
|
from = from.gsub(/\.atom$/, "")
|
@@ -4,23 +4,24 @@ class SetupController < BaseController
|
|
4
4
|
before_action :check_config
|
5
5
|
layout "accounts"
|
6
6
|
|
7
|
-
def index
|
7
|
+
def index
|
8
|
+
this_blog.blog_name = ""
|
9
|
+
@user = User.new
|
10
|
+
end
|
8
11
|
|
9
12
|
def create
|
10
|
-
this_blog.blog_name =
|
13
|
+
this_blog.blog_name = blog_params[:blog_name]
|
11
14
|
this_blog.base_url = blog_base_url
|
12
15
|
|
13
|
-
@user = User.new(login: "admin",
|
14
|
-
|
15
|
-
|
16
|
-
text_filter_name: this_blog.text_filter,
|
17
|
-
nickname: "Publify Admin")
|
16
|
+
@user = User.new(user_params.merge(login: "admin",
|
17
|
+
text_filter_name: this_blog.text_filter,
|
18
|
+
nickname: "Publify Admin"))
|
18
19
|
@user.name = @user.login
|
19
20
|
|
20
|
-
unless this_blog.
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
return render :index unless this_blog.valid? && @user.valid?
|
22
|
+
|
23
|
+
this_blog.save!
|
24
|
+
@user.save!
|
24
25
|
|
25
26
|
sign_in @user
|
26
27
|
|
@@ -36,6 +37,14 @@ class SetupController < BaseController
|
|
36
37
|
|
37
38
|
private
|
38
39
|
|
40
|
+
def blog_params
|
41
|
+
params.require(:blog).permit(:blog_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def user_params
|
45
|
+
params.require(:user).permit(:email, :password)
|
46
|
+
end
|
47
|
+
|
39
48
|
def create_first_post(user)
|
40
49
|
this_blog.articles.build(title: I18n.t("setup.article.title"),
|
41
50
|
author: user.login,
|
data/app/helpers/base_helper.rb
CHANGED
@@ -138,7 +138,7 @@ module BaseHelper
|
|
138
138
|
v = v.chomp
|
139
139
|
# trim the same number of spaces from the beginning of each line
|
140
140
|
# this way plugins can indent nicely without making ugly source output
|
141
|
-
spaces = /\A[ \t]*/.match(v)[0].gsub(
|
141
|
+
spaces = /\A[ \t]*/.match(v)[0].gsub("\t", " ")
|
142
142
|
# add 2 spaces to line up with the assumed position of the surrounding tags
|
143
143
|
v.gsub!(/^#{spaces}/, " ")
|
144
144
|
end
|
data/app/models/article.rb
CHANGED
data/app/models/note.rb
CHANGED
@@ -57,11 +57,9 @@ class ResourceUploader < CarrierWave::Uploader::Base
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def check_content_type!(new_file)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
file_content_type(new_file)
|
64
|
-
end
|
60
|
+
return unless image? new_file
|
61
|
+
|
62
|
+
detected_type = file_content_content_type(new_file)
|
65
63
|
if detected_type != new_file.content_type
|
66
64
|
raise CarrierWave::IntegrityError, "has MIME type mismatch"
|
67
65
|
end
|
@@ -72,8 +70,4 @@ class ResourceUploader < CarrierWave::Uploader::Base
|
|
72
70
|
def file_content_content_type(new_file)
|
73
71
|
Marcel::MimeType.for Pathname.new(new_file.path)
|
74
72
|
end
|
75
|
-
|
76
|
-
def file_content_type(new_file)
|
77
|
-
Marcel::MimeType.for Pathname.new(new_file.path), name: new_file.filename
|
78
|
-
end
|
79
73
|
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<%= image_tag(@reply['user']['profile_image_url'], class: 'alignleft', alt: @reply['user']['name']) %>
|
6
6
|
<% end %>
|
7
7
|
<strong><%= get_reply_context_url(@reply) %></strong>
|
8
|
-
<p><%= nofollowify_links(
|
8
|
+
<p><%= nofollowify_links(PublifyCore::TextFilter::Twitterfilter.filtertext(@reply['text'])) %></p>
|
9
9
|
<p>
|
10
10
|
<small>
|
11
11
|
<%= get_reply_context_twitter_link(@reply) %>
|
@@ -1,17 +1,48 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-md-8 col-md-offset-2" id="error-message-page">
|
3
|
+
<% if this_blog.errors.any? %>
|
4
|
+
<div id="error_explanation">
|
5
|
+
<h2><%= t("errors.template.header", model: 'blog', count: this_blog.errors.count) %></h2>
|
6
|
+
<p><%= t("errors.template.body") %></p>
|
7
|
+
<ul>
|
8
|
+
<% this_blog.errors.full_messages.each do |message| %>
|
9
|
+
<li><%= message %></li>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
<% if @user.errors.any? %>
|
15
|
+
<div id="error_explanation">
|
16
|
+
<h2><%= t("errors.template.header", model: 'blog', count: @user.errors.count) %></h2>
|
17
|
+
<p><%= t("errors.template.body") %></p>
|
18
|
+
<ul>
|
19
|
+
<% @user.errors.full_messages.each do |message| %>
|
20
|
+
<li><%= message %></li>
|
21
|
+
<% end %>
|
22
|
+
</ul>
|
23
|
+
</div>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
|
1
28
|
<%= form_tag action: 'index' do %>
|
2
29
|
<div class='alert alert-info'>
|
3
30
|
<small><%= t('.welcome_to_your_blog_setup', publify: link_to('Publify', 'https://publify.github.io/')) %></small>
|
4
31
|
</div>
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
32
|
+
<%= fields model: this_blog do |form| %>
|
33
|
+
<div class='form-group'>
|
34
|
+
<%= form.text_field(:blog_name, class: 'form-control', placeholder: t('.blog_name')) %>
|
35
|
+
</div>
|
36
|
+
<% end %>
|
37
|
+
<%= fields model: @user do |form| %>
|
38
|
+
<div class='form-group'>
|
39
|
+
<%= form.text_field(:email, class: 'form-control', placeholder: t('.your_mail')) %>
|
40
|
+
</div>
|
41
|
+
<div class='form-group'>
|
42
|
+
<%= form.label :password, t('.password') %><br>
|
43
|
+
<%= form.password_field(:password, class: 'form-control') %>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
15
46
|
|
16
|
-
<input type="submit" id="submit" class='btn btn-lg btn-success btn-block' value="<%= t('generic.save') %>"
|
47
|
+
<input type="submit" id="submit" class='btn btn-lg btn-success btn-block' value="<%= t('generic.save') %>">
|
17
48
|
<% end %>
|
data/db/seeds.rb
CHANGED
@@ -13,9 +13,9 @@
|
|
13
13
|
blog = Blog.first || Blog.create!
|
14
14
|
|
15
15
|
unless blog.sidebars.any?
|
16
|
-
PageSidebar.create!(active_position: 0, staged_position: 0,
|
17
|
-
TagSidebar.create!(active_position: 1,
|
18
|
-
ArchivesSidebar.create!(active_position: 2,
|
19
|
-
StaticSidebar.create!(active_position: 3,
|
20
|
-
MetaSidebar.create!(active_position: 4,
|
16
|
+
PageSidebar.create!(active_position: 0, staged_position: 0, blog: blog)
|
17
|
+
TagSidebar.create!(active_position: 1, blog: blog)
|
18
|
+
ArchivesSidebar.create!(active_position: 2, blog: blog)
|
19
|
+
StaticSidebar.create!(active_position: 3, blog: blog)
|
20
|
+
MetaSidebar.create!(active_position: 4, blog: blog)
|
21
21
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# FIXME: Replace with helpers and/or methods provided by Rails
|
4
|
+
module PublifyCore
|
5
|
+
module StringExt
|
6
|
+
ACCENTS = { %w(á à â ä ã Ã Ä Â À) => "a",
|
7
|
+
%w(é è ê ë Ë É È Ê) => "e",
|
8
|
+
%w(í ì î ï I Î Ì) => "i",
|
9
|
+
%w(ó ò ô ö õ Õ Ö Ô Ò) => "o",
|
10
|
+
["œ"] => "oe",
|
11
|
+
["ß"] => "ss",
|
12
|
+
%w(ú ù û ü U Û Ù) => "u",
|
13
|
+
%w(ç Ç) => "c" }.freeze
|
14
|
+
|
15
|
+
def to_permalink
|
16
|
+
string = self
|
17
|
+
ACCENTS.each do |key, value|
|
18
|
+
string = string.tr(key.join, value)
|
19
|
+
end
|
20
|
+
string = string.tr("'", "-")
|
21
|
+
string.gsub(/<[^>]*>/, "").to_url
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns a-string-with-dashes when passed 'a string with dashes'.
|
25
|
+
# All special chars are stripped in the process
|
26
|
+
def to_url
|
27
|
+
return if nil?
|
28
|
+
|
29
|
+
s = downcase.tr("\"'", "")
|
30
|
+
s = s.gsub(/\P{Word}/, " ")
|
31
|
+
s.strip.tr_s(" ", "-").tr(" ", "-").sub(/^$/, "-")
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_title(item, settings, params)
|
35
|
+
TitleBuilder.new(self).build(item, settings, params)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Strips any html markup from a string
|
39
|
+
TYPO_TAG_KEY = TYPO_ATTRIBUTE_KEY = /[\w:_-]+/.freeze
|
40
|
+
TYPO_ATTRIBUTE_VALUE = /(?:[A-Za-z0-9]+|(?:'[^']*?'|"[^"]*?"))/.freeze
|
41
|
+
TYPO_ATTRIBUTE = /(?:#{TYPO_ATTRIBUTE_KEY}(?:\s*=\s*#{TYPO_ATTRIBUTE_VALUE})?)/.freeze
|
42
|
+
TYPO_ATTRIBUTES = /(?:#{TYPO_ATTRIBUTE}(?:\s+#{TYPO_ATTRIBUTE})*)/.freeze
|
43
|
+
TAG =
|
44
|
+
%r{<[!/?\[]?(?:#{TYPO_TAG_KEY}|--)(?:\s+#{TYPO_ATTRIBUTES})?\s*(?:[!/?\]]+|--)?>}
|
45
|
+
.freeze
|
46
|
+
def strip_html
|
47
|
+
gsub(TAG, "").gsub(/\s+/, " ").strip
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
String.include PublifyCore::StringExt
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "text_filter_plugin"
|
4
|
+
require "commonmarker"
|
5
|
+
|
6
|
+
module PublifyCore::TextFilter
|
7
|
+
class Markdown < TextFilterPlugin::Markup
|
8
|
+
plugin_display_name "Markdown"
|
9
|
+
plugin_description "Markdown markup language from" \
|
10
|
+
' <a href="http://daringfireball.com/">Daring Fireball</a>'
|
11
|
+
|
12
|
+
def self.help_text
|
13
|
+
<<~TXT
|
14
|
+
[Markdown](http://daringfireball.net/projects/markdown/) is a simple
|
15
|
+
text-to-HTML converter that turns common text idioms into HTML. The
|
16
|
+
[full syntax](http://daringfireball.net/projects/markdown/syntax) is
|
17
|
+
available from the author's site, but here's a short summary:
|
18
|
+
|
19
|
+
* **Paragraphs**: Start a new paragraph by skipping a line.
|
20
|
+
* **Italics**: Put text in *italics* by enclosing it in either * or
|
21
|
+
_: `*italics*` turns into *italics*.
|
22
|
+
* **Bold**: Put text in **bold** by enclosing it in two *s:
|
23
|
+
`**bold**` turns into **bold**.
|
24
|
+
* **Pre-formatted text**: Enclosing a short block of text in
|
25
|
+
backquotes (`) displays it in a monospaced font and converts HTML
|
26
|
+
metacharacters so they display correctly. Example:
|
27
|
+
``<img src="foo"/>`` displays as `<img src="foo"/>`. Also,
|
28
|
+
any paragraph indented 4 or more spaces is treated as pre-formatted
|
29
|
+
text.
|
30
|
+
* **Block quotes**: Any paragraph (or line) that starts with a `>` is
|
31
|
+
treated as a blockquote.
|
32
|
+
* **Hyperlinks**: You can create links like this:
|
33
|
+
`[amazon's web site](http://www.amazon.com)`. That produces
|
34
|
+
"[amazon's web site](http://www.amazon.com)".
|
35
|
+
* **Lists**: You can create numbered or bulleted lists by ending a
|
36
|
+
paragraph with a colon (:), skipping a line, and then using asterisks
|
37
|
+
(*, for bullets) or numbers (for numbered lists). See the
|
38
|
+
[Markdown syntax page](http://daringfireball.net/projects/markdown/syntax)
|
39
|
+
for examples.
|
40
|
+
* **Raw HTML**: Markdown will pass raw HTML through unchanged, so you
|
41
|
+
can use HTML's syntax whenever Markdown doesn't provide a reasonable
|
42
|
+
alternative.
|
43
|
+
TXT
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.filtertext(text)
|
47
|
+
# FIXME: Workaround for <publify:foo> not being interpreted as an HTML tag.
|
48
|
+
escaped_macros = text.gsub(%r{(</?publify):}, '\1X')
|
49
|
+
html = CommonMarker.render_html(escaped_macros, :UNSAFE)
|
50
|
+
html.gsub(%r{(</?publify)X}, '\1:').strip
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "text_filter_plugin"
|
4
|
-
require "
|
4
|
+
require "publify_core/text_filter/markdown"
|
5
5
|
|
6
|
-
module
|
7
|
-
class MarkdownSmartquotes <
|
6
|
+
module PublifyCore::TextFilter
|
7
|
+
class MarkdownSmartquotes < PublifyCore::TextFilter::Markdown
|
8
8
|
plugin_display_name "Markdown with smart quotes"
|
9
9
|
plugin_description "Markdown markup language from" \
|
10
10
|
' <a href="http://daringfireball.com/">Daring Fireball</a>' \
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "text_filter_plugin"
|
4
|
+
|
5
|
+
module PublifyCore::TextFilter
|
6
|
+
class None < TextFilterPlugin::Markup
|
7
|
+
plugin_display_name "None"
|
8
|
+
plugin_description "Raw HTML only"
|
9
|
+
|
10
|
+
def self.filtertext(text)
|
11
|
+
text
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubypants"
|
4
|
+
|
5
|
+
module PublifyCore::TextFilter
|
6
|
+
class Smartypants < TextFilterPlugin::PostProcess
|
7
|
+
plugin_display_name "Smartypants"
|
8
|
+
plugin_description "Converts HTML to use typographically correct quotes and dashes"
|
9
|
+
|
10
|
+
def self.filtertext(text)
|
11
|
+
RubyPants.new(text).to_html
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "text_filter_plugin"
|
4
|
+
require "html/pipeline"
|
5
|
+
require "html/pipeline/hashtag/hashtag_filter"
|
6
|
+
|
7
|
+
module PublifyCore::TextFilter
|
8
|
+
class Twitterfilter < TextFilterPlugin::PostProcess
|
9
|
+
plugin_display_name "Twitter Filter"
|
10
|
+
plugin_description "Convert hashtags and mentions to links"
|
11
|
+
|
12
|
+
class TwitterHashtagFilter < HTML::Pipeline::HashtagFilter
|
13
|
+
def initialize(text)
|
14
|
+
super(text,
|
15
|
+
tag_url: "https://twitter.com/search?q=%%23%<tag>s&src=tren&mode=realtime",
|
16
|
+
tag_link_attr: "")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TwitterMentionFilter < HTML::Pipeline::MentionFilter
|
21
|
+
def initialize(text)
|
22
|
+
super(text, base_url: "https://twitter.com")
|
23
|
+
end
|
24
|
+
|
25
|
+
# Override base mentions finder, treating @mention just like any other @foo.
|
26
|
+
def self.mentioned_logins_in(text, username_pattern = UsernamePattern)
|
27
|
+
text.gsub MentionPatterns[username_pattern] do |match|
|
28
|
+
login = Regexp.last_match(1)
|
29
|
+
yield match, login, false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Override base link creator, removing the class
|
34
|
+
def link_to_mentioned_user(login)
|
35
|
+
result[:mentioned_usernames] |= [login]
|
36
|
+
|
37
|
+
url = base_url.dup
|
38
|
+
url << "/" unless %r{[/~]\z}.match?(url)
|
39
|
+
|
40
|
+
"<a href='#{url << login}'>" \
|
41
|
+
"@#{login}" \
|
42
|
+
"</a>"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.filtertext(text)
|
47
|
+
# First, autolink
|
48
|
+
helper = PublifyCore::ContentTextHelpers.new
|
49
|
+
text = helper.auto_link(text)
|
50
|
+
|
51
|
+
text = TwitterHashtagFilter.new(text).call
|
52
|
+
TwitterMentionFilter.new(text).call.to_s
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/publify_core/version.rb
CHANGED
data/lib/publify_core.rb
CHANGED
@@ -8,6 +8,12 @@ require "publify_core/version"
|
|
8
8
|
require "publify_core/engine"
|
9
9
|
require "publify_core/lang"
|
10
10
|
require "publify_core/content_text_helpers"
|
11
|
+
require "publify_core/text_filter/none"
|
12
|
+
require "publify_core/text_filter/markdown"
|
13
|
+
require "publify_core/text_filter/markdown_smartquotes"
|
14
|
+
require "publify_core/text_filter/smartypants"
|
15
|
+
require "publify_core/text_filter/twitterfilter"
|
16
|
+
require "publify_core/string_ext"
|
11
17
|
|
12
18
|
require "carrierwave"
|
13
19
|
require "jquery-rails"
|
@@ -20,17 +26,11 @@ require "sassc-rails"
|
|
20
26
|
|
21
27
|
require "email_notify"
|
22
28
|
require "publify_guid"
|
23
|
-
require "publify_textfilter_none"
|
24
|
-
require "publify_textfilter_markdown"
|
25
|
-
require "publify_textfilter_markdown_smartquotes"
|
26
|
-
require "publify_textfilter_smartypants"
|
27
|
-
require "publify_textfilter_twitterfilter"
|
28
29
|
require "publify_time"
|
29
30
|
require "sidebar_registry"
|
30
31
|
require "spam_protection"
|
31
32
|
require "text_filter_plugin"
|
32
33
|
require "theme"
|
33
|
-
require "transforms"
|
34
34
|
|
35
35
|
module PublifyCore
|
36
36
|
Theme.register_themes File.join(Engine.root, "themes")
|
data/lib/text_filter_plugin.rb
CHANGED
@@ -13,10 +13,8 @@ class TextFilterPlugin
|
|
13
13
|
def self.inherited(sub)
|
14
14
|
super
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
@@filter_map[name] = sub
|
19
|
-
end
|
16
|
+
name = sub.short_name
|
17
|
+
@@filter_map[name] = sub
|
20
18
|
end
|
21
19
|
|
22
20
|
def self.filter_map
|
@@ -116,34 +114,40 @@ class TextFilterPlugin
|
|
116
114
|
def self.logger
|
117
115
|
@logger ||= ::Rails.logger || Logger.new($stdout)
|
118
116
|
end
|
117
|
+
|
118
|
+
def self.abstract_filter!
|
119
|
+
@@filter_map.delete short_name
|
120
|
+
end
|
119
121
|
end
|
120
122
|
|
121
123
|
class TextFilterPlugin::PostProcess < TextFilterPlugin
|
124
|
+
abstract_filter!
|
125
|
+
|
122
126
|
def self.filter_type
|
123
127
|
"postprocess"
|
124
128
|
end
|
125
129
|
end
|
126
130
|
|
127
|
-
|
131
|
+
module TextFilterPlugin::MacroMethods
|
128
132
|
# Utility function -- hand it a XML string like <a href="foo" title="bar">
|
129
133
|
# and it'll give you back { "href" => "foo", "title" => "bar" }
|
130
|
-
def
|
134
|
+
def attributes_parse(string)
|
131
135
|
attributes = {}
|
132
136
|
|
133
137
|
string.gsub(/([^ =]+="[^"]*")/) do |match|
|
134
|
-
key, value = match.split(
|
138
|
+
key, value = match.split("=", 2)
|
135
139
|
attributes[key] = value.delete('"')
|
136
140
|
end
|
137
141
|
|
138
142
|
string.gsub(/([^ =]+='[^']*')/) do |match|
|
139
|
-
key, value = match.split(
|
143
|
+
key, value = match.split("=", 2)
|
140
144
|
attributes[key] = value.delete("'")
|
141
145
|
end
|
142
146
|
|
143
147
|
attributes
|
144
148
|
end
|
145
149
|
|
146
|
-
def
|
150
|
+
def filtertext(text)
|
147
151
|
regex1 = %r{<publify:#{short_name}(?:[ \t][^>]*)?/>}
|
148
152
|
regex2 = %r{<publify:#{short_name}([ \t][^>]*)?>(.*?)</publify:#{short_name}>}m
|
149
153
|
|
@@ -157,19 +161,27 @@ class TextFilterPlugin::Macro < TextFilterPlugin
|
|
157
161
|
end
|
158
162
|
end
|
159
163
|
|
160
|
-
class TextFilterPlugin::MacroPre < TextFilterPlugin
|
164
|
+
class TextFilterPlugin::MacroPre < TextFilterPlugin
|
165
|
+
abstract_filter!
|
166
|
+
extend TextFilterPlugin::MacroMethods
|
167
|
+
|
161
168
|
def self.filter_type
|
162
169
|
"macropre"
|
163
170
|
end
|
164
171
|
end
|
165
172
|
|
166
|
-
class TextFilterPlugin::MacroPost < TextFilterPlugin
|
173
|
+
class TextFilterPlugin::MacroPost < TextFilterPlugin
|
174
|
+
abstract_filter!
|
175
|
+
extend TextFilterPlugin::MacroMethods
|
176
|
+
|
167
177
|
def self.filter_type
|
168
178
|
"macropost"
|
169
179
|
end
|
170
180
|
end
|
171
181
|
|
172
182
|
class TextFilterPlugin::Markup < TextFilterPlugin
|
183
|
+
abstract_filter!
|
184
|
+
|
173
185
|
def self.filter_type
|
174
186
|
"markup"
|
175
187
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: publify_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.0.
|
4
|
+
version: 10.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matijs van Zuijlen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-10-28 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: aasm
|
@@ -61,14 +61,14 @@ dependencies:
|
|
61
61
|
requirements:
|
62
62
|
- - "~>"
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version:
|
64
|
+
version: '3.0'
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
69
|
- - "~>"
|
70
70
|
- !ruby/object:Gem::Version
|
71
|
-
version:
|
71
|
+
version: '3.0'
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: commonmarker
|
74
74
|
requirement: !ruby/object:Gem::Requirement
|
@@ -191,16 +191,22 @@ dependencies:
|
|
191
191
|
name: jquery-rails
|
192
192
|
requirement: !ruby/object:Gem::Requirement
|
193
193
|
requirements:
|
194
|
-
- - "
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '4.5'
|
197
|
+
- - "<"
|
195
198
|
- !ruby/object:Gem::Version
|
196
|
-
version: 4.
|
199
|
+
version: '4.7'
|
197
200
|
type: :runtime
|
198
201
|
prerelease: false
|
199
202
|
version_requirements: !ruby/object:Gem::Requirement
|
200
203
|
requirements:
|
201
|
-
- - "
|
204
|
+
- - ">="
|
202
205
|
- !ruby/object:Gem::Version
|
203
|
-
version: 4.5
|
206
|
+
version: '4.5'
|
207
|
+
- - "<"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '4.7'
|
204
210
|
- !ruby/object:Gem::Dependency
|
205
211
|
name: jquery-ui-rails
|
206
212
|
requirement: !ruby/object:Gem::Requirement
|
@@ -539,70 +545,84 @@ dependencies:
|
|
539
545
|
requirements:
|
540
546
|
- - "~>"
|
541
547
|
- !ruby/object:Gem::Version
|
542
|
-
version: 1.
|
548
|
+
version: 1.57.1
|
549
|
+
type: :development
|
550
|
+
prerelease: false
|
551
|
+
version_requirements: !ruby/object:Gem::Requirement
|
552
|
+
requirements:
|
553
|
+
- - "~>"
|
554
|
+
- !ruby/object:Gem::Version
|
555
|
+
version: 1.57.1
|
556
|
+
- !ruby/object:Gem::Dependency
|
557
|
+
name: rubocop-capybara
|
558
|
+
requirement: !ruby/object:Gem::Requirement
|
559
|
+
requirements:
|
560
|
+
- - "~>"
|
561
|
+
- !ruby/object:Gem::Version
|
562
|
+
version: 2.19.0
|
543
563
|
type: :development
|
544
564
|
prerelease: false
|
545
565
|
version_requirements: !ruby/object:Gem::Requirement
|
546
566
|
requirements:
|
547
567
|
- - "~>"
|
548
568
|
- !ruby/object:Gem::Version
|
549
|
-
version:
|
569
|
+
version: 2.19.0
|
550
570
|
- !ruby/object:Gem::Dependency
|
551
571
|
name: rubocop-factory_bot
|
552
572
|
requirement: !ruby/object:Gem::Requirement
|
553
573
|
requirements:
|
554
574
|
- - "~>"
|
555
575
|
- !ruby/object:Gem::Version
|
556
|
-
version: 2.
|
576
|
+
version: 2.24.0
|
557
577
|
type: :development
|
558
578
|
prerelease: false
|
559
579
|
version_requirements: !ruby/object:Gem::Requirement
|
560
580
|
requirements:
|
561
581
|
- - "~>"
|
562
582
|
- !ruby/object:Gem::Version
|
563
|
-
version: 2.
|
583
|
+
version: 2.24.0
|
564
584
|
- !ruby/object:Gem::Dependency
|
565
585
|
name: rubocop-performance
|
566
586
|
requirement: !ruby/object:Gem::Requirement
|
567
587
|
requirements:
|
568
588
|
- - "~>"
|
569
589
|
- !ruby/object:Gem::Version
|
570
|
-
version: 1.
|
590
|
+
version: 1.19.0
|
571
591
|
type: :development
|
572
592
|
prerelease: false
|
573
593
|
version_requirements: !ruby/object:Gem::Requirement
|
574
594
|
requirements:
|
575
595
|
- - "~>"
|
576
596
|
- !ruby/object:Gem::Version
|
577
|
-
version: 1.
|
597
|
+
version: 1.19.0
|
578
598
|
- !ruby/object:Gem::Dependency
|
579
599
|
name: rubocop-rails
|
580
600
|
requirement: !ruby/object:Gem::Requirement
|
581
601
|
requirements:
|
582
602
|
- - "~>"
|
583
603
|
- !ruby/object:Gem::Version
|
584
|
-
version: 2.
|
604
|
+
version: 2.21.1
|
585
605
|
type: :development
|
586
606
|
prerelease: false
|
587
607
|
version_requirements: !ruby/object:Gem::Requirement
|
588
608
|
requirements:
|
589
609
|
- - "~>"
|
590
610
|
- !ruby/object:Gem::Version
|
591
|
-
version: 2.
|
611
|
+
version: 2.21.1
|
592
612
|
- !ruby/object:Gem::Dependency
|
593
613
|
name: rubocop-rspec
|
594
614
|
requirement: !ruby/object:Gem::Requirement
|
595
615
|
requirements:
|
596
616
|
- - "~>"
|
597
617
|
- !ruby/object:Gem::Version
|
598
|
-
version: 2.
|
618
|
+
version: 2.24.1
|
599
619
|
type: :development
|
600
620
|
prerelease: false
|
601
621
|
version_requirements: !ruby/object:Gem::Requirement
|
602
622
|
requirements:
|
603
623
|
- - "~>"
|
604
624
|
- !ruby/object:Gem::Version
|
605
|
-
version: 2.
|
625
|
+
version: 2.24.1
|
606
626
|
- !ruby/object:Gem::Dependency
|
607
627
|
name: shoulda-matchers
|
608
628
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1103,6 +1123,7 @@ files:
|
|
1103
1123
|
- lib/publify_core/content_text_helpers.rb
|
1104
1124
|
- lib/publify_core/engine.rb
|
1105
1125
|
- lib/publify_core/lang.rb
|
1126
|
+
- lib/publify_core/string_ext.rb
|
1106
1127
|
- lib/publify_core/testing_support/dns_mock.rb
|
1107
1128
|
- lib/publify_core/testing_support/factories/articles.rb
|
1108
1129
|
- lib/publify_core/testing_support/factories/blogs.rb
|
@@ -1127,14 +1148,14 @@ files:
|
|
1127
1148
|
- lib/publify_core/testing_support/fixtures/testfile.png
|
1128
1149
|
- lib/publify_core/testing_support/fixtures/testfile.txt
|
1129
1150
|
- lib/publify_core/testing_support/upload_fixtures.rb
|
1151
|
+
- lib/publify_core/text_filter/markdown.rb
|
1152
|
+
- lib/publify_core/text_filter/markdown_smartquotes.rb
|
1153
|
+
- lib/publify_core/text_filter/none.rb
|
1154
|
+
- lib/publify_core/text_filter/smartypants.rb
|
1155
|
+
- lib/publify_core/text_filter/twitterfilter.rb
|
1130
1156
|
- lib/publify_core/version.rb
|
1131
1157
|
- lib/publify_guid.rb
|
1132
1158
|
- lib/publify_plugins.rb
|
1133
|
-
- lib/publify_textfilter_markdown.rb
|
1134
|
-
- lib/publify_textfilter_markdown_smartquotes.rb
|
1135
|
-
- lib/publify_textfilter_none.rb
|
1136
|
-
- lib/publify_textfilter_smartypants.rb
|
1137
|
-
- lib/publify_textfilter_twitterfilter.rb
|
1138
1159
|
- lib/publify_time.rb
|
1139
1160
|
- lib/sidebar_field.rb
|
1140
1161
|
- lib/sidebar_registry.rb
|
@@ -1143,7 +1164,6 @@ files:
|
|
1143
1164
|
- lib/tasks/publify_core_tasks.rake
|
1144
1165
|
- lib/text_filter_plugin.rb
|
1145
1166
|
- lib/theme.rb
|
1146
|
-
- lib/transforms.rb
|
1147
1167
|
- themes/plain/about.markdown
|
1148
1168
|
- themes/plain/javascripts/theme.js
|
1149
1169
|
- themes/plain/preview.png
|
@@ -1168,7 +1188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1168
1188
|
- !ruby/object:Gem::Version
|
1169
1189
|
version: '0'
|
1170
1190
|
requirements: []
|
1171
|
-
rubygems_version: 3.4.
|
1191
|
+
rubygems_version: 3.4.20
|
1172
1192
|
signing_key:
|
1173
1193
|
specification_version: 4
|
1174
1194
|
summary: Core engine for the Publify blogging system.
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "text_filter_plugin"
|
4
|
-
require "commonmarker"
|
5
|
-
|
6
|
-
# TODO: Move to a different namespace
|
7
|
-
class PublifyApp
|
8
|
-
class Textfilter
|
9
|
-
class Markdown < TextFilterPlugin::Markup
|
10
|
-
plugin_display_name "Markdown"
|
11
|
-
plugin_description "Markdown markup language from" \
|
12
|
-
' <a href="http://daringfireball.com/">Daring Fireball</a>'
|
13
|
-
|
14
|
-
def self.help_text
|
15
|
-
<<~TXT
|
16
|
-
[Markdown](http://daringfireball.net/projects/markdown/) is a simple
|
17
|
-
text-to-HTML converter that turns common text idioms into HTML. The
|
18
|
-
[full syntax](http://daringfireball.net/projects/markdown/syntax) is
|
19
|
-
available from the author's site, but here's a short summary:
|
20
|
-
|
21
|
-
* **Paragraphs**: Start a new paragraph by skipping a line.
|
22
|
-
* **Italics**: Put text in *italics* by enclosing it in either * or
|
23
|
-
_: `*italics*` turns into *italics*.
|
24
|
-
* **Bold**: Put text in **bold** by enclosing it in two *s:
|
25
|
-
`**bold**` turns into **bold**.
|
26
|
-
* **Pre-formatted text**: Enclosing a short block of text in
|
27
|
-
backquotes (`) displays it in a monospaced font and converts HTML
|
28
|
-
metacharacters so they display correctly. Example:
|
29
|
-
``<img src="foo"/>`` displays as `<img src="foo"/>`. Also,
|
30
|
-
any paragraph indented 4 or more spaces is treated as pre-formatted
|
31
|
-
text.
|
32
|
-
* **Block quotes**: Any paragraph (or line) that starts with a `>` is
|
33
|
-
treated as a blockquote.
|
34
|
-
* **Hyperlinks**: You can create links like this:
|
35
|
-
`[amazon's web site](http://www.amazon.com)`. That produces
|
36
|
-
"[amazon's web site](http://www.amazon.com)".
|
37
|
-
* **Lists**: You can create numbered or bulleted lists by ending a
|
38
|
-
paragraph with a colon (:), skipping a line, and then using asterisks
|
39
|
-
(*, for bullets) or numbers (for numbered lists). See the
|
40
|
-
[Markdown syntax page](http://daringfireball.net/projects/markdown/syntax)
|
41
|
-
for examples.
|
42
|
-
* **Raw HTML**: Markdown will pass raw HTML through unchanged, so you
|
43
|
-
can use HTML's syntax whenever Markdown doesn't provide a reasonable
|
44
|
-
alternative.
|
45
|
-
TXT
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.filtertext(text)
|
49
|
-
# FIXME: Workaround for <publify:foo> not being interpreted as an HTML tag.
|
50
|
-
escaped_macros = text.gsub(%r{(</?publify):}, '\1X')
|
51
|
-
html = CommonMarker.render_html(escaped_macros, :UNSAFE)
|
52
|
-
html.gsub(%r{(</?publify)X}, '\1:').strip
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "text_filter_plugin"
|
4
|
-
|
5
|
-
class PublifyApp
|
6
|
-
class Textfilter
|
7
|
-
class None < TextFilterPlugin::Markup
|
8
|
-
plugin_display_name "None"
|
9
|
-
plugin_description "Raw HTML only"
|
10
|
-
|
11
|
-
def self.filtertext(text)
|
12
|
-
text
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rubypants"
|
4
|
-
|
5
|
-
class PublifyApp
|
6
|
-
class Textfilter
|
7
|
-
class Smartypants < TextFilterPlugin::PostProcess
|
8
|
-
plugin_display_name "Smartypants"
|
9
|
-
plugin_description "Converts HTML to use typographically correct quotes and dashes"
|
10
|
-
|
11
|
-
def self.filtertext(text)
|
12
|
-
RubyPants.new(text).to_html
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "text_filter_plugin"
|
4
|
-
require "html/pipeline"
|
5
|
-
require "html/pipeline/hashtag/hashtag_filter"
|
6
|
-
|
7
|
-
class PublifyApp
|
8
|
-
class Textfilter
|
9
|
-
class Twitterfilter < TextFilterPlugin::PostProcess
|
10
|
-
plugin_display_name "HTML Filter"
|
11
|
-
plugin_description "Strip HTML tags"
|
12
|
-
|
13
|
-
class TwitterHashtagFilter < HTML::Pipeline::HashtagFilter
|
14
|
-
def initialize(text)
|
15
|
-
super(text,
|
16
|
-
tag_url: "https://twitter.com/search?q=%%23%<tag>s&src=tren&mode=realtime",
|
17
|
-
tag_link_attr: "")
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class TwitterMentionFilter < HTML::Pipeline::MentionFilter
|
22
|
-
def initialize(text)
|
23
|
-
super(text, base_url: "https://twitter.com")
|
24
|
-
end
|
25
|
-
|
26
|
-
# Override base mentions finder, treating @mention just like any other @foo.
|
27
|
-
def self.mentioned_logins_in(text, username_pattern = UsernamePattern)
|
28
|
-
text.gsub MentionPatterns[username_pattern] do |match|
|
29
|
-
login = Regexp.last_match(1)
|
30
|
-
yield match, login, false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Override base link creator, removing the class
|
35
|
-
def link_to_mentioned_user(login)
|
36
|
-
result[:mentioned_usernames] |= [login]
|
37
|
-
|
38
|
-
url = base_url.dup
|
39
|
-
url << "/" unless %r{[/~]\z}.match?(url)
|
40
|
-
|
41
|
-
"<a href='#{url << login}'>" \
|
42
|
-
"@#{login}" \
|
43
|
-
"</a>"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.filtertext(text)
|
48
|
-
# First, autolink
|
49
|
-
helper = PublifyCore::ContentTextHelpers.new
|
50
|
-
text = helper.auto_link(text)
|
51
|
-
|
52
|
-
text = TwitterHashtagFilter.new(text).call
|
53
|
-
TwitterMentionFilter.new(text).call.to_s
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/transforms.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# FIXME: Replace with helpers and/or methods provided by Rails
|
4
|
-
class String
|
5
|
-
ACCENTS = { %w(á à â ä ã Ã Ä Â À) => "a",
|
6
|
-
%w(é è ê ë Ë É È Ê) => "e",
|
7
|
-
%w(í ì î ï I Î Ì) => "i",
|
8
|
-
%w(ó ò ô ö õ Õ Ö Ô Ò) => "o",
|
9
|
-
["œ"] => "oe",
|
10
|
-
["ß"] => "ss",
|
11
|
-
%w(ú ù û ü U Û Ù) => "u",
|
12
|
-
%w(ç Ç) => "c" }.freeze
|
13
|
-
|
14
|
-
def to_permalink
|
15
|
-
string = self
|
16
|
-
ACCENTS.each do |key, value|
|
17
|
-
string = string.tr(key.join, value)
|
18
|
-
end
|
19
|
-
string = string.tr("'", "-")
|
20
|
-
string.gsub(/<[^>]*>/, "").to_url
|
21
|
-
end
|
22
|
-
|
23
|
-
# Returns a-string-with-dashes when passed 'a string with dashes'.
|
24
|
-
# All special chars are stripped in the process
|
25
|
-
def to_url
|
26
|
-
return if nil?
|
27
|
-
|
28
|
-
s = downcase.tr("\"'", "")
|
29
|
-
s = s.gsub(/\P{Word}/, " ")
|
30
|
-
s.strip.tr_s(" ", "-").tr(" ", "-").sub(/^$/, "-")
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_title(item, settings, params)
|
34
|
-
TitleBuilder.new(self).build(item, settings, params)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Strips any html markup from a string
|
38
|
-
TYPO_TAG_KEY = TYPO_ATTRIBUTE_KEY = /[\w:_-]+/.freeze
|
39
|
-
TYPO_ATTRIBUTE_VALUE = /(?:[A-Za-z0-9]+|(?:'[^']*?'|"[^"]*?"))/.freeze
|
40
|
-
TYPO_ATTRIBUTE = /(?:#{TYPO_ATTRIBUTE_KEY}(?:\s*=\s*#{TYPO_ATTRIBUTE_VALUE})?)/.freeze
|
41
|
-
TYPO_ATTRIBUTES = /(?:#{TYPO_ATTRIBUTE}(?:\s+#{TYPO_ATTRIBUTE})*)/.freeze
|
42
|
-
TAG =
|
43
|
-
%r{<[!/?\[]?(?:#{TYPO_TAG_KEY}|--)(?:\s+#{TYPO_ATTRIBUTES})?\s*(?:[!/?\]]+|--)?>}.freeze
|
44
|
-
def strip_html
|
45
|
-
gsub(TAG, "").gsub(/\s+/, " ").strip
|
46
|
-
end
|
47
|
-
end
|