CsprojResxWriter.rb 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. require 'rexml/document'
  2. class CsprojResxWriter
  3. attr_reader :language_exceptions
  4. def initialize(csproj_path, relative_resx_path)
  5. @csproj_path, @relative_resx_path = csproj_path, relative_resx_path
  6. @language_exceptions = {
  7. 'ca@valencia' => 'ca-ES-valencia',
  8. }
  9. end
  10. def absolute_resx_path_for_language(language)
  11. File.join(File.dirname(@csproj_path), relative_resx_path_for_language(language))
  12. end
  13. def remove_all_resx
  14. csproj = parse_csproj()
  15. csproj.each_element("//Project/ItemGroup/EmbeddedResource") do |resource|
  16. next unless resource.attributes['Include'] =~ /^#{Regexp.quote(@relative_resx_path.gsub('/', '\\'))}\\Resources\.\S+\.resx$/
  17. File.delete(File.join(File.dirname(@csproj_path), resource.attributes['Include']))
  18. resource.parent.delete(resource)
  19. end
  20. csproj.each_element("//Project/ItemGroup/Compile") do |resource|
  21. next unless resource.attributes['Include'] =~ /^#{Regexp.quote(@relative_resx_path.gsub('/', '\\'))}\\Resources\.\S+\.Designer.cs$/
  22. File.delete(File.join(File.dirname(@csproj_path), resource.attributes['Include']))
  23. resource.parent.delete(resource)
  24. end
  25. write_csproj(csproj)
  26. end
  27. def add_resx_to_csproj(language)
  28. csproj = parse_csproj()
  29. main_resx_name = @relative_resx_path.gsub('/', '\\') + '\\Resources.resx'
  30. item_group = csproj.elements["//Project/ItemGroup[.//EmbeddedResource[@Include='#{main_resx_name}']]"]
  31. item_group.add_element('EmbeddedResource', { 'Include' => relative_resx_path_for_language(language).gsub('/', '\\') })
  32. write_csproj(csproj)
  33. end
  34. def read_and_sort_source_resx
  35. doc = REXML::Document.new(IO.read(File.join(File.dirname(@csproj_path), @relative_resx_path, "Resources.resx")), { :attribute_quote => :quote })
  36. elements = doc.get_elements('//root/data')
  37. elements.sort_by!{ |x| x.attributes['name'] }
  38. elements.each do |element|
  39. parent = element.parent
  40. parent.delete(element)
  41. parent.add(element)
  42. end
  43. output = ""
  44. doc.write(output)
  45. output
  46. end
  47. private
  48. def relative_resx_path_for_language(language)
  49. normalized_language = @language_exceptions.has_key?(language) ? @language_exceptions[language] : language.sub('_', '-')
  50. File.join(@relative_resx_path, "Resources.#{normalized_language}.resx")
  51. end
  52. def parse_csproj
  53. REXML::Document.new(IO.read(@csproj_path), { :attribute_quote => :quote })
  54. end
  55. def write_csproj(doc)
  56. formatter = REXMLFormatter.new(2, true) # Add a space before a closing slash
  57. formatter.width = 10000
  58. formatter.compact = true
  59. File.open(@csproj_path, 'w') do |f|
  60. f.write "\uFEFF"
  61. f.puts '<?xml version="1.0" encoding="utf-8"?>'
  62. formatter.write(doc.root, f)
  63. end
  64. end
  65. class REXMLFormatter < REXML::Formatters::Pretty
  66. def write_element(node, output)
  67. if node.children.length == 1 && node.text =~ /\A[\n\s]+\z/m && node.attributes.empty?
  68. output << ' '*@level
  69. output << "<#{node.expanded_name}>\n"
  70. output << ' '*@level
  71. output << "</#{node.expanded_name}>"
  72. else
  73. super
  74. end
  75. end
  76. end
  77. end