prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Allow TinyMCE to be used in inline-mode
  Inline-mode of TinyMCE (https://www.tiny.cloud/docs/demo/inline) is nice among other reasons because the edited text looks exactly the way as the saved result. 
  
  To enable it you could simply set `{"inline": "true"}` as the value in the field "Other settings" of the TinyMCE controlpanel. That is enough to trigger it. 
  
  But that fails with `Could not initialize inline editor on invalid inline target element` since the html-tag that renders the TinyMCE is a `<textarea>`. See https://www.tiny.cloud/blog/tinymce-inline-option-not-working for details about that constraint.
  
  The `<textarea>` thing is defined in `plone.app.z3cform.widget.RichTextWidget` which has `TextareaWidget` as `_base`. In `render_input_mode` of the widget it is possible to conditionally render a different html element like `div` around the text. But then fallback to textarea no longer works and saving also fails and and and... 
  
  So it seems that using inline-mode in not straightforward. The question is do we like that option enough to do the required work?
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `Products/CMFPlone/patterns/settings.py`
  Content:
  ```
  1 from Acquisition import aq_inner
  2 from Acquisition import aq_parent
  3 from borg.localrole.interfaces import IFactoryTempFolder
  4 from plone.app.content.browser.interfaces import IFolderContentsView
  5 from plone.app.widgets.utils import get_relateditems_options
  6 from plone.app.z3cform.utils import call_callables
  7 from plone.registry.interfaces import IRegistry
  8 from plone.uuid.interfaces import IUUID
  9 from Products.CMFCore.interfaces._content import IFolderish
  10 from plone.base.interfaces import ILinkSchema
  11 from plone.base.interfaces import IPatternsSettings
  12 from plone.base.interfaces import IPloneSiteRoot
  13 from Products.CMFPlone.patterns.tinymce import TinyMCESettingsGenerator
  14 from Products.CMFPlone.utils import get_portal
  15 from zope.component import getUtility
  16 from zope.i18n import translate
  17 from zope.interface import implementer
  18 from zope.schema.interfaces import IVocabularyFactory
  19 
  20 import json
  21 
  22 
  23 @implementer(IPatternsSettings)
  24 class PatternSettingsAdapter:
  25     """
  26     Provides default plone settings relevant for patterns.
  27     """
  28 
  29     def __init__(self, context, request, field):
  30         self.request = request
  31         self.context = context
  32         self.field = field
  33 
  34     def __call__(self):
  35         data = {}
  36         data.update(self.mark_special_links())
  37         data.update(self.structure_updater())
  38         return data
  39 
  40     def structure_updater(self):
  41         """Generate the options for the structure updater pattern.
  42         If we're not in folder contents view, do not expose these options.
  43         """
  44         data = {}
  45         view = self.request.get("PUBLISHED", None)
  46         if IFolderContentsView.providedBy(view):
  47             data = {
  48                 "data-pat-structureupdater": json.dumps(
  49                     {
  50                         "titleSelector": ".documentFirstHeading",
  51                         "descriptionSelector": ".documentDescription",
  52                     }
  53                 )
  54             }
  55         return data
  56 
  57     def mark_special_links(self):
  58         result = {}
  59 
  60         registry = getUtility(IRegistry)
  61         settings = registry.forInterface(ILinkSchema, prefix="plone", check=False)
  62 
  63         msl = settings.mark_special_links
  64         elonw = settings.external_links_open_new_window
  65         if msl or elonw:
  66             result = {
  67                 "data-pat-markspeciallinks": json.dumps(
  68                     {"external_links_open_new_window": elonw, "mark_special_links": msl}
  69                 )
  70             }
  71         return result
  72 
  73     @property
  74     def image_scales(self):
  75         factory = getUtility(IVocabularyFactory, "plone.app.vocabularies.ImagesScales")
  76         vocabulary = factory(self.context)
  77         ret = [{"title": translate(it.title), "value": it.value} for it in vocabulary]
  78         ret = sorted(ret, key=lambda it: it["title"])
  79         return json.dumps(ret)
  80 
  81     def tinymce(self):
  82         """
  83         data-pat-tinymce : JSON.stringify({
  84             relatedItems: {
  85               vocabularyUrl: config.portal_url +
  86                 '/@@getVocabulary?name=plone.app.vocabularies.Catalog'
  87             },
  88             tiny: config,
  89             prependToUrl: 'resolveuid/',
  90             linkAttribute: 'UID',
  91             prependToScalePart: '/@@images/image/'
  92           })
  93         """
  94 
  95         generator = TinyMCESettingsGenerator(self.context, self.request)
  96         settings = generator.settings
  97         folder = aq_inner(self.context)
  98 
  99         # Test if we are currently creating an Archetype object
  100         if IFactoryTempFolder.providedBy(aq_parent(folder)):
  101             folder = aq_parent(aq_parent(aq_parent(folder)))
  102         if not IFolderish.providedBy(folder):
  103             folder = aq_parent(folder)
  104 
  105         if IPloneSiteRoot.providedBy(folder):
  106             initial = None
  107         else:
  108             initial = IUUID(folder, None)
  109 
  110         portal = get_portal()
  111         portal_url = portal.absolute_url()
  112         current_path = folder.absolute_url()[len(portal_url) :]
  113 
  114         image_types = settings.image_objects or []
  115 
  116         server_url = self.request.get("SERVER_URL", "")
  117         site_path = portal_url[len(server_url) :]
  118 
  119         related_items_config = get_relateditems_options(
  120             context=self.context,
  121             value=None,
  122             separator=";",
  123             vocabulary_name="plone.app.vocabularies.Catalog",
  124             vocabulary_view="@@getVocabulary",
  125             field_name=None,
  126         )
  127         related_items_config = call_callables(related_items_config, self.context)
  128 
  129         configuration = {
  130             "base_url": self.context.absolute_url(),
  131             "imageTypes": image_types,
  132             "imageScales": self.image_scales,
  133             "linkAttribute": "UID",
  134             # This is for loading the languages on tinymce
  135             "loadingBaseUrl": "{}/++plone++static/components/tinymce-builded/"
  136             "js/tinymce".format(portal_url),
  137             "relatedItems": related_items_config,
  138             "prependToScalePart": "/@@images/image/",
  139             "prependToUrl": "{}/resolveuid/".format(site_path.rstrip("/")),
  140             "tiny": generator.get_tiny_config(),
  141             "upload": {
  142                 "baseUrl": portal_url,
  143                 "currentPath": current_path,
  144                 "initialFolder": initial,
  145                 "maxFiles": 1,
  146                 "relativePath": "@@fileUpload",
  147                 "showTitle": False,
  148                 "uploadMultiple": False,
  149             },
  150         }
  151         return {"data-pat-tinymce": json.dumps(configuration)}
  152
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/Products/CMFPlone/patterns/settings.py b/Products/CMFPlone/patterns/settings.py
  --- a/Products/CMFPlone/patterns/settings.py
  +++ b/Products/CMFPlone/patterns/settings.py
  @@ -137,6 +137,7 @@
               "relatedItems": related_items_config,
               "prependToScalePart": "/@@images/image/",
               "prependToUrl": "{}/resolveuid/".format(site_path.rstrip("/")),
  +            "inline": settings.inline,
               "tiny": generator.get_tiny_config(),
               "upload": {
                   "baseUrl": portal_url,
  
verification_info: {"golden_diff": "diff --git a/Products/CMFPlone/patterns/settings.py b/Products/CMFPlone/patterns/settings.py\n--- a/Products/CMFPlone/patterns/settings.py\n+++ b/Products/CMFPlone/patterns/settings.py\n@@ -137,6 +137,7 @@\n             \"relatedItems\": related_items_config,\n             \"prependToScalePart\": \"/@@images/image/\",\n             \"prependToUrl\": \"{}/resolveuid/\".format(site_path.rstrip(\"/\")),\n+            \"inline\": settings.inline,\n             \"tiny\": generator.get_tiny_config(),\n             \"upload\": {\n                 \"baseUrl\": portal_url,\n", "issue": "Allow TinyMCE to be used in inline-mode\nInline-mode of TinyMCE (https://www.tiny.cloud/docs/demo/inline) is nice among other reasons because the edited text looks exactly the way as the saved result. \r\n\r\nTo enable it you could simply set `{\"inline\": \"true\"}` as the value in the field \"Other settings\" of the TinyMCE controlpanel. That is enough to trigger it. \r\n\r\nBut that fails with `Could not initialize inline editor on invalid inline target element` since the html-tag that renders the TinyMCE is a `<textarea>`. See https://www.tiny.cloud/blog/tinymce-inline-option-not-working for details about that constraint.\r\n\r\nThe `<textarea>` thing is defined in `plone.app.z3cform.widget.RichTextWidget` which has `TextareaWidget` as `_base`. In `render_input_mode` of the widget it is possible to conditionally render a different html element like `div` around the text. But then fallback to textarea no longer works and saving also fails and and and... \r\n\r\nSo it seems that using inline-mode in not straightforward. The question is do we like that option enough to do the required work?\r\n\n", "before_files": [{"content": "from Acquisition import aq_inner\nfrom Acquisition import aq_parent\nfrom borg.localrole.interfaces import IFactoryTempFolder\nfrom plone.app.content.browser.interfaces import IFolderContentsView\nfrom plone.app.widgets.utils import get_relateditems_options\nfrom plone.app.z3cform.utils import call_callables\nfrom plone.registry.interfaces import IRegistry\nfrom plone.uuid.interfaces import IUUID\nfrom Products.CMFCore.interfaces._content import IFolderish\nfrom plone.base.interfaces import ILinkSchema\nfrom plone.base.interfaces import IPatternsSettings\nfrom plone.base.interfaces import IPloneSiteRoot\nfrom Products.CMFPlone.patterns.tinymce import TinyMCESettingsGenerator\nfrom Products.CMFPlone.utils import get_portal\nfrom zope.component import getUtility\nfrom zope.i18n import translate\nfrom zope.interface import implementer\nfrom zope.schema.interfaces import IVocabularyFactory\n\nimport json\n\n\n@implementer(IPatternsSettings)\nclass PatternSettingsAdapter:\n    \"\"\"\n    Provides default plone settings relevant for patterns.\n    \"\"\"\n\n    def __init__(self, context, request, field):\n        self.request = request\n        self.context = context\n        self.field = field\n\n    def __call__(self):\n        data = {}\n        data.update(self.mark_special_links())\n        data.update(self.structure_updater())\n        return data\n\n    def structure_updater(self):\n        \"\"\"Generate the options for the structure updater pattern.\n        If we're not in folder contents view, do not expose these options.\n        \"\"\"\n        data = {}\n        view = self.request.get(\"PUBLISHED\", None)\n        if IFolderContentsView.providedBy(view):\n            data = {\n                \"data-pat-structureupdater\": json.dumps(\n                    {\n                        \"titleSelector\": \".documentFirstHeading\",\n                        \"descriptionSelector\": \".documentDescription\",\n                    }\n                )\n            }\n        return data\n\n    def mark_special_links(self):\n        result = {}\n\n        registry = getUtility(IRegistry)\n        settings = registry.forInterface(ILinkSchema, prefix=\"plone\", check=False)\n\n        msl = settings.mark_special_links\n        elonw = settings.external_links_open_new_window\n        if msl or elonw:\n            result = {\n                \"data-pat-markspeciallinks\": json.dumps(\n                    {\"external_links_open_new_window\": elonw, \"mark_special_links\": msl}\n                )\n            }\n        return result\n\n    @property\n    def image_scales(self):\n        factory = getUtility(IVocabularyFactory, \"plone.app.vocabularies.ImagesScales\")\n        vocabulary = factory(self.context)\n        ret = [{\"title\": translate(it.title), \"value\": it.value} for it in vocabulary]\n        ret = sorted(ret, key=lambda it: it[\"title\"])\n        return json.dumps(ret)\n\n    def tinymce(self):\n        \"\"\"\n        data-pat-tinymce : JSON.stringify({\n            relatedItems: {\n              vocabularyUrl: config.portal_url +\n                '/@@getVocabulary?name=plone.app.vocabularies.Catalog'\n            },\n            tiny: config,\n            prependToUrl: 'resolveuid/',\n            linkAttribute: 'UID',\n            prependToScalePart: '/@@images/image/'\n          })\n        \"\"\"\n\n        generator = TinyMCESettingsGenerator(self.context, self.request)\n        settings = generator.settings\n        folder = aq_inner(self.context)\n\n        # Test if we are currently creating an Archetype object\n        if IFactoryTempFolder.providedBy(aq_parent(folder)):\n            folder = aq_parent(aq_parent(aq_parent(folder)))\n        if not IFolderish.providedBy(folder):\n            folder = aq_parent(folder)\n\n        if IPloneSiteRoot.providedBy(folder):\n            initial = None\n        else:\n            initial = IUUID(folder, None)\n\n        portal = get_portal()\n        portal_url = portal.absolute_url()\n        current_path = folder.absolute_url()[len(portal_url) :]\n\n        image_types = settings.image_objects or []\n\n        server_url = self.request.get(\"SERVER_URL\", \"\")\n        site_path = portal_url[len(server_url) :]\n\n        related_items_config = get_relateditems_options(\n            context=self.context,\n            value=None,\n            separator=\";\",\n            vocabulary_name=\"plone.app.vocabularies.Catalog\",\n            vocabulary_view=\"@@getVocabulary\",\n            field_name=None,\n        )\n        related_items_config = call_callables(related_items_config, self.context)\n\n        configuration = {\n            \"base_url\": self.context.absolute_url(),\n            \"imageTypes\": image_types,\n            \"imageScales\": self.image_scales,\n            \"linkAttribute\": \"UID\",\n            # This is for loading the languages on tinymce\n            \"loadingBaseUrl\": \"{}/++plone++static/components/tinymce-builded/\"\n            \"js/tinymce\".format(portal_url),\n            \"relatedItems\": related_items_config,\n            \"prependToScalePart\": \"/@@images/image/\",\n            \"prependToUrl\": \"{}/resolveuid/\".format(site_path.rstrip(\"/\")),\n            \"tiny\": generator.get_tiny_config(),\n            \"upload\": {\n                \"baseUrl\": portal_url,\n                \"currentPath\": current_path,\n                \"initialFolder\": initial,\n                \"maxFiles\": 1,\n                \"relativePath\": \"@@fileUpload\",\n                \"showTitle\": False,\n                \"uploadMultiple\": False,\n            },\n        }\n        return {\"data-pat-tinymce\": json.dumps(configuration)}\n", "path": "Products/CMFPlone/patterns/settings.py"}], "after_files": [{"content": "from Acquisition import aq_inner\nfrom Acquisition import aq_parent\nfrom borg.localrole.interfaces import IFactoryTempFolder\nfrom plone.app.content.browser.interfaces import IFolderContentsView\nfrom plone.app.widgets.utils import get_relateditems_options\nfrom plone.app.z3cform.utils import call_callables\nfrom plone.registry.interfaces import IRegistry\nfrom plone.uuid.interfaces import IUUID\nfrom Products.CMFCore.interfaces._content import IFolderish\nfrom plone.base.interfaces import ILinkSchema\nfrom plone.base.interfaces import IPatternsSettings\nfrom plone.base.interfaces import IPloneSiteRoot\nfrom Products.CMFPlone.patterns.tinymce import TinyMCESettingsGenerator\nfrom Products.CMFPlone.utils import get_portal\nfrom zope.component import getUtility\nfrom zope.i18n import translate\nfrom zope.interface import implementer\nfrom zope.schema.interfaces import IVocabularyFactory\n\nimport json\n\n\n@implementer(IPatternsSettings)\nclass PatternSettingsAdapter:\n    \"\"\"\n    Provides default plone settings relevant for patterns.\n    \"\"\"\n\n    def __init__(self, context, request, field):\n        self.request = request\n        self.context = context\n        self.field = field\n\n    def __call__(self):\n        data = {}\n        data.update(self.mark_special_links())\n        data.update(self.structure_updater())\n        return data\n\n    def structure_updater(self):\n        \"\"\"Generate the options for the structure updater pattern.\n        If we're not in folder contents view, do not expose these options.\n        \"\"\"\n        data = {}\n        view = self.request.get(\"PUBLISHED\", None)\n        if IFolderContentsView.providedBy(view):\n            data = {\n                \"data-pat-structureupdater\": json.dumps(\n                    {\n                        \"titleSelector\": \".documentFirstHeading\",\n                        \"descriptionSelector\": \".documentDescription\",\n                    }\n                )\n            }\n        return data\n\n    def mark_special_links(self):\n        result = {}\n\n        registry = getUtility(IRegistry)\n        settings = registry.forInterface(ILinkSchema, prefix=\"plone\", check=False)\n\n        msl = settings.mark_special_links\n        elonw = settings.external_links_open_new_window\n        if msl or elonw:\n            result = {\n                \"data-pat-markspeciallinks\": json.dumps(\n                    {\"external_links_open_new_window\": elonw, \"mark_special_links\": msl}\n                )\n            }\n        return result\n\n    @property\n    def image_scales(self):\n        factory = getUtility(IVocabularyFactory, \"plone.app.vocabularies.ImagesScales\")\n        vocabulary = factory(self.context)\n        ret = [{\"title\": translate(it.title), \"value\": it.value} for it in vocabulary]\n        ret = sorted(ret, key=lambda it: it[\"title\"])\n        return json.dumps(ret)\n\n    def tinymce(self):\n        \"\"\"\n        data-pat-tinymce : JSON.stringify({\n            relatedItems: {\n              vocabularyUrl: config.portal_url +\n                '/@@getVocabulary?name=plone.app.vocabularies.Catalog'\n            },\n            tiny: config,\n            prependToUrl: 'resolveuid/',\n            linkAttribute: 'UID',\n            prependToScalePart: '/@@images/image/'\n          })\n        \"\"\"\n\n        generator = TinyMCESettingsGenerator(self.context, self.request)\n        settings = generator.settings\n        folder = aq_inner(self.context)\n\n        # Test if we are currently creating an Archetype object\n        if IFactoryTempFolder.providedBy(aq_parent(folder)):\n            folder = aq_parent(aq_parent(aq_parent(folder)))\n        if not IFolderish.providedBy(folder):\n            folder = aq_parent(folder)\n\n        if IPloneSiteRoot.providedBy(folder):\n            initial = None\n        else:\n            initial = IUUID(folder, None)\n\n        portal = get_portal()\n        portal_url = portal.absolute_url()\n        current_path = folder.absolute_url()[len(portal_url) :]\n\n        image_types = settings.image_objects or []\n\n        server_url = self.request.get(\"SERVER_URL\", \"\")\n        site_path = portal_url[len(server_url) :]\n\n        related_items_config = get_relateditems_options(\n            context=self.context,\n            value=None,\n            separator=\";\",\n            vocabulary_name=\"plone.app.vocabularies.Catalog\",\n            vocabulary_view=\"@@getVocabulary\",\n            field_name=None,\n        )\n        related_items_config = call_callables(related_items_config, self.context)\n\n        configuration = {\n            \"base_url\": self.context.absolute_url(),\n            \"imageTypes\": image_types,\n            \"imageScales\": self.image_scales,\n            \"linkAttribute\": \"UID\",\n            # This is for loading the languages on tinymce\n            \"loadingBaseUrl\": \"{}/++plone++static/components/tinymce-builded/\"\n            \"js/tinymce\".format(portal_url),\n            \"relatedItems\": related_items_config,\n            \"prependToScalePart\": \"/@@images/image/\",\n            \"prependToUrl\": \"{}/resolveuid/\".format(site_path.rstrip(\"/\")),\n            \"inline\": settings.inline,\n            \"tiny\": generator.get_tiny_config(),\n            \"upload\": {\n                \"baseUrl\": portal_url,\n                \"currentPath\": current_path,\n                \"initialFolder\": initial,\n                \"maxFiles\": 1,\n                \"relativePath\": \"@@fileUpload\",\n                \"showTitle\": False,\n                \"uploadMultiple\": False,\n            },\n        }\n        return {\"data-pat-tinymce\": json.dumps(configuration)}\n", "path": "Products/CMFPlone/patterns/settings.py"}]}