You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CK Editor(RTE)中将链接锚点从#cuid改为#title-of-contentelement?

Hey there! Great question—you can absolutely achieve this using RTE configuration, typolink processors, or TYPO3 hooks depending on your use case. Let's break down each approach with actionable steps:


1. RTE (CKEditor) Configuration Adjustment

If you want to fix this at the source—so users generate title-based anchors right when inserting them in CKEditor—customizing the RTE is the best approach. We'll build a tiny custom CKEditor plugin to replace the default anchor behavior:

  • Step 1: Create the custom anchor plugin
    In your extension, add a JavaScript file at Resources/Public/JavaScript/CustomAnchor.js with this logic:

    CKEDITOR.plugins.add('customanchor', {
      init: function(editor) {
        editor.addCommand('customanchor', {
          exec: function(editor) {
            var selectedText = editor.getSelection().getSelectedText();
            // Convert selected text to a clean slug (lowercase, hyphens instead of spaces)
            var anchorSlug = selectedText.toLowerCase()
              .replace(/\s+/g, '-')
              .replace(/[^a-z0-9-]/g, '');
            
            // Insert the anchor with our slug instead of a cuid
            editor.insertHtml('<a id="' + anchorSlug + '"></a>');
          }
        });
    
        // Replace the default Anchor button with our custom command
        editor.ui.addButton('Anchor', {
          label: 'Insert Anchor',
          command: 'customanchor',
          toolbar: 'links'
        });
      }
    });
    
  • Step 2: Register the plugin in your RTE config
    Update your RTE YAML config (e.g., Configuration/RTE/Default.yaml) to load the custom plugin and disable the default anchor plugin:

    editor:
      externalPlugins:
        customanchor: '/typo3conf/ext/your_extension/Resources/Public/JavaScript/CustomAnchor.js'
      config:
        removePlugins: 'anchor'
        extraPlugins: 'customanchor'
    

    Note: Replace your_extension with your actual extension key.


If you need to fix existing anchors (or anchors generated via TYPO3's internal link system), a typolink processor will modify the anchor during link rendering. This works for all links generated via typolink (like content element links):

  • Step 1: Register the processor in TypoScript
    Add this to your extension's Configuration/TypoScript/setup.typoscript:

    typolink.processors {
      10 = Vendor\YourExtension\LinkProcessing\CustomAnchorProcessor
    }
    
  • Step 2: Build the processor class
    Create Classes/LinkProcessing/CustomAnchorProcessor.php with this logic (we'll map cuids to content element titles and convert them to slugs):

    <?php
    namespace Vendor\YourExtension\LinkProcessing;
    
    use TYPO3\CMS\Core\LinkHandling\LinkProcessorInterface;
    use TYPO3\CMS\Core\Utility\GeneralUtility;
    use TYPO3\CMS\Core\Database\ConnectionPool;
    
    class CustomAnchorProcessor implements LinkProcessorInterface
    {
      public function process(array $linkParameters, array $configuration): array
      {
        // Check if the fragment is a cuid (UUID format)
        if (isset($linkParameters['fragment']) && preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', $linkParameters['fragment'])) {
          $cuid = $linkParameters['fragment'];
          
          // Fetch the content element's header using the cuid (adjust the table/field if needed)
          $contentElement = GeneralUtility::makeInstance(ConnectionPool::class)
            ->getConnectionForTable('tt_content')
            ->select(['header'], 'tt_content', ['uid' => $cuid])
            ->fetchAssociative();
    
          if ($contentElement) {
            // Convert header to a clean slug
            $slug = strtolower(preg_replace('/\s+/', '-', preg_replace('/[^a-zA-Z0-9\s]/', '', $contentElement['header'])));
            $linkParameters['fragment'] = $slug;
          }
        }
        return $linkParameters;
      }
    }
    

3. TYPO3 Hooks for Global Replacement

Hooks give you maximum flexibility—you can modify anchors when content is saved, or when it's rendered. Here are two common use cases:

Option A: Modify Anchors When Content is Saved

This ensures anchors are updated immediately when a content element is created/edited:

  • Register the hook in Configuration/TCA/Overrides/tt_content.php:
    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['your_extension'] = \Vendor\YourExtension\Hooks\ContentElementSaveHook::class;
    
  • Create the hook class at Classes/Hooks/ContentElementSaveHook.php:
    <?php
    namespace Vendor\YourExtension\Hooks;
    
    use TYPO3\CMS\Core\DataHandling\DataHandler;
    use TYPO3\CMS\Core\Utility\GeneralUtility;
    use TYPO3\CMS\Core\Database\ConnectionPool;
    
    class ContentElementSaveHook
    {
      public function processDatamap_postProcessFieldArray($status, $table, $id, &$fieldArray, DataHandler &$pObj)
      {
        if ($table === 'tt_content' && isset($fieldArray['header'])) {
          $header = $fieldArray['header'];
          $slug = strtolower(preg_replace('/\s+/', '-', preg_replace('/[^a-zA-Z0-9\s]/', '', $header)));
          
          // Replace any cuid anchors in the bodytext with our slug
          if (isset($fieldArray['bodytext'])) {
            // If it's a new record, $id will be a temporary string—we'll skip that for now
            if (is_numeric($id)) {
              $fieldArray['bodytext'] = str_replace('#' . $id, '#' . $slug, $fieldArray['bodytext']);
            }
          }
        }
      }
    }
    

Option B: Replace Anchors During RTE Rendering

This modifies anchors right before content is displayed on the frontend:

  • Register the hook in TypoScript:
    lib.parseFunc_RTE {
      hooks {
        postProcess = Vendor\YourExtension\Hooks\RteRenderHook->postProcess
      }
    }
    
  • Create the hook class at Classes/Hooks/RteRenderHook.php:
    <?php
    namespace Vendor\YourExtension\Hooks;
    
    use TYPO3\CMS\Core\Utility\GeneralUtility;
    use TYPO3\CMS\Core\Database\ConnectionPool;
    
    class RteRenderHook
    {
      public function postProcess(&$value, $conf, $obj)
      {
        // Match all #cuid anchors and replace them with title slugs
        $value = preg_replace_callback('/#([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/', function($matches) {
          $cuid = $matches[1];
          $contentElement = GeneralUtility::makeInstance(ConnectionPool::class)
            ->getConnectionForTable('tt_content')
            ->select(['header'], 'tt_content', ['uid' => $cuid])
            ->fetchAssociative();
    
          if ($contentElement) {
            $slug = strtolower(preg_replace('/\s+/', '-', preg_replace('/[^a-zA-Z0-9\s]/', '', $contentElement['header'])));
            return '#' . $slug;
          }
          return $matches[0]; // Fallback to original if no content element found
        }, $value);
      }
    }
    

Which Approach Should You Use?

  • RTE Configuration: Best for preventing cuid anchors from being inserted in the first place (user-facing fix).
  • Typolink Processor: Ideal for batch-fixing existing internal links generated via TYPO3's link system.
  • Hooks: Most flexible—use when you need to modify anchors during content save or rendering for edge cases.

内容的提问来源于stack exchange,提问作者Markus Dübbert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:33:30