Skip to content

Commit

Permalink
Merge pull request #110 from publify/improve-text-filter-plugin-system
Browse files Browse the repository at this point in the history
Make it easier to create text filter plugins
  • Loading branch information
mvz authored Sep 30, 2023
2 parents 75d1448 + b5a3e00 commit b55d79d
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 43 deletions.
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

0 comments on commit b55d79d

Please sign in to comment.