We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Feature Request]: Improve the experience of adding concept cards in the exploration editor.
### Is your feature request related to a problem? Please describe.

The experience of adding skill concept cards in the exploration editor has a number of issues:

- The highlighted text in the RTE does not get transferred to the concept card skill link modal when it is opened.
- Cancelling the operation results in the disappearance of the highlighted text.
- The list of skills takes a long time to load, even if it has already been fetched previously.
- Terms entered in the skill filter input box do not get applied when the skill list finally loads.
- The detailed skill explanations show up in red, which is hard to read (and suggests some kind of error).

See the video below for the current experience:

https://github.com/oppia/oppia/assets/10575562/60c94af1-8550-4be8-b277-ad4084b8daa9

### Describe the solution you'd like

- [x] When the skill link modal is opened, the text input field should be populated with the highlighted text in the RTE, or "concept card" if there is no highlighted text.
- [x] When the modal is cancelled, the RTE contents should stay as they were before the modal was opened. In particular, any highlighted text should not be deleted.
- [x] The skill filter input box should be disabled until the list of skills has loaded.
- [x] Skill explanations should show up in black text.

### Describe alternatives you've considered

- I considered also writing "the list of skills should load faster", but in reality there's always going to be some lag time. It might be possible to cache this list so that it loads fast for the second and subsequent queries, but that could lead to problems with stale data if a skill is created/deleted while an exploration is being edited. So I suggest that we don't solve that problem in this issue, and fix the other points first -- then, we can see if the loading time is still an issue.

### Additional context

