Skip to content

Commit

Permalink
Merge pull request #8 from LikeTheSalad/release/2.3.0
Browse files Browse the repository at this point in the history
Release/2.3.0
  • Loading branch information
LikeTheSalad authored Jul 28, 2024
2 parents 5eae3d2 + fcdb037 commit f38fac5
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 31 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
==========

Version 2.3.0
---

* Keeping xml tags from xml string body.

Version 2.2.2
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import javax.xml.xpath.XPath
import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory

class AndroidXmlResDocument(private val document: Document) {

Expand All @@ -39,6 +42,7 @@ class AndroidXmlResDocument(private val document: Document) {
}

private val resources: Element by lazy { getOrCreateResources() }
private val xPath: XPath by lazy { XPathFactory.newInstance().newXPath() }

fun saveToFile(file: File, indentSpaces: Int = 4) {
val transformerFactory = TransformerFactory.newInstance()
Expand Down Expand Up @@ -66,8 +70,8 @@ class AndroidXmlResDocument(private val document: Document) {
}
}

fun getElementsByTagName(name: String): NodeList {
return resources.getElementsByTagName(name)
fun getElementsByXPath(xpath: String): NodeList {
return xPath.compile(xpath).evaluate(document, XPathConstants.NODESET) as NodeList
}

private fun getOrCreateResources(): Element {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.likethesalad.tools.resource.collector.android.data.xml

import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir
import org.w3c.dom.Node
import java.io.File
import java.io.StringWriter
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult

object XmlUtils {

private val XML_FORMAT = Regex(".+\\.[xX][mM][lL]\$")
private val OUTER_XML_TAGS_PATTERN = Regex("^<[^>]*>|<[^>]*>\$")
private val contentExtractor by lazy {
val transformer = TransformerFactory.newInstance().newTransformer()
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
transformer
}

fun findXmlFiles(valueDir: ValueDir): List<File> {
return valueDir.dir.listFiles { _, name ->
isXmlFile(name)
}?.toList() ?: emptyList()
}

private fun isXmlFile(name: String): Boolean {
return XML_FORMAT.matches(name)
}

fun getContents(node: Node): String {
val outText = StringWriter()
val streamResult = StreamResult(outText)
return try {
contentExtractor.transform(DOMSource(node), streamResult)
val text = outText.toString()
return OUTER_XML_TAGS_PATTERN.replace(text, "")
} catch (e: TransformerException) {
node.textContent
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.likethesalad.tools.resource.api.android.impl.AndroidResourceScope
import com.likethesalad.tools.resource.collector.android.data.resdir.ResDir
import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir
import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDirFinder
import com.likethesalad.tools.resource.collector.android.data.xml.XmlFileFinder
import com.likethesalad.tools.resource.collector.android.data.xml.XmlUtils
import com.likethesalad.tools.resource.collector.android.source.AndroidXmlResourceSource
import com.likethesalad.tools.resource.collector.source.ResourceSource
import com.likethesalad.tools.resource.collector.source.ResourceSourceProvider
Expand All @@ -25,7 +25,7 @@ class ResDirResourceSourceProvider(private val resDir: ResDir) : ResourceSourceP

private fun extractSourcesFromValueDir(valueDir: ValueDir): Collection<ResourceSource> {
val sources = mutableListOf<ResourceSource>()
val xmlFiles = XmlFileFinder.findXmlFiles(valueDir)
val xmlFiles = XmlUtils.findXmlFiles(valueDir)
val scope = AndroidResourceScope(valueDir.resDir.variant, valueDir.language)

for (file in xmlFiles) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir
import com.likethesalad.tools.testing.DummyResourcesFinder.getResourceFile
import io.mockk.mockk
import org.junit.Test
import java.io.ByteArrayInputStream
import java.io.File
import javax.xml.parsers.DocumentBuilderFactory

class XmlFileFinderTest {

class XmlUtilsTest {

@Test
fun `Find xml files`() {
Expand All @@ -35,10 +38,21 @@ class XmlFileFinderTest {
Truth.assertThat(files).isEmpty()
}

@Test
fun `Extract text from node`() {
val node = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(ByteArrayInputStream("<string name=\"the_name\">value <b>something bold</b></string>".toByteArray()))
.documentElement

Truth.assertThat(XmlUtils.getContents(node)).isEqualTo("value <b>something bold</b>")
}

private fun findXmlFilesFromFolder(folder: File): List<File> {
val resDir = mockk<ResDir>()
val valuesDir = ValueDir(resDir, folder, Language.Default)

return XmlFileFinder.findXmlFiles(valuesDir)
return XmlUtils.findXmlFiles(valuesDir)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.likethesalad.resource.serializer.android

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.likethesalad.resource.serializer.android.internal.AndroidResourceJsonCollection
import com.likethesalad.resource.serializer.android.internal.AndroidResourceJsonStructure
import com.likethesalad.resource.serializer.android.internal.AndroidResourceMapper
Expand All @@ -12,7 +12,11 @@ import com.likethesalad.tools.resource.serializer.ResourceSerializer

class AndroidResourceSerializer : ResourceSerializer {

private val gson by lazy { Gson() }
private val gson by lazy {
GsonBuilder()
.disableHtmlEscaping()
.create()
}

override fun serialize(resource: Resource): String {
val jsonStructure = AndroidResourceMapper.mapToJson(resource as AndroidResource)
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kotlin.code.style=official
kotlin.version=1.9.22
group=com.likethesalad.tools.resources
version=2.2.2
version=2.3.0
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import com.likethesalad.tools.resource.api.android.impl.AndroidResourceScope
import com.likethesalad.tools.resource.api.android.modules.string.StringAndroidResource
import com.likethesalad.tools.resource.api.attributes.AttributeKey
import com.likethesalad.tools.resource.collector.android.data.AndroidXmlResDocument
import com.likethesalad.tools.resource.collector.android.data.xml.XmlUtils
import com.likethesalad.tools.resource.collector.android.extractor.XmlResourceExtractor
import org.w3c.dom.Node
import org.w3c.dom.NodeList

class StringXmlResourceExtractor : XmlResourceExtractor<StringAndroidResource>() {

companion object {
private const val XML_STRING_TAG = "string"
private const val STRING_RESOURCE_PATH = "/resources/string"
}

override fun getResourcesFromAndroidDocument(
Expand All @@ -40,7 +41,7 @@ class StringXmlResourceExtractor : XmlResourceExtractor<StringAndroidResource>()

private fun parseNodeToStringAndroidResource(node: Node, scope: Resource.Scope): StringAndroidResource {
val attributesMap = mutableMapOf<AttributeKey, String>()
val value = trimQuotes(node.textContent)
val value = trimQuotes(getNodeText(node))
val attributesNodes = node.attributes
for (index in 0 until attributesNodes.length) {
val attr = attributesNodes.item(index)
Expand All @@ -55,11 +56,15 @@ class StringXmlResourceExtractor : XmlResourceExtractor<StringAndroidResource>()
return StringAndroidResource(attributesMap, value, scope as AndroidResourceScope)
}

private fun getNodeText(node: Node): String {
return XmlUtils.getContents(node)
}

private fun trimQuotes(text: String): String {
return text.replace(Regex("(?<!\\\\)\""), "")
}

private fun getStringNodeList(document: AndroidXmlResDocument): NodeList {
return document.getElementsByTagName(XML_STRING_TAG)
return document.getElementsByXPath(STRING_RESOURCE_PATH)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
<integer name="number_1">1</integer>
<bool name="bool_1">true</bool>
<string name="string_7">Just one more string</string>
<string name="string_8">Some string with <b>tags</b></string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class StringXmlResourceExtractorTest {
StringAndroidResource("string_4", "Some partially quoted string", scope),
StringAndroidResource("string_5", "Some partially quoted escaped \\\"string\\\"", scope),
StringAndroidResource("string_7", "Just one more string", scope),
StringAndroidResource("string_8", "Some string with <b>tags</b>", scope),
StringAndroidResource("string_3", "Some quoted string", scope),
StringAndroidResource(
mapOf(plain("name") to "string_2", plain("translatable") to "false"),
Expand Down

0 comments on commit f38fac5

Please sign in to comment.