feminizer 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in feminizer.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,9 @@
1
+ # Feminizer
2
+
3
+ Turns men into women and women into men. Great for a mind-fuck or to prove an example of implicity patriarchy.
4
+ In use at [The Art Of Womanliness](http://artofwomanliness.heroku.com/).
5
+
6
+
7
+ Patches welcome, forks celebrated.
8
+
9
+ Copyright (c) 2011 [Jack Danger Canty](http://jåck.com). Released under the MIT License.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => :test
5
+
6
+ require 'rake/testtask'
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << '.'
9
+ test.ruby_opts << '-rubygems'
10
+ test.pattern = 'test/*.rb'
11
+ test.verbose = true
12
+ end
data/feminizer.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "feminizer"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "feminizer"
7
+ s.version = Feminizer::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jack Danger Canty"]
10
+ s.email = ["rubygems@6brand.com"]
11
+ s.homepage = "http://github.com/JackDanger/feminizer"
12
+ s.summary = %q{Programmatically swap the gender of an English text string}
13
+ s.description = %q{This library can take a piece of English text as a string and swap masculine words for feminine and vice-versa.}
14
+
15
+ s.rubyforge_project = "feminizer"
16
+
17
+ s.add_dependency 'nokogiri'
18
+ s.add_dependency 'activesupport'
19
+ s.add_dependency 'without_accents'
20
+ s.add_development_dependency 'shoulda'
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
data/lib/feminizer.rb ADDED
@@ -0,0 +1,144 @@
1
+ require 'without_accents'
2
+ require 'nokogiri'
3
+
4
+ module Feminizer
5
+
6
+ VERSION = "1.0.1"
7
+
8
+
9
+ extend self
10
+
11
+ def feminize_html content
12
+ tree = Nokogiri::HTML content
13
+ feminize_node! tree
14
+ tree.to_html
15
+ end
16
+
17
+ def feminize_text string
18
+ return string if ['', '\n', "\n"].include?(string.to_s)
19
+
20
+ string = string.dup.without_accents
21
+ string = string.gsub(/\302\240/, ' ')
22
+
23
+
24
+ forms = {
25
+ 'man' => 'woman',
26
+ 'men' => 'women',
27
+ 'manly' => 'womanly',
28
+ 'manliness' => 'womanliness',
29
+ 'manlier' => 'womanlier',
30
+ 'manliest' => 'womanliest',
31
+ 'manhood' => 'womanhood',
32
+ 'manvotional' => 'womanvotional',
33
+ 'masculine' => 'feminine',
34
+ 'masculinity' => 'femininity',
35
+ 'male' => 'female',
36
+ 'patriarch' => 'matriarch',
37
+ 'mr.' => 'ms.',
38
+ 'boy' => 'girl',
39
+ 'boys' => 'girls',
40
+ 'guy' => 'gal',
41
+ 'guys' => 'gals',
42
+ 'dude' => 'lady',
43
+ 'dudes' => 'ladies',
44
+ 'he' => 'she',
45
+ 'his' => 'her',
46
+ 'him' => 'her',
47
+ 'himself' => 'herself',
48
+ 'waitress' => 'waiter',
49
+ 'waitressed' => 'waited',
50
+ 'craftsman' => 'craftswoman',
51
+ 'nobleman' => 'noblewoman',
52
+ 'gentleman' => 'lady',
53
+ 'gentlemen' => 'ladies',
54
+ 'prince' => 'princess',
55
+ 'princes' => 'princesses',
56
+ 'king' => 'queen',
57
+ 'kings' => 'queens',
58
+ 'sissy' => 'boyish',
59
+ 'emasculate' => 'defeminize',
60
+ 'cowboy' => 'cowgirl',
61
+ 'cowboying' => 'cowgirling',
62
+ 'cowboys' => 'cowgirls',
63
+ 'dad' => 'mom',
64
+ 'daddy' => 'mommy',
65
+ 'dick' => 'pussy',
66
+ 'ex-wife' => 'ex-husband',
67
+ 'father' => 'mother',
68
+ 'fathers' => 'mothers',
69
+ 'brother' => 'sister',
70
+ 'brothers' => 'sisters',
71
+ 'Matt' => 'Mattie',
72
+ 'David' => 'Davida',
73
+ 'Paul' => 'Paula'
74
+ }
75
+
76
+ forms.each do |masculine, feminine|
77
+ if string =~ /#{feminine}/i
78
+ string = string_search_replace(string, feminine, masculine, :mark) unless 'his' == masculine
79
+ string = string_search_replace(string, masculine, feminine)
80
+ string = string_search_replace(string, feminine, masculine, :unmark) unless 'his' == masculine
81
+ elsif string =~ /#{masculine}/i
82
+ string = string_search_replace(string, masculine, feminine)
83
+ end
84
+ end
85
+
86
+ string
87
+ end
88
+
89
+ protected
90
+
91
+ def feminize_node! node, indent = 0
92
+ case node.name
93
+ when 'text'
94
+ # print " "*indent
95
+ # puts "feminizing: #{node.content.inspect}"
96
+ node.content = feminize_text(node.content)
97
+ # print " "*indent
98
+ # puts "out: #{node.content.inspect}"
99
+ when 'a'
100
+ # puts "rewriting: #{node.attributes['href'].value}"
101
+ if href = node.attributes['href']
102
+ href.value = href.value.sub(/https?:\/\/artofmanliness.com\/?/, '/')
103
+ end
104
+ else
105
+ # puts 'not processing: '+node.inspect
106
+ end
107
+
108
+ if node.children.size > 0
109
+ node.children.each do |child|
110
+ # print " "*indent
111
+ # puts "-> #{child.name}"
112
+ feminize_node! child, indent + 1
113
+ end
114
+ end
115
+ end
116
+
117
+
118
+ def ok
119
+ @ok ||= %Q{([\s"':;\.,\>\<\?\!-])}
120
+ end
121
+
122
+ def string_search_replace(string, from, to, mode = nil)
123
+ [
124
+ [ from, to],
125
+ [ from[0..0].upcase + from[1..-1],
126
+ to[0..0].upcase + to[1..-1] ]
127
+ ].each do |search, replace|
128
+ case mode
129
+ when :mark
130
+ replace = "[marked]#{search}[marked]"
131
+ when :unmark
132
+ search = /\[marked\]#{search}\[marked\]/
133
+ end
134
+
135
+ string.gsub! %r{#{ok}#{search}#{ok}}, '\1'+replace+'\2'
136
+ string.gsub! %r{^#{search}#{ok}}, replace+'\1'
137
+ string.gsub! %r{#{ok}#{search}$}, '\1'+replace
138
+ string.gsub! %r{^#{search}$}, replace
139
+
140
+ end
141
+ string
142
+ end
143
+
144
+ end
@@ -0,0 +1,151 @@
1
+ require 'test/unit'
2
+ require 'active_support'
3
+ require 'open-uri'
4
+ require File.expand_path File.join(File.dirname(__FILE__), '..', 'lib', 'feminizer')
5
+ require 'shoulda'
6
+
7
+ class FeminizerTest < Test::Unit::TestCase
8
+ def feminize_text *args
9
+ Feminizer.feminize_text *args
10
+ end
11
+ def feminize_html *args
12
+ Feminizer.feminize_html *args
13
+ end
14
+
15
+ context "feminize_text" do
16
+ setup {
17
+ @feminized = feminize_text "The Art of Manliness - by a Man’s man, as his hobby, for masculine men everywhere"
18
+ }
19
+ should "turn all girly" do
20
+ assert_equal "The Art of Womanliness - by a Woman's woman, as her hobby, for feminine women everywhere",
21
+ @feminized
22
+ end
23
+ end
24
+ context "feminize" do
25
+ setup {
26
+ @feminized = feminize_html HTML.dup
27
+ }
28
+ should "have remote url in original" do
29
+ assert_match %r{<li><a href="http://artofmanliness.com/man-knowledge">Man Knowledge</a></li>}, HTML
30
+ end
31
+ should "replace link content with feminized text and relative path" do
32
+ assert_match %r{<li><a href="/man-knowledge">Woman Knowledge</a></li>}, @feminized
33
+ end
34
+ should "replace link content when it's next to an image" do
35
+ assert_match %r{How to Apologize Like a Woman}, @feminized
36
+ end
37
+ should "swap genders in small string" do
38
+ assert_match %r{This string started with Man in it and should turn into Woman},
39
+ feminize_html("This string started with Woman in it and should turn into Man")
40
+ end
41
+ should "swap genders in full document" do
42
+ assert_match %r{This string started with Man in it and should turn into Woman}, @feminized
43
+ end
44
+ should "feminize even if a period is following the word" do
45
+ assert_match %r{would be the cowgirl.},
46
+ feminize_html(open("http://artofmanliness.com/2010/09/07/3-archetypes-of-american-manliness-part-ii-the-heroic-artisan/", {'User-Agent' => 'Firefox'}).read)
47
+ end
48
+ end
49
+
50
+
51
+ HTML = <<-EOHTML
52
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:og="http://opengraphprotocol.org/schema/" xmlns:fb="http://www.facebook.com/2008/fbml" dir="ltr" lang="en-US">
53
+ <head profile="http://gmpg.org/xfn/11">
54
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
55
+ <title>The Art of Manliness | Men&#039;s Interests and Lifestyle</title>
56
+ <meta name="robots" content="noodp, noydir" />
57
+ <meta name="description" content="The Art of Manliness is a men\&#8217;s interest and lifestyle site dedicated to reviving the lost art of manliness." />
58
+ <meta name="keywords" content="men, man, manliness," />
59
+ <link rel="stylesheet" href="http://artofmanliness.com/wp-content/themes/thesis_18/style.css?081310-141114" type="text/css" media="screen, projection" />
60
+ <link rel="stylesheet" href="http://artofmanliness.com/wp-content/themes/thesis_18/custom/layout.css?082310-12445" type="text/css" media="screen, projection" />
61
+ <!--[if lte IE 8]><link rel="stylesheet" href="http://artofmanliness.com/wp-content/themes/thesis_18/lib/css/ie.css?072510-23516" type="text/css" media="screen, projection" /><![endif]-->
62
+ <link rel="stylesheet" href="http://artofmanliness.com/wp-content/themes/thesis_18/custom/custom.css?091610-211116" type="text/css" media="screen, projection" />
63
+ <link rel="canonical" href="http://artofmanliness.com/" />
64
+ <link rel="alternate" type="application/rss+xml" title="The Art of Manliness RSS Feed" href="http://feeds2.feedburner.com/TheArtOfManliness" />
65
+ <link rel="pingback" href="http://artofmanliness.com/xmlrpc.php" />
66
+ <link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://artofmanliness.com/xmlrpc.php?rsd" />
67
+ <script language="Javascript">
68
+ <!--
69
+ var axel = Math.random() + "";
70
+ var ord = axel * 1000000000000000000;
71
+ //-->
72
+ </script>
73
+ <!-- PUT THIS TAG IN THE head SECTION -->
74
+ <script type="text/javascript" src="http://partner.googleadservices.com/gampad/google_service.js">
75
+ </script>
76
+ <script type="text/javascript">
77
+ GS_googleAddAdSenseService("ca-pub-5284223420088782");
78
+ GS_googleEnableAllServices();
79
+ </script>
80
+ <script type="text/javascript">
81
+ GA_googleAddSlot("ca-pub-5284223420088782", "300x105");
82
+ </script>
83
+ <script type="text/javascript">
84
+ GA_googleFetchAds();
85
+ </script>
86
+ <!-- END OF TAG FOR head SECTION -->
87
+ <script type="text/javascript">
88
+ (function() {
89
+ var s = document.createElement('SCRIPT'), s1 = document.getElementsByTagName('SCRIPT')[0];
90
+ s.type = 'text/javascript';
91
+ s.src = 'http://widgets.digg.com/buttons.js';
92
+ s1.parentNode.insertBefore(s, s1);
93
+ })();
94
+ </script>
95
+ <script type="text/javascript">var _sf_startpt=(new Date()).getTime()</script>
96
+ <meta name="verify-postrank" content="7pljxog" />
97
+ <link rel='stylesheet' id='slideshow-gallery-css' href='http://artofmanliness.com/wp-content/plugins/slideshow-gallery/css/gallery-css.php?1=1&amp;resizeimages=Y&amp;width=618&amp;height=336&amp;border&amp;background=%23000000&amp;infobackground=%23000000&amp;infocolor=%23FFFFFF&#038;ver=1.0' type='text/css' media='screen' />
98
+ <link rel='stylesheet' id='wp-email-css' href='http://artofmanliness.com/wp-content/plugins/wp-email/email-css.css?ver=2.50' type='text/css' media='all' />
99
+ <script type='text/javascript' src='http://artofmanliness.com/wp-includes/js/jquery/jquery.js?ver=1.4.2'></script>
100
+ <script type='text/javascript' src='http://artofmanliness.com/wp-content/plugins/slideshow-gallery/js/gallery.js?ver=1.0'></script>
101
+ <meta property="fb:admins" content="9604892"/><meta property="og:site_name" content="The Art of Manliness"/><meta property="og:url" content="http://artofmanliness.com/"/><meta property="og:type" content="blog"/><!-- tweet this -->
102
+ <!-- End tweet this -->
103
+
104
+ <link rel=”shortcut icon” href=”http://artofmanliness.com/favicon.ico”>
105
+ <meta name="verify-v1" content="4RSETFIMUwgS0VJ1XssuMNE1blUbrfpZHAb6qTSZde0=" >
106
+ <style type="text/css">
107
+ ol.footnotes li {list-style-type:decimal;}
108
+ ol.footnotes{font-size:0.8em; color:#666666;} </style>
109
+ </head>
110
+ <body class="custom">
111
+ <div id="header_area" class="full_width">
112
+ <div class="page">
113
+ <div id="topad">
114
+ <!-- FM Leaderboard 1 Zone -->
115
+ <script type='text/javascript' src='http://static.fmpub.net/zone/3323'></script>
116
+ <!-- FM Leaderboard 1 Zone -->
117
+ </div> <div id="header">
118
+ <p id="logo"><a href="http://artofmanliness.com">The Art of Manliness</a></p>
119
+ <h1 id="tagline">Men&#039;s Interests and Lifestyle</h1>
120
+ </div>
121
+ <ul class="menu">
122
+ <li class="tab tab-home current"><a href="http://artofmanliness.com" rel="nofollow">Home</a></li>
123
+ <li class="cat-item cat-item-3"><a href="http://artofmanliness.com/category/a-mans-life/" title="View all posts filed under A Man&#039;s Life">A Man&#039;s Life</a>
124
+ </li>
125
+ <li class="cat-item cat-item-5"><a href="http://artofmanliness.com/category/dress-grooming/" title="View all posts filed under Dress &amp; Grooming">Dress &amp; Grooming</a>
126
+ </li>
127
+ <li class="cat-item cat-item-7"><a href="http://artofmanliness.com/category/health-sports/" title="View all posts filed under Health &amp; Sports">Health &amp; Sports</a>
128
+ </li>
129
+ <li class="cat-item cat-item-11"><a href="http://artofmanliness.com/category/manly-skills/" title="View all posts filed under Manly Skills">Manly Skills</a>
130
+ </li>
131
+ <li class="cat-item cat-item-12"><a href="http://artofmanliness.com/category/money-career/" title="View all posts filed under Money &amp; Career">Money &amp; Career</a>
132
+ </li>
133
+ <li class="cat-item cat-item-65"><a href="http://artofmanliness.com/category/relationships-family/" title="View all posts filed under Relationships &amp; Family">Relationships &amp; Family</a>
134
+ </li>
135
+ <li><a href="http://community.artofmanliness.com">Community</a></li>
136
+ <li><a href="http://artofmanliness.com/man-knowledge">Man Knowledge</a></li>
137
+ </ul>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ <span>This string started with Woman in it and should turn into Man</span>
142
+ <span>I love me that cowboy.</span>
143
+ <a href="/2009/08/23/how-to-apologize-like-a-man/" rel="bookmark">
144
+ <img src="http://content.artofmanliness.com/uploads/2009/thumbnails/apologizethumb.jpg" alt="How to Apologize Like a Man">
145
+ How to Apologize Like a Man
146
+ </a>
147
+ </body>
148
+ </html>
149
+ EOHTML
150
+
151
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: feminizer
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 1
10
+ version: 1.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jack Danger Canty
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-28 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: nokogiri
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: activesupport
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: without_accents
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: shoulda
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ description: This library can take a piece of English text as a string and swap masculine words for feminine and vice-versa.
78
+ email:
79
+ - rubygems@6brand.com
80
+ executables: []
81
+
82
+ extensions: []
83
+
84
+ extra_rdoc_files: []
85
+
86
+ files:
87
+ - .gitignore
88
+ - Gemfile
89
+ - README.markdown
90
+ - Rakefile
91
+ - feminizer.gemspec
92
+ - lib/feminizer.rb
93
+ - test/feminizer_test.rb
94
+ has_rdoc: true
95
+ homepage: http://github.com/JackDanger/feminizer
96
+ licenses: []
97
+
98
+ post_install_message:
99
+ rdoc_options: []
100
+
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 3
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ requirements: []
122
+
123
+ rubyforge_project: feminizer
124
+ rubygems_version: 1.3.7
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: Programmatically swap the gender of an English text string
128
+ test_files:
129
+ - test/feminizer_test.rb