Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it easier to create text filter plugins #110

Merged
merged 3 commits into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/publify_core/text_filter/markdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
require "commonmarker"

module PublifyCore::TextFilter
class Markdown < TextFilterPlugin::Markup
class Markdown < TextFilterPlugin
include TextFilterPlugin::Markup

plugin_display_name "Markdown"
plugin_description "Markdown markup language from" \
' <a href="http://daringfireball.com/">Daring Fireball</a>'
Expand Down
4 changes: 3 additions & 1 deletion lib/publify_core/text_filter/none.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
require "text_filter_plugin"

module PublifyCore::TextFilter
class None < TextFilterPlugin::Markup
class None < TextFilterPlugin
include TextFilterPlugin::Markup

plugin_display_name "None"
plugin_description "Raw HTML only"

Expand Down
4 changes: 3 additions & 1 deletion lib/publify_core/text_filter/smartypants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
require "rubypants"

module PublifyCore::TextFilter
class Smartypants < TextFilterPlugin::PostProcess
class Smartypants < TextFilterPlugin
include TextFilterPlugin::PostProcess

plugin_display_name "Smartypants"
plugin_description "Converts HTML to use typographically correct quotes and dashes"

Expand Down
4 changes: 3 additions & 1 deletion lib/publify_core/text_filter/twitterfilter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
require "html/pipeline/hashtag/hashtag_filter"

module PublifyCore::TextFilter
class Twitterfilter < TextFilterPlugin::PostProcess
class Twitterfilter < TextFilterPlugin
include TextFilterPlugin::PostProcess

plugin_display_name "HTML Filter"
plugin_description "Strip HTML tags"

Expand Down
52 changes: 35 additions & 17 deletions lib/text_filter_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ class << self
def self.inherited(sub)
super

if sub.to_s.start_with?("Plugin", "PublifyCore::TextFilter")
name = sub.short_name
@@filter_map[name] = sub
end
name = sub.short_name
@@filter_map[name] = sub
end

def self.filter_map
Expand Down Expand Up @@ -118,16 +116,16 @@ def self.logger
end
end

class TextFilterPlugin::PostProcess < TextFilterPlugin
module TextFilterPlugin::PostProcess
def self.filter_type
"postprocess"
end
end

class TextFilterPlugin::Macro < TextFilterPlugin
module TextFilterPlugin::MacroMethods
# Utility function -- hand it a XML string like <a href="foo" title="bar">
# and it'll give you back { "href" => "foo", "title" => "bar" }
def self.attributes_parse(string)
def attributes_parse(string)
attributes = {}

string.gsub(/([^ =]+="[^"]*")/) do |match|
Expand All @@ -143,7 +141,7 @@ def self.attributes_parse(string)
attributes
end

def self.filtertext(text)
def filtertext(text)
regex1 = %r{<publify:#{short_name}(?:[ \t][^>]*)?/>}
regex2 = %r{<publify:#{short_name}([ \t][^>]*)?>(.*?)</publify:#{short_name}>}m

Expand All @@ -157,20 +155,40 @@ def self.filtertext(text)
end
end

class TextFilterPlugin::MacroPre < TextFilterPlugin::Macro
def self.filter_type
"macropre"
module TextFilterPlugin::MacroPre
def self.included(base)
base.extend ClassMethods
base.extend TextFilterPlugin::MacroMethods
end

module ClassMethods
def filter_type
"macropre"
end
end
end

class TextFilterPlugin::MacroPost < TextFilterPlugin::Macro
def self.filter_type
"macropost"
module TextFilterPlugin::MacroPost
def self.included(base)
base.extend ClassMethods
base.extend TextFilterPlugin::MacroMethods
end

module ClassMethods
def filter_type
"macropost"
end
end
end

class TextFilterPlugin::Markup < TextFilterPlugin
def self.filter_type
"markup"
module TextFilterPlugin::Markup
def self.included(base)
base.extend ClassMethods
end

module ClassMethods
def filter_type
"markup"
end
end
end
71 changes: 49 additions & 22 deletions spec/lib/text_filter_plugin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,67 @@

RSpec.describe TextFilterPlugin do
describe ".available_filters" do
subject { described_class.available_filters }

it { is_expected.to include(PublifyCore::TextFilter::Markdown) }
it { is_expected.to include(PublifyCore::TextFilter::Smartypants) }
it { is_expected.to include(PublifyCore::TextFilter::Twitterfilter) }
it { is_expected.not_to include(TextFilterPlugin::Markup) }
it { is_expected.not_to include(TextFilterPlugin::Macro) }
it { is_expected.not_to include(TextFilterPlugin::MacroPre) }
it { is_expected.not_to include(TextFilterPlugin::MacroPost) }
it "lists only directly usable filters" do
expect(described_class.available_filters).to contain_exactly(
PublifyCore::TextFilter::None,
PublifyCore::TextFilter::Markdown,
PublifyCore::TextFilter::Smartypants,
PublifyCore::TextFilter::MarkdownSmartquotes,
PublifyCore::TextFilter::Twitterfilter)
end
end

describe ".macro_filters" do
subject { described_class.macro_filters }

it { is_expected.not_to include(PublifyCore::TextFilter::Markdown) }
it { is_expected.not_to include(PublifyCore::TextFilter::Smartypants) }
it { is_expected.not_to include(PublifyCore::TextFilter::Twitterfilter) }
it { is_expected.not_to include(TextFilterPlugin::Markup) }
it { is_expected.not_to include(TextFilterPlugin::Macro) }
it { is_expected.not_to include(TextFilterPlugin::MacroPre) }
it { is_expected.not_to include(TextFilterPlugin::MacroPost) }
it "lists no filters" do
expect(described_class.macro_filters).to be_empty
end
end

describe described_class::Macro do
describe "#self.attributes_parse" do
shared_examples "a macro module" do
describe ".attributes_parse" do
it 'parses lang="ruby" to {"lang" => "ruby"}' do
expect(described_class.attributes_parse('<publify:code lang="ruby">'))
expect(derived_class.attributes_parse('<publify:code lang="ruby">'))
.to eq("lang" => "ruby")
end

it "parses lang='ruby' to {'lang' => 'ruby'}" do
expect(described_class.attributes_parse("<publify:code lang='ruby'>"))
expect(derived_class.attributes_parse("<publify:code lang='ruby'>"))
.to eq("lang" => "ruby")
end
end
end

describe described_class::MacroPre, "when included" do
let(:derived_class) do
Class.new.tap { |klass| klass.include described_class }
end

it_behaves_like "a macro module"

it "declares including classes to be macropre filters" do
expect(derived_class.filter_type).to eq "macropre"
end
end

describe described_class::MacroPost, "when included" do
let(:derived_class) do
Class.new.tap { |klass| klass.include described_class }
end

it_behaves_like "a macro module"

it "declares including classes to be macropost filters" do
expect(derived_class.filter_type).to eq "macropost"
end
end

describe described_class::Markup, "when included" do
let(:derived_class) do
Class.new.tap { |klass| klass.include described_class }
end

it "declares including classes to be markup filters" do
expect(derived_class.filter_type).to eq "markup"
end
end
end