Issue #3612219: Add a reusable search-text extractor and an optional Search API processor for indexing custom element text
Adds a reusable search-text extractor plus an optional Search API processor, so the body of a decoupled entity becomes searchable. See [#3612219] for the full rationale.
What this adds
CustomElementSearchTextExtractor(servicecustom_elements.search_text_extractor): walks aCustomElementthroughgetAttributes()andgetSortedSlotsByName()and returns the human-readable text. String props are indexed unless the key is technical (URLs, paths, colours, dimensions, identifiers, structural tokens); slots are recursed, including plain-HTML markup slots; content nested inside attribute values (the paragraph / component-list shape a generator produces) is recursed too. Subtrees flaggedno-search-indexare pruned.custom_elements_fulltextSearch API processor: a thin caller exposing ace_fulltextproperty that can replacerendered_item.
No new dependency
custom_elements.info.yml is unchanged. A Search API processor plugin is only discovered and instantiated by Search API's own plugin manager, so on sites without search_api the class is never autoloaded. The processor's kernel test declares search_api in its own $modules list, keeping the dependency test-only.
Tests
Kernel coverage for both classes: string props kept and technical attributes dropped, markup and plain-HTML slots indexed, nested attribute content indexed, the paragraphs-prop shape indexed, no-search-index subtrees pruned, renderless-container transparent, and the processor delegating to the extractor.
The patch on the issue was prepared against 3.4.1 and green there (7 tests, 43 assertions). This branch is rebased onto current 3.x, where the render-converter refactor from [#3534177] has since landed; only custom_elements.services.yml needed adjusting, and 3.x's version of that file is preserved with the new service added to it. Relying on the MR pipeline to confirm against 3.x.
Drafted with the assistance of AI (Claude Code / Opus 4.8).