_No response_

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/domain/rte_component_registry.py`
Content:
```
1 # coding: utf-8
2 #
3 # Copyright 2014 The Oppia Authors. All Rights Reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS-IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 """Registry for custom rich-text components."""
18 
19 from __future__ import annotations
20 
21 import inspect
22 import os
23 import pkgutil
24 
25 from core import constants
26 from core import feconf
27 from core import utils
28 
29 from typing import Any, Dict, List, Type, TypedDict, Union
30 
31 MYPY = False
32 if MYPY: # pragma: no cover
33     # Here, we are importing 'components' from rich_text_components only
34     # for type checking.
35     from extensions.rich_text_components import components
36 
37 
38 class CustomizationArgSpecDict(TypedDict):
39     """Dictionary representing the customization_arg_specs object."""
40 
41     name: str
42     description: str
43     # Here we use type Any because values in schema dictionary can be of
44     # type str, List, Dict and other types too.
45     schema: Dict[str, Any]
46     default_value: Union[str, int, List[str], Dict[str, str]]
47 
48 
49 class RteComponentDict(TypedDict):
50     """Dictionary representing the RTE component's definition."""
51 
52     backend_id: str
53     category: str
54     description: str
55     frontend_id: str
56     tooltip: str
57     icon_data_url: str
58     is_complex: bool
59     requires_internet: bool
60     requires_fs: bool
61     is_block_element: bool
62     customization_arg_specs: List[CustomizationArgSpecDict]
63 
64 
65 class Registry:
66     """Registry of all custom rich-text components."""
67 
68     _rte_components: Dict[str, RteComponentDict] = {}
69 
70     @classmethod
71     def _refresh(cls) -> None:
72         """Repopulate the registry."""
73         cls._rte_components.clear()
74         package, filepath = os.path.split(
75             feconf.RTE_EXTENSIONS_DEFINITIONS_PATH)
76         cls._rte_components = constants.parse_json_from_ts(
77             constants.get_package_file_contents(package, filepath))
78 
79     @classmethod
80     def get_all_rte_components(cls) -> Dict[str, RteComponentDict]:
81         """Get a dictionary mapping RTE component IDs to their definitions."""
82         if not cls._rte_components:
83             cls._refresh()
84         return cls._rte_components
85 
86     @classmethod
87     def get_tag_list_with_attrs(cls) -> Dict[str, List[str]]:
88         """Returns a dict of HTML tag names and attributes for RTE components.
89 
90         The keys are tag names starting with 'oppia-noninteractive-', followed
91         by the hyphenated version of the name of the RTE component. The values
92         are lists of allowed attributes of the form
93         [PARAM_NAME]-with-[CUSTOMIZATION_ARG_NAME].
94         """
95         # TODO(sll): Cache this computation and update it on each refresh.
96         # Better still, bring this into the build process so it doesn't have
97         # to be manually computed each time.
98         component_list = list(cls.get_all_rte_components().values())
99 
100         component_tags = {}
101         for component_specs in component_list:
102             tag_name = 'oppia-noninteractive-%s' % (
103                 utils.camelcase_to_hyphenated(component_specs['backend_id']))
104 
105             component_tags[tag_name] = [
106                 '%s-with-value' % ca_spec['name']
107                 for ca_spec in component_specs['customization_arg_specs']]
108 
109         return component_tags
110 
111     @classmethod
112     def get_component_types_to_component_classes(
113         cls
114     ) -> Dict[str, Type[components.BaseRteComponent]]:
115         """Get component classes mapping for component types.
116 
117         Returns:
118             dict. A dict mapping from rte component types to rte component
119             classes.
120         """
121         rte_path = [feconf.RTE_EXTENSIONS_DIR]
122 
123         for loader, name, _ in pkgutil.iter_modules(path=rte_path):
124             if name == 'components':
125                 fetched_module = loader.find_module(name)
126                 # Ruling out the possibility of None for mypy type checking.
127                 assert fetched_module is not None
128                 module = fetched_module.load_module(name)
129                 break
130 
131         component_types_to_component_classes = {}
132         component_names = list(cls.get_all_rte_components().keys())
133         for component_name in component_names:
134             for name, obj in inspect.getmembers(module):
135                 if inspect.isclass(obj) and name == component_name:
136                     component_types_to_component_classes[
137                         'oppia-noninteractive-%s' % component_name.lower()] = (
138                             obj)
139 
140         return component_types_to_component_classes
141 
142     @classmethod
143     def get_component_tag_names(
144         cls, key: str, expected_value: bool
145     ) -> List[str]:
146         """Get a list of component tag names which have the expected
147         value of a key.
148 
149         Args:
150             key: str. The key to be checked in component spec.
151             expected_value: bool. The expected value of the key to select
152                 the components.
153 
154         Returns:
155             list(str). A list of component tag names which have the expected
156             value of a key.
157         """
158         rich_text_components_specs = cls.get_all_rte_components()
159         component_tag_names = []
160         for component_spec in rich_text_components_specs.values():
161             if component_spec.get(key) == expected_value:
162                 component_tag_names.append(
163                     'oppia-noninteractive-%s' % component_spec['frontend_id'])
164         return component_tag_names
165 
166     @classmethod
167     def get_inline_component_tag_names(cls) -> List[str]:
168         """Get a list of inline component tag names.
169 
170         Returns:
171             list(str). A list of inline component tag names.
172         """
173         return cls.get_component_tag_names('is_block_element', False)
174 
175     @classmethod
176     def get_block_component_tag_names(cls) -> List[str]:
177         """Get a list of block component tag names.
178 
179         Returns:
180             list(str). A list of block component tag names.
181         """
182         return cls.get_component_tag_names('is_block_element', True)
183 
184     @classmethod
185     def get_simple_component_tag_names(cls) -> List[str]:
186         """Get a list of simple component tag names.
187 
188         Returns:
189             list(str). A list of simple component tag names.
190         """
191         return cls.get_component_tag_names('is_complex', False)
192 
193     @classmethod
194     def get_complex_component_tag_names(cls) -> List[str]:
195         """Get a list of complex component tag names.
196 
197         Returns:
198             list(str). A list of complex component tag names.
199         """
200         return cls.get_component_tag_names('is_complex', True)
201
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/domain/rte_component_registry.py b/core/domain/rte_component_registry.py
--- a/core/domain/rte_component_registry.py
+++ b/core/domain/rte_component_registry.py
@@ -43,6 +43,7 @@
     # Here we use type Any because values in schema dictionary can be of
     # type str, List, Dict and other types too.
     schema: Dict[str, Any]
+    default_value_obtainable_from_highlight: bool
     default_value: Union[str, int, List[str], Dict[str, str]]

