diff --git a/xml/xml-psi-api/resources/messages/XmlPsiBundle.properties b/xml/xml-psi-api/resources/messages/XmlPsiBundle.properties index 77b87444b8ce..2943c72001f9 100644 --- a/xml/xml-psi-api/resources/messages/XmlPsiBundle.properties +++ b/xml/xml-psi-api/resources/messages/XmlPsiBundle.properties @@ -49,50 +49,4 @@ element.is.not.closed=Element is not closed # suppress inspection "UnusedProperty" rename.start.tag.name.intention=Rename start tag ''{0}'' to ''{1}'' # suppress inspection "UnusedProperty" -rename.end.tag.name.intention=Rename end tag ''{0}'' to ''{1}'' - -# Dynamic usage in MdnSymbolDocumentationAdapter -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.browser_compatibility=Supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.flex_context=Supported in
Flex context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.grid_context=Supported in
Grid context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.multicol_context=Supported in
Multi-column Layout by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.paged_context=Supported in
Paged Media by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.supported_in_grid_layout="Supported in
Grid Layout by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.support_of_multi-keyword_values=Multiple values
supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.supported_for_width_and_other_sizing_properties=Sizing properties
supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.support_of_ruby_values=ruby-* supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.support_of_table_values=table-* supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.support_of_WOFF=WOFF supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.support_of_WOFF_2=WOFF 2 supported by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.2d_context=Supported in
2D context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.3d_context=Supported in
3D context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.bitmaprenderer_context=Supported in
bitmaprenderer context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.webgl2_context=Supported in
WebGL 2 context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.webgl_context=Supported in
WebGL context by -# suppress inspection "UnusedProperty" -mdn.documentation.section.compat.webgpu_context=Supported in
Web GPU context by - -mdn.documentation.section.compat.support_of={0} supported by -mdn.documentation.section.compat.supported_by.none=none -mdn.documentation.section.parameters=Params -mdn.documentation.section.returns=Returns -mdn.documentation.section.throws=Throws -mdn.documentation.section.syntax=Syntax -mdn.documentation.section.values=Values +rename.end.tag.name.intention=Rename end tag ''{0}'' to ''{1}'' \ No newline at end of file diff --git a/xml/xml-psi-impl/mdn-doc-gen/intellij.documenation.mdn.gen.iml b/xml/xml-psi-impl/mdn-doc-gen/intellij.documenation.mdn.gen.iml index 84ba3bcb1019..ffbea2b5380d 100644 --- a/xml/xml-psi-impl/mdn-doc-gen/intellij.documenation.mdn.gen.iml +++ b/xml/xml-psi-impl/mdn-doc-gen/intellij.documenation.mdn.gen.iml @@ -17,10 +17,15 @@ - + + + + + + \ No newline at end of file diff --git a/xml/xml-psi-impl/mdn-doc-gen/src/GenerateMdnDocumentation.kt b/xml/xml-psi-impl/mdn-doc-gen/src/GenerateMdnDocumentation.kt index de439ab1ccce..49e7c905a994 100644 --- a/xml/xml-psi-impl/mdn-doc-gen/src/GenerateMdnDocumentation.kt +++ b/xml/xml-psi-impl/mdn-doc-gen/src/GenerateMdnDocumentation.kt @@ -43,59 +43,8 @@ val htmlSpecialMappings = mapOf( * When adding a known property here, ensure that there is appropriate key in XmlPsiBundle. */ const val defaultBcdContext = "\$default_context" -val knownBcdIds = setOf( - defaultBcdContext, - "flex_context", - "grid_context", - "multicol_context", - "paged_context", - "supported_for_width_and_other_sizing_properties", - "supported_in_grid_layout", - // CSS values support - by default not translated - "support_of_multi-keyword_values", // translated - "support_of_flow-root", - "support_of_grid", - "support_of_flex", - "support_of_ruby_values", //translated - "support_of_table_values", //translated - "support_of_inline-table", - "support_of_inline-grid", - "support_of_inline-flex", - "support_of_inline-block", - "support_of_WOFF", //translated - "support_of_WOFF_2", //translated - "support_of_-webkit-resizer", - "support_of_-webkit-scrollbar", - "support_of_-webkit-scrollbar-button", - "support_of_-webkit-scrollbar-corner", - "support_of_-webkit-scrollbar-thumb", - "support_of_-webkit-scrollbar-track", - "support_of_-webkit-scrollbar-track-piece", - "support_of_color-mix", - "support_of_interpolation_color_space", - "support_of_hue_interpolation_method", - "support_of_fit-content", - "support_of_fit-content_function", - "support_of_hsl", - "support_of_hwb", - "support_of_lch", - "support_of_oklch", - - //JS - by default not translated - "support_of_compressedTexImage2D", - "support_of_compressedTexImage3D", - "support_of_texParameterf", - "support_of_texParameteri", - "2d_context", - "3d_context", - "bitmaprenderer_context", - "webgl2_context", - "webgl_context", - "webgpu_context" -) - -val jsRuntimesMap = MdnJavaScriptRuntime.values().associateBy { it.mdnId } +val jsRuntimesMap = MdnJavaScriptRuntime.entries.associateBy { it.mdnId } val BROWSER_COMPAT_DATA_PATH = PathManager.getCommunityHomePath() + "/xml/xml-psi-impl/mdn-doc-gen/work/browser-compat-data.json" val MDN_CONTENT_ROOT = PathManager.getCommunityHomePath() + "/xml/xml-psi-impl/mdn-doc-gen/work/mdn-content/files" @@ -103,7 +52,8 @@ val YARI_BUILD_PATH = PathManager.getCommunityHomePath() + "/xml/xml-psi-impl/md const val BUILT_LANG = "en-us" const val WEB_DOCS = "docs/web" const val MDN_DOCS_URL_PREFIX = "\$MDN_URL\$" -const val OUTPUT_DIR = "xml/xml-psi-impl/gen/com/intellij/documentation/mdn/" +const val OUTPUT_DIR = "xml/xml-psi-impl/resources-gen/com/intellij/documentation/mdn/" +const val BUNDLE_OUTPUT_DIR = "xml/xml-psi-impl/resources-gen/messages/" const val SEE_REFERENCE = "\$SEE_REFERENCE\$" val seePattern = Regex("

See [a-z0-9_\\-]+\\.

", @@ -121,6 +71,8 @@ val jsWebApiNameFilter: (String) -> Boolean = { name -> && name != "index" } +val bcdIdDescriptions = mutableMapOf() + /* It's so much easier to run a test, than to setup the whole IJ environment */ class GenerateMdnDocumentation : BasePlatformTestCase() { @@ -183,6 +135,7 @@ class GenerateMdnDocumentation : BasePlatformTestCase() { FileUtil.writeToFile(Path.of(PathManager.getCommunityHomePath(), OUTPUT_DIR, "${MdnApiNamespace.WebApi.name}-index.json").toFile(), GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create() .toJson(index)) + updateBcdDescriptions() } fun testGenJsGlobalObjects() { @@ -234,6 +187,7 @@ class GenerateMdnDocumentation : BasePlatformTestCase() { .registerTypeAdapter(Map::class.java, CompatibilityMapSerializer()) .create() .toJson(additionalMetadata() + data)) + updateBcdDescriptions() } private fun extractInformationSimple(bcdPath: String, mdnPath: String, @@ -993,20 +947,20 @@ class GenerateMdnDocumentation : BasePlatformTestCase() { ?.takeIf { map -> map.values.any { it == null || it.isNotEmpty() } } ?.filterValues { it != null } ?.let { + val bcdId = if (id != defaultBcdContext) getBcdId(id) else id + if (bcdId != defaultBcdContext) { + val description = data.compat.description + if (description != null) { + bcdIdDescriptions.putIfAbsent(bcdId, description) + } + } + @Suppress("UNCHECKED_CAST") - Pair(if (id != defaultBcdContext) getBcdId(id) else id, - it.toMap(TreeMap()) as Map) + Pair(bcdId, it.toMap(TreeMap()) as Map) } } .toMap(TreeMap()) .takeIf { it.isNotEmpty() } - ?.let { - it.forEach { (id, _) -> - if (!knownBcdIds.contains(id)) throw AssertionError( - "Unknown BCD id: $id. Add id to the list and possibly add readable caption to Xml bundle (mdn.documentation.section.compat.* strings).") - } - it - } private fun getBcdId(id: String): String = id.takeLastWhile { it != '.' }.let { @@ -1109,6 +1063,25 @@ class GenerateMdnDocumentation : BasePlatformTestCase() { private fun File.toMdnUrl(): String = toString().removePrefix(getMdnDir("").toString()) + private fun updateBcdDescriptions() { + val bundleFile = Path.of(PathManager.getCommunityHomePath(), BUNDLE_OUTPUT_DIR, "MdnBundle.properties").toFile() + val contents = FileUtil.loadLines(bundleFile) + + val existingProperties = contents.asSequence() + .filter { it.startsWith("mdn.documentation.section.compat.")} + .map { it.substring("mdn.documentation.section.compat.".length).substringBefore("=") } + .toSet() + + bcdIdDescriptions + .filter { it.key !in existingProperties } + .ifEmpty { return } + .forEach { (id, description) -> + contents.add("mdn.documentation.section.compat.$id=$description") + } + + FileUtil.writeToFile(bundleFile, contents.joinToString("\n")); + } + private inner class CssElementInfo(docDir: File) { val name: String @@ -1255,8 +1228,11 @@ private fun RawProse.appendOtherSections(indexDataProseValues: List) content, if (try_it_section != null) { val iframeEnd = try_it_section.indexOf("") - if (iframeEnd < 0) throw RuntimeException("Cannot find iframe end - $try_it_section") - try_it_section.substring(iframeEnd + "".length).trim() + .takeIf { it > 0 }?.let { it + "".length } + ?: try_it_section.indexOf("") + .takeIf { it > 0 }?.let { it + "".length } + if (iframeEnd == null) throw RuntimeException("Cannot find iframe or interactive-example end - $try_it_section") + try_it_section.substring(iframeEnd).trim() } else "", description_section?.trim() ?: "" @@ -1283,10 +1259,13 @@ private fun String.patchProse(): String = .replace("'", "'") .replace(""", "\"") .replace(" ", " ") + .replace("&ldquo","“") + .replace("&rdquo","”") + .replace("&hellip","…") .replace(Regex("

\\s+"), "

") .replace(Regex("(^

\\s*)|(\\s*

)|(\\s*]*>)|(\\s*\\s*\\s*)"), "") .also { fixedProse -> - Regex("&(?!lt|gt|amp)[a-z]*;").find(fixedProse)?.let { + Regex("&(?!lt|gt|amp|shy)[a-z]*;").find(fixedProse)?.let { throw Exception("Unknown entity found in prose: ${it.value}") } } diff --git a/xml/xml-psi-impl/resources-gen/messages/MdnBundle.properties b/xml/xml-psi-impl/resources-gen/messages/MdnBundle.properties new file mode 100644 index 000000000000..f772713bb112 --- /dev/null +++ b/xml/xml-psi-impl/resources-gen/messages/MdnBundle.properties @@ -0,0 +1,42 @@ +mdn.documentation.section.compat.support_of={0} supported by +mdn.documentation.section.compat.supported_by.none=none +mdn.documentation.section.parameters=Params +mdn.documentation.section.returns=Returns +mdn.documentation.section.throws=Throws +mdn.documentation.section.syntax=Syntax +mdn.documentation.section.values=Values + +# Dynamic usage in MdnSymbolDocumentationAdapter +mdn.documentation.section.compat.browser_compatibility=Supported by +mdn.documentation.section.compat.flex_context=Supported in
Flex Layout by +mdn.documentation.section.compat.grid_context=Supported in
Grid Layout by +mdn.documentation.section.compat.block_context=Supported in
Block Layout by +mdn.documentation.section.compat.multicol_context=Supported in
Multi-column Layout by +mdn.documentation.section.compat.paged_context=Supported in
Paged Media by +mdn.documentation.section.compat.position_absolute_context=Supported in
absolute position context by +mdn.documentation.section.compat.supported_in_grid_layout="Supported in
Grid Layout by +mdn.documentation.section.compat.2d_context=Supported in
2D context by +mdn.documentation.section.compat.3d_context=Supported in
3D context by +mdn.documentation.section.compat.bitmaprenderer_context=Supported in
bitmaprenderer context by +mdn.documentation.section.compat.webgl2_context=Supported in
WebGL 2 context by +mdn.documentation.section.compat.webgl_context=Supported in
WebGL context by +mdn.documentation.section.compat.webgpu_context=Supported in
Web GPU context by +mdn.documentation.section.compat.supported_for_width_and_other_sizing_properties=Sizing properties
supported by +mdn.documentation.section.compat.support_of_multi-keyword_values=Multiple values
supported by +mdn.documentation.section.compat.support_of_WOFF=WOFF supported by +mdn.documentation.section.compat.support_of_WOFF_2=WOFF 2 supported by +mdn.documentation.section.compat.support_of_dialog_elements=beforetoggle event fires at dialog elements +mdn.documentation.section.compat.support_of_details_elements=toggle event fires at details elements +mdn.documentation.section.compat.support_of_-webkit-scrollbar=::-webkit-scrollbar +mdn.documentation.section.compat.support_of_-webkit-scrollbar-button=::-webkit-scrollbar-button +mdn.documentation.section.compat.support_of_-webkit-scrollbar-thumb=::-webkit-scrollbar-thumb +mdn.documentation.section.compat.support_of_-webkit-scrollbar-track=::-webkit-scrollbar-track +mdn.documentation.section.compat.support_of_-webkit-scrollbar-track-piece=::-webkit-scrollbar-track-piece +mdn.documentation.section.compat.support_of_-webkit-scrollbar-corner=::-webkit-scrollbar-corner +mdn.documentation.section.compat.support_of_-webkit-resizer=::-webkit-resizer +mdn.documentation.section.compat.support_of_fit-content=fit-content() +mdn.documentation.section.compat.support_of_fit-content_function=fit-content() +mdn.documentation.section.compat.support_of_hsl=hsl() (HSL color model) +mdn.documentation.section.compat.support_of_hwb=hwb() (HWB color model) +mdn.documentation.section.compat.support_of_lch=lch() (LCH color model) +mdn.documentation.section.compat.support_of_oklch=oklch() (OKLCH color model) \ No newline at end of file diff --git a/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnBundle.java b/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnBundle.java new file mode 100644 index 000000000000..2991822a6e93 --- /dev/null +++ b/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnBundle.java @@ -0,0 +1,30 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.documentation.mdn; + +import com.intellij.DynamicBundle; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.PropertyKey; + +import java.util.function.Supplier; + +public final class MdnBundle { + private static final @NonNls String BUNDLE = "messages.MdnBundle"; + private static final DynamicBundle INSTANCE = new DynamicBundle(MdnBundle.class, BUNDLE); + + private MdnBundle() { + } + + public static @NotNull @Nls String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { + return INSTANCE.getMessage(key, params); + } + + public static @NotNull Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { + return INSTANCE.getLazyMessage(key, params); + } + + public static boolean hasKey(String key) { + return INSTANCE.containsKey(key); + } +} diff --git a/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnDocumentation.kt b/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnDocumentation.kt index 860c1931f6b3..9bcd98f6d7c6 100644 --- a/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnDocumentation.kt +++ b/xml/xml-psi-impl/src/com/intellij/documentation/mdn/MdnDocumentation.kt @@ -26,7 +26,6 @@ import com.intellij.psi.xml.* import com.intellij.util.asSafely import com.intellij.webSymbols.WebSymbolApiStatus import com.intellij.webSymbols.WebSymbolsBundle -import com.intellij.xml.psi.XmlPsiBundle import com.intellij.xml.util.HtmlUtil import org.jetbrains.annotations.Nls import java.util.* @@ -225,15 +224,15 @@ class MdnSymbolDocumentationAdapter(override val name: String, doc.compatibility!!.entries.forEach { (id, map) -> val actualId = if (id == defaultBcdContext) "browser_compatibility" else id val bundleKey = "mdn.documentation.section.compat.$actualId" - val sectionName: String = if (actualId.startsWith("support_of_") && !XmlPsiBundle.hasKey(bundleKey)) { - XmlPsiBundle.message("mdn.documentation.section.compat.support_of", actualId.substring("support_of_".length)) + val sectionName: String = if (actualId.startsWith("support_of_") && !MdnBundle.hasKey(bundleKey)) { + MdnBundle.message("mdn.documentation.section.compat.support_of", actualId.substring("support_of_".length)) } else { - XmlPsiBundle.message(bundleKey) + MdnBundle.message(bundleKey) } result[sectionName] = map.entries .joinToString(", ") { it.key.displayName + (if (it.value.isNotEmpty()) " " + it.value else "") } - .ifBlank { XmlPsiBundle.message("mdn.documentation.section.compat.supported_by.none") } + .ifBlank { MdnBundle.message("mdn.documentation.section.compat.supported_by.none") } } } doc.status?.asSequence() @@ -329,11 +328,11 @@ data class MdnJsSymbolDocumentation(override val url: String?, get() { val result = mutableMapOf() parameters?.takeIf { it.isNotEmpty() }?.let { - result.put(XmlPsiBundle.message("mdn.documentation.section.parameters"), buildSubSection(it)) + result.put(MdnBundle.message("mdn.documentation.section.parameters"), buildSubSection(it)) } - returns?.let { result.put(XmlPsiBundle.message("mdn.documentation.section.returns"), it) } + returns?.let { result.put(MdnBundle.message("mdn.documentation.section.returns"), it) } throws?.takeIf { it.isNotEmpty() }?.let { - result.put(XmlPsiBundle.message("mdn.documentation.section.throws"), buildSubSection(it)) + result.put(MdnBundle.message("mdn.documentation.section.throws"), buildSubSection(it)) } return result } @@ -349,7 +348,7 @@ data class MdnCssBasicSymbolDocumentation(override val url: String?, get() { val result = mutableMapOf() formalSyntax?.takeIf { it.isNotEmpty() }?.let { - result.put(XmlPsiBundle.message("mdn.documentation.section.syntax"), "
$it
") + result.put(MdnBundle.message("mdn.documentation.section.syntax"), "
$it
") } return result } @@ -366,7 +365,7 @@ data class MdnCssAtRuleSymbolDocumentation(override val url: String?, get() { val result = mutableMapOf() formalSyntax?.takeIf { it.isNotEmpty() }?.let { - result.put(XmlPsiBundle.message("mdn.documentation.section.syntax"), "
$it
") + result.put(MdnBundle.message("mdn.documentation.section.syntax"), "
$it
") } return result } @@ -383,10 +382,10 @@ data class MdnCssPropertySymbolDocumentation(override val url: String?, get() { val result = mutableMapOf() formalSyntax?.takeIf { it.isNotEmpty() }?.let { - result.put(XmlPsiBundle.message("mdn.documentation.section.syntax"), "
$it
") + result.put(MdnBundle.message("mdn.documentation.section.syntax"), "
$it
") } values?.takeIf { it.isNotEmpty() }?.let { - result.put(XmlPsiBundle.message("mdn.documentation.section.values"), buildSubSection(values)) + result.put(MdnBundle.message("mdn.documentation.section.values"), buildSubSection(values)) } return result }