Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/twine.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Ludwig <sebastian@lurado.de>2016-05-03 23:49:43 +0300
committerSebastian Ludwig <sebastian@lurado.de>2016-05-03 23:59:22 +0300
commit60b0eb2adf71f0896b7cc19a826e0c1941734c92 (patch)
tree97df03cf7d73fa1a19388f5146eac94c98c4d405
parent50b1e90f8f79f323b898b20d7770ef93fc1cae89 (diff)
Allowing xliff tags in android values and escaping special characters as recommended by Android docs.
-rw-r--r--lib/twine/formatters/android.rb45
-rw-r--r--test/test_formatters.rb22
2 files changed, 53 insertions, 14 deletions
diff --git a/lib/twine/formatters/android.rb b/lib/twine/formatters/android.rb
index acc5da8..24c28aa 100644
--- a/lib/twine/formatters/android.rb
+++ b/lib/twine/formatters/android.rb
@@ -112,19 +112,44 @@ module Twine
"\t<string name=\"%{key}\">%{value}</string>"
end
- def format_value(value)
- # Android enforces the following rules on the values
- # 1) apostrophes and quotes must be escaped with a backslash
+ def escape_value(value)
+ # escape double and single quotes, & signs and tags
value = escape_quotes(value)
value.gsub!("'", "\\\\'")
- # 2) HTML escape the string
- value = CGI.escapeHTML(value)
- # 3) convert placeholders (e.g. %@ -> %s)
- value = convert_placeholders_from_twine_to_android(value)
- # 4) escape non resource identifier @ signs (http://developer.android.com/guide/topics/resources/accessing-resources.html#ResourcesFromXml)
+ value.gsub!(/&/, '&amp;')
+ value.gsub!('<', '&lt;')
+
+ # escape non resource identifier @ signs (http://developer.android.com/guide/topics/resources/accessing-resources.html#ResourcesFromXml)
resource_identifier_regex = /@(?!([a-z\.]+:)?[a-z+]+\/[a-zA-Z_]+)/ # @[<package_name>:]<resource_type>/<resource_name>
- value.gsub!(resource_identifier_regex, '\@')
- # 5) replace beginning and end spaces with \u0020. Otherwise Android strips them.
+ value.gsub(resource_identifier_regex, '\@')
+ end
+
+ # see http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling
+ # however unescaped HTML markup like in "Welcome to <b>Android</b>!" is stripped when retrieved with getString() (http://stackoverflow.com/questions/9891996/)
+ def format_value(value)
+ value = value.dup
+
+ # capture xliff tags and replace them with a placeholder
+ xliff_tags = []
+ value.gsub! /<xliff:g.+?<\/xliff:g>/ do
+ xliff_tags << $&
+ 'TWINE_XLIFF_TAG_PLACEHOLDER'
+ end
+
+ # escape everything outside xliff tags
+ value = escape_value(value)
+
+ # put xliff tags back into place
+ xliff_tags.each do |xliff_tag|
+ # escape content of xliff tags
+ xliff_tag.gsub! /(<xliff:g.*?>)(.*)(<\/xliff:g>)/ do "#{$1}#{escape_value($2)}#{$3}" end
+ value.sub! 'TWINE_XLIFF_TAG_PLACEHOLDER', xliff_tag
+ end
+
+ # convert placeholders (e.g. %@ -> %s)
+ value = convert_placeholders_from_twine_to_android(value)
+
+ # replace beginning and end spaces with \u0020. Otherwise Android strips them.
value.gsub(/\A *| *\z/) { |spaces| '\u0020' * spaces.length }
end
diff --git a/test/test_formatters.rb b/test/test_formatters.rb
index c40a12a..b8f0001 100644
--- a/test/test_formatters.rb
+++ b/test/test_formatters.rb
@@ -101,10 +101,24 @@ class TestAndroidFormatter < FormatterTest
assert_equal "value\\u0020", @formatter.format_value('value ')
end
- def test_format_value_escapes_single_quotes
- skip 'not working with ruby 2.0'
- # http://stackoverflow.com/questions/18735608/cgiescapehtml-is-escaping-single-quote
- assert_equal "not \\'so\\' easy", @formatter.format_value("not 'so' easy")
+ def test_format_value_escaping
+ values = {
+ 'this & that' => 'this &amp; that',
+ 'this < that' => 'this &lt; that',
+ "it's complicated" => "it\\'s complicated",
+ 'a "good" way' => 'a \"good\" way',
+ '<b>bold</b>' => '&lt;b>bold&lt;/b>',
+ '<a href="target">link</a>' => '&lt;a href=\"target\">link&lt;/a>',
+
+ '<xliff:g></xliff:g>' => '<xliff:g></xliff:g>',
+ '<xliff:g>untouched</xliff:g>' => '<xliff:g>untouched</xliff:g>',
+ '<xliff:g id="42">untouched</xliff:g>' => '<xliff:g id="42">untouched</xliff:g>',
+ '<xliff:g id="1">first</xliff:g> inbetween <xliff:g id="2">second</xliff:g>' => '<xliff:g id="1">first</xliff:g> inbetween <xliff:g id="2">second</xliff:g>'
+ }
+
+ values.each do |input, expected|
+ assert_equal expected, @formatter.format_value(input)
+ end
end
def test_format_value_escapes_non_resource_identifier_at_signs