{"golden_diff": "diff --git a/core/domain/rte_component_registry.py b/core/domain/rte_component_registry.py\n--- a/core/domain/rte_component_registry.py\n+++ b/core/domain/rte_component_registry.py\n@@ -43,6 +43,7 @@\n     # Here we use type Any because values in schema dictionary can be of\n     # type str, List, Dict and other types too.\n     schema: Dict[str, Any]\n+    default_value_obtainable_from_highlight: bool\n     default_value: Union[str, int, List[str], Dict[str, str]]\n", "issue": "[Feature Request]: Improve the experience of adding concept cards in the exploration editor.\n### Is your feature request related to a problem? Please describe.\r\n\r\nThe experience of adding skill concept cards in the exploration editor has a number of issues:\r\n\r\n- The highlighted text in the RTE does not get transferred to the concept card skill link modal when it is opened.\r\n- Cancelling the operation results in the disappearance of the highlighted text.\r\n- The list of skills takes a long time to load, even if it has already been fetched previously.\r\n- Terms entered in the skill filter input box do not get applied when the skill list finally loads.\r\n- The detailed skill explanations show up in red, which is hard to read (and suggests some kind of error).\r\n\r\nSee the video below for the current experience:\r\n\r\nhttps://github.com/oppia/oppia/assets/10575562/60c94af1-8550-4be8-b277-ad4084b8daa9\r\n\r\n### Describe the solution you'd like\r\n\r\n- [x] When the skill link modal is opened, the text input field should be populated with the highlighted text in the RTE, or \"concept card\" if there is no highlighted text.\r\n- [x] When the modal is cancelled, the RTE contents should stay as they were before the modal was opened. In particular, any highlighted text should not be deleted.\r\n- [x] The skill filter input box should be disabled until the list of skills has loaded.\r\n- [x] Skill explanations should show up in black text.\r\n\r\n### Describe alternatives you've considered\r\n\r\n- I considered also writing \"the list of skills should load faster\", but in reality there's always going to be some lag time. It might be possible to cache this list so that it loads fast for the second and subsequent queries, but that could lead to problems with stale data if a skill is created/deleted while an exploration is being edited. So I suggest that we don't solve that problem in this issue, and fix the other points first -- then, we can see if the loading time is still an issue.\r\n\r\n### Additional context\r\n\r\n_No response_\n", "before_files": [{"content": "# coding: utf-8\n#\n# Copyright 2014 The Oppia Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS-IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Registry for custom rich-text components.\"\"\"\n\nfrom __future__ import annotations\n\nimport inspect\nimport os\nimport pkgutil\n\nfrom core import constants\nfrom core import feconf\nfrom core import utils\n\nfrom typing import Any, Dict, List, Type, TypedDict, Union\n\nMYPY = False\nif MYPY: # pragma: no cover\n    # Here, we are importing 'components' from rich_text_components only\n    # for type checking.\n    from extensions.rich_text_components import components\n\n\nclass CustomizationArgSpecDict(TypedDict):\n    \"\"\"Dictionary representing the customization_arg_specs object.\"\"\"\n\n    name: str\n    description: str\n    # Here we use type Any because values in schema dictionary can be of\n    # type str, List, Dict and other types too.\n    schema: Dict[str, Any]\n    default_value: Union[str, int, List[str], Dict[str, str]]\n\n\nclass RteComponentDict(TypedDict):\n    \"\"\"Dictionary representing the RTE component's definition.\"\"\"\n\n    backend_id: str\n    category: str\n    description: str\n    frontend_id: str\n    tooltip: str\n    icon_data_url: str\n    is_complex: bool\n    requires_internet: bool\n    requires_fs: bool\n    is_block_element: bool\n    customization_arg_specs: List[CustomizationArgSpecDict]\n\n\nclass Registry:\n    \"\"\"Registry of all custom rich-text components.\"\"\"\n\n    _rte_components: Dict[str, RteComponentDict] = {}\n\n    @classmethod\n    def _refresh(cls) -> None:\n        \"\"\"Repopulate the registry.\"\"\"\n        cls._rte_components.clear()\n        package, filepath = os.path.split(\n            feconf.RTE_EXTENSIONS_DEFINITIONS_PATH)\n        cls._rte_components = constants.parse_json_from_ts(\n            constants.get_package_file_contents(package, filepath))\n\n    @classmethod\n    def get_all_rte_components(cls) -> Dict[str, RteComponentDict]:\n        \"\"\"Get a dictionary mapping RTE component IDs to their definitions.\"\"\"\n        if not cls._rte_components:\n            cls._refresh()\n        return cls._rte_components\n\n    @classmethod\n    def get_tag_list_with_attrs(cls) -> Dict[str, List[str]]:\n        \"\"\"Returns a dict of HTML tag names and attributes for RTE components.\n\n        The keys are tag names starting with 'oppia-noninteractive-', followed\n        by the hyphenated version of the name of the RTE component. The values\n        are lists of allowed attributes of the form\n        [PARAM_NAME]-with-[CUSTOMIZATION_ARG_NAME].\n        \"\"\"\n        # TODO(sll): Cache this computation and update it on each refresh.\n        # Better still, bring this into the build process so it doesn't have\n        # to be manually computed each time.\n        component_list = list(cls.get_all_rte_components().values())\n\n        component_tags = {}\n        for component_specs in component_list:\n            tag_name = 'oppia-noninteractive-%s' % (\n                utils.camelcase_to_hyphenated(component_specs['backend_id']))\n\n            component_tags[tag_name] = [\n                '%s-with-value' % ca_spec['name']\n                for ca_spec in component_specs['customization_arg_specs']]\n\n        return component_tags\n\n    @classmethod\n    def get_component_types_to_component_classes(\n        cls\n    ) -> Dict[str, Type[components.BaseRteComponent]]:\n        \"\"\"Get component classes mapping for component types.\n\n        Returns:\n            dict. A dict mapping from rte component types to rte component\n            classes.\n        \"\"\"\n        rte_path = [feconf.RTE_EXTENSIONS_DIR]\n\n        for loader, name, _ in pkgutil.iter_modules(path=rte_path):\n            if name == 'components':\n                fetched_module = loader.find_module(name)\n                # Ruling out the possibility of None for mypy type checking.\n                assert fetched_module is not None\n                module = fetched_module.load_module(name)\n                break\n\n        component_types_to_component_classes = {}\n        component_names = list(cls.get_all_rte_components().keys())\n        for component_name in component_names:\n            for name, obj in inspect.getmembers(module):\n                if inspect.isclass(obj) and name == component_name:\n                    component_types_to_component_classes[\n                        'oppia-noninteractive-%s' % component_name.lower()] = (\n                            obj)\n\n        return component_types_to_component_classes\n\n    @classmethod\n    def get_component_tag_names(\n        cls, key: str, expected_value: bool\n    ) -> List[str]:\n        \"\"\"Get a list of component tag names which have the expected\n        value of a key.\n\n        Args:\n            key: str. The key to be checked in component spec.\n            expected_value: bool. The expected value of the key to select\n                the components.\n\n        Returns:\n            list(str). A list of component tag names which have the expected\n            value of a key.\n        \"\"\"\n        rich_text_components_specs = cls.get_all_rte_components()\n        component_tag_names = []\n        for component_spec in rich_text_components_specs.values():\n            if component_spec.get(key) == expected_value:\n                component_tag_names.append(\n                    'oppia-noninteractive-%s' % component_spec['frontend_id'])\n        return component_tag_names\n\n    @classmethod\n    def get_inline_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of inline component tag names.\n\n        Returns:\n            list(str). A list of inline component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_block_element', False)\n\n    @classmethod\n    def get_block_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of block component tag names.\n\n        Returns:\n            list(str). A list of block component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_block_element', True)\n\n    @classmethod\n    def get_simple_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of simple component tag names.\n\n        Returns:\n            list(str). A list of simple component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_complex', False)\n\n    @classmethod\n    def get_complex_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of complex component tag names.\n\n        Returns:\n            list(str). A list of complex component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_complex', True)\n", "path": "core/domain/rte_component_registry.py"}], "after_files": [{"content": "# coding: utf-8\n#\n# Copyright 2014 The Oppia Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS-IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Registry for custom rich-text components.\"\"\"\n\nfrom __future__ import annotations\n\nimport inspect\nimport os\nimport pkgutil\n\nfrom core import constants\nfrom core import feconf\nfrom core import utils\n\nfrom typing import Any, Dict, List, Type, TypedDict, Union\n\nMYPY = False\nif MYPY: # pragma: no cover\n    # Here, we are importing 'components' from rich_text_components only\n    # for type checking.\n    from extensions.rich_text_components import components\n\n\nclass CustomizationArgSpecDict(TypedDict):\n    \"\"\"Dictionary representing the customization_arg_specs object.\"\"\"\n\n    name: str\n    description: str\n    # Here we use type Any because values in schema dictionary can be of\n    # type str, List, Dict and other types too.\n    schema: Dict[str, Any]\n    default_value_obtainable_from_highlight: bool\n    default_value: Union[str, int, List[str], Dict[str, str]]\n\n\nclass RteComponentDict(TypedDict):\n    \"\"\"Dictionary representing the RTE component's definition.\"\"\"\n\n    backend_id: str\n    category: str\n    description: str\n    frontend_id: str\n    tooltip: str\n    icon_data_url: str\n    is_complex: bool\n    requires_internet: bool\n    requires_fs: bool\n    is_block_element: bool\n    customization_arg_specs: List[CustomizationArgSpecDict]\n\n\nclass Registry:\n    \"\"\"Registry of all custom rich-text components.\"\"\"\n\n    _rte_components: Dict[str, RteComponentDict] = {}\n\n    @classmethod\n    def _refresh(cls) -> None:\n        \"\"\"Repopulate the registry.\"\"\"\n        cls._rte_components.clear()\n        package, filepath = os.path.split(\n            feconf.RTE_EXTENSIONS_DEFINITIONS_PATH)\n        cls._rte_components = constants.parse_json_from_ts(\n            constants.get_package_file_contents(package, filepath))\n\n    @classmethod\n    def get_all_rte_components(cls) -> Dict[str, RteComponentDict]:\n        \"\"\"Get a dictionary mapping RTE component IDs to their definitions.\"\"\"\n        if not cls._rte_components:\n            cls._refresh()\n        return cls._rte_components\n\n    @classmethod\n    def get_tag_list_with_attrs(cls) -> Dict[str, List[str]]:\n        \"\"\"Returns a dict of HTML tag names and attributes for RTE components.\n\n        The keys are tag names starting with 'oppia-noninteractive-', followed\n        by the hyphenated version of the name of the RTE component. The values\n        are lists of allowed attributes of the form\n        [PARAM_NAME]-with-[CUSTOMIZATION_ARG_NAME].\n        \"\"\"\n        # TODO(sll): Cache this computation and update it on each refresh.\n        # Better still, bring this into the build process so it doesn't have\n        # to be manually computed each time.\n        component_list = list(cls.get_all_rte_components().values())\n\n        component_tags = {}\n        for component_specs in component_list:\n            tag_name = 'oppia-noninteractive-%s' % (\n                utils.camelcase_to_hyphenated(component_specs['backend_id']))\n\n            component_tags[tag_name] = [\n                '%s-with-value' % ca_spec['name']\n                for ca_spec in component_specs['customization_arg_specs']]\n\n        return component_tags\n\n    @classmethod\n    def get_component_types_to_component_classes(\n        cls\n    ) -> Dict[str, Type[components.BaseRteComponent]]:\n        \"\"\"Get component classes mapping for component types.\n\n        Returns:\n            dict. A dict mapping from rte component types to rte component\n            classes.\n        \"\"\"\n        rte_path = [feconf.RTE_EXTENSIONS_DIR]\n\n        for loader, name, _ in pkgutil.iter_modules(path=rte_path):\n            if name == 'components':\n                fetched_module = loader.find_module(name)\n                # Ruling out the possibility of None for mypy type checking.\n                assert fetched_module is not None\n                module = fetched_module.load_module(name)\n                break\n\n        component_types_to_component_classes = {}\n        component_names = list(cls.get_all_rte_components().keys())\n        for component_name in component_names:\n            for name, obj in inspect.getmembers(module):\n                if inspect.isclass(obj) and name == component_name:\n                    component_types_to_component_classes[\n                        'oppia-noninteractive-%s' % component_name.lower()] = (\n                            obj)\n\n        return component_types_to_component_classes\n\n    @classmethod\n    def get_component_tag_names(\n        cls, key: str, expected_value: bool\n    ) -> List[str]:\n        \"\"\"Get a list of component tag names which have the expected\n        value of a key.\n\n        Args:\n            key: str. The key to be checked in component spec.\n            expected_value: bool. The expected value of the key to select\n                the components.\n\n        Returns:\n            list(str). A list of component tag names which have the expected\n            value of a key.\n        \"\"\"\n        rich_text_components_specs = cls.get_all_rte_components()\n        component_tag_names = []\n        for component_spec in rich_text_components_specs.values():\n            if component_spec.get(key) == expected_value:\n                component_tag_names.append(\n                    'oppia-noninteractive-%s' % component_spec['frontend_id'])\n        return component_tag_names\n\n    @classmethod\n    def get_inline_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of inline component tag names.\n\n        Returns:\n            list(str). A list of inline component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_block_element', False)\n\n    @classmethod\n    def get_block_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of block component tag names.\n\n        Returns:\n            list(str). A list of block component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_block_element', True)\n\n    @classmethod\n    def get_simple_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of simple component tag names.\n\n        Returns:\n            list(str). A list of simple component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_complex', False)\n\n    @classmethod\n    def get_complex_component_tag_names(cls) -> List[str]:\n        \"\"\"Get a list of complex component tag names.\n\n        Returns:\n            list(str). A list of complex component tag names.\n        \"\"\"\n        return cls.get_component_tag_names('is_complex', True)\n", "path": "core/domain/rte_component_registry.py"}]}