-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 39c45bd
Showing
24 changed files
with
1,235 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
namespace Paessler\AnchorLink; | ||
|
||
use Neos\ContentRepository\Domain\Model\NodeInterface; | ||
|
||
interface AnchorLinkResolverInterface | ||
{ | ||
/** | ||
* Return an array of options for the anchor link selectbox: | ||
* | ||
* [ | ||
* [ | ||
* 'icon' => 'icon-foo', // optional | ||
* 'group' => 'first', // optional | ||
* 'value' => 'bar', | ||
* 'label' => 'Bar', | ||
* ], | ||
* [ | ||
* 'icon' => 'icon-foo', // optional | ||
* 'group' => 'second', | ||
* 'value' => 'baz', | ||
* 'label' => 'Baz', | ||
* ] | ||
* ]; | ||
* | ||
* @param NodeInterface $node Currently focused node | ||
* @param string $link Current link target (for example "node://<some-identifier>" or "https://www.external.url") | ||
* @param string $searchTerm Search term (term that has been entered in the "Choose link anchor" search field, defaults to an empty string) | ||
* @return array | ||
*/ | ||
public function resolve(NodeInterface $node, string $link, string $searchTerm): array; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
<?php | ||
|
||
namespace Paessler\AnchorLink; | ||
|
||
use Neos\Eel\Exception as EelException; | ||
use Neos\Flow\Annotations as Flow; | ||
use Neos\ContentRepository\Domain\Model\NodeInterface; | ||
use Neos\Flow\ObjectManagement\DependencyInjection\DependencyProxy; | ||
use Neos\Neos\Service\LinkingService; | ||
use Neos\Eel\EelEvaluatorInterface; | ||
use Neos\Eel\Utility; | ||
use Neos\Eel\FlowQuery\FlowQuery; | ||
use Neos\Neos\Domain\Service\NodeSearchService; | ||
|
||
/** | ||
* Create link anchors based on all matching nodes within the target link node | ||
* | ||
* @see Paessler:AnchorLink:* Settings | ||
*/ | ||
class ContentNodeAnchorLinkResolver implements AnchorLinkResolverInterface | ||
{ | ||
/** | ||
* @Flow\Inject | ||
* @var NodeSearchService | ||
*/ | ||
protected $nodeSearchService; | ||
|
||
/** | ||
* @Flow\Inject | ||
* @var EelEvaluatorInterface | ||
*/ | ||
protected $eelEvaluator; | ||
|
||
/** | ||
* @Flow\InjectConfiguration("eelContext") | ||
* @var array | ||
*/ | ||
protected $contextConfiguration; | ||
|
||
/** | ||
* @Flow\InjectConfiguration(path="contentNodeType") | ||
* @var string | ||
*/ | ||
protected $contentNodeType; | ||
|
||
/** | ||
* @Flow\InjectConfiguration(path="anchor") | ||
* @var string | ||
*/ | ||
protected $anchor; | ||
|
||
/** | ||
* @Flow\InjectConfiguration(path="label") | ||
* @var string | ||
*/ | ||
protected $label; | ||
|
||
/** | ||
* @Flow\InjectConfiguration(path="group") | ||
* @var string | ||
*/ | ||
protected $group; | ||
|
||
/** | ||
* @Flow\InjectConfiguration(path="icon") | ||
* @var string | ||
*/ | ||
protected $icon; | ||
|
||
/** | ||
* @inheritDoc | ||
* @throws EelException | ||
*/ | ||
public function resolve(NodeInterface $node, string $link, string $searchTerm): array | ||
{ | ||
$context = $node->getContext(); | ||
$targetNode = null; | ||
|
||
if ((preg_match(LinkingService::PATTERN_SUPPORTED_URIS, $link, $matches) === 1) && $matches[1] === 'node') { | ||
$targetNode = $context->getNodeByIdentifier($matches[2]) ?? $node; | ||
} | ||
if ($targetNode === null) { | ||
return []; | ||
} | ||
|
||
if ($searchTerm !== '') { | ||
$nodes = $this->nodeSearchService->findByProperties($searchTerm, [$this->contentNodeType], $context, $targetNode->getPrimaryChildNode()); | ||
} else { | ||
$q = new FlowQuery([$targetNode]); | ||
/** @noinspection PhpUndefinedMethodInspection */ | ||
$nodes = $q->children('[instanceof Neos.Neos:ContentCollection]')->find('[instanceof ' . $this->contentNodeType . ']')->get(); | ||
} | ||
|
||
if ($this->eelEvaluator instanceof DependencyProxy) { | ||
$this->eelEvaluator->_activateDependency(); | ||
} | ||
|
||
return array_values(array_map(function (NodeInterface $node) { | ||
$anchor = (string)Utility::evaluateEelExpression($this->anchor, $this->eelEvaluator, ['node' => $node], $this->contextConfiguration); | ||
$label = (string)Utility::evaluateEelExpression($this->label, $this->eelEvaluator, ['node' => $node], $this->contextConfiguration); | ||
$group = (string)Utility::evaluateEelExpression($this->group, $this->eelEvaluator, ['node' => $node], $this->contextConfiguration); | ||
$icon = (string)Utility::evaluateEelExpression($this->icon, $this->eelEvaluator, ['node' => $node], $this->contextConfiguration); | ||
return [ | ||
'icon' => $icon, | ||
'group' => $group, | ||
'value' => $anchor, | ||
'label' => $label, | ||
]; | ||
}, $nodes)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
namespace Paessler\AnchorLink\Controller; | ||
|
||
use Neos\Flow\Annotations as Flow; | ||
use Neos\Flow\Mvc\View\JsonView; | ||
use Neos\Flow\Mvc\Controller\ActionController; | ||
use Neos\ContentRepository\Domain\Model\NodeInterface; | ||
use Paessler\AnchorLink\AnchorLinkResolverInterface; | ||
|
||
class AnchorLinkController extends ActionController | ||
{ | ||
/** | ||
* @var AnchorLinkResolverInterface | ||
* @Flow\Inject | ||
*/ | ||
protected AnchorLinkResolverInterface $resolver; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $viewFormatToObjectNameMap = array( | ||
'json' => JsonView::class | ||
); | ||
|
||
/** | ||
* @param NodeInterface $node | ||
* @param string $link | ||
* @param string $searchTerm | ||
* @return void | ||
*/ | ||
public function resolveAnchorsAction(NodeInterface $node, string $link, string $searchTerm): void | ||
{ | ||
$options = $this->resolver->resolve($node, $link, $searchTerm); | ||
$this->view->assign('value', $options); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
'Paessler\AnchorLink\Controller\AnchorLinkController': | ||
properties: | ||
resolver: | ||
object: Paessler\AnchorLink\ContentNodeAnchorLinkResolver |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
privilegeTargets: | ||
Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege: | ||
"Paessler.AnchorLink:Backend": | ||
matcher: 'method(Paessler\AnchorLink\Controller\AnchorLinkController->(.*)Action())' | ||
|
||
roles: | ||
"Neos.Neos:AbstractEditor": | ||
privileges: | ||
- privilegeTarget: "Paessler.AnchorLink:Backend" | ||
permission: GRANT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
- name: "Paessler.AnchorLink options resolver route" | ||
uriPattern: "link-resolver/{@action}" | ||
defaults: | ||
"@package": "Paessler.AnchorLink" | ||
"@controller": "AnchorLink" | ||
"@format": "json" | ||
"@action": "resolveAnchors" | ||
appendExceedingArguments: TRUE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
Neos: | ||
Neos: | ||
fusion: | ||
autoInclude: | ||
Paessler.AnchorLink: true | ||
userInterface: | ||
translation: | ||
autoInclude: | ||
Paessler.AnchorLink: | ||
- Main | ||
- 'NodeTypes/*' | ||
Ui: | ||
resources: | ||
javascript: | ||
'Paessler.AnchorLink': | ||
resource: 'resource://Paessler.AnchorLink/Public/JavaScript/AnchorLink/Plugin.js' | ||
frontendConfiguration: | ||
'Paessler.AnchorLink': | ||
displaySearchBox: true | ||
threshold: 0 | ||
Flow: | ||
security: | ||
authentication: | ||
providers: | ||
'Neos.Neos:Backend': | ||
requestPatterns: | ||
'Paessler.AnchorLink:Backend': | ||
pattern: ControllerObjectName | ||
patternOptions: | ||
controllerObjectNamePattern: 'Paessler\AnchorLink\Controller\.*' | ||
mvc: | ||
routes: | ||
'Paessler.AnchorLink': | ||
position: 'before Neos.Neos' | ||
Paessler: | ||
AnchorLink: | ||
# The following configuration is only considered if the default ContentNodeAnchorLinkResolver is used: | ||
|
||
# Only nodes of this type will appear in the "Choose link anchor" selector | ||
contentNodeType: 'Paessler.AnchorLink:AnchorMixin' | ||
# Eel Expression that returns the anchor (without leading "#") for a given node | ||
anchor: ${node.properties.anchor || node.name} | ||
# Eel Expression that returns the label to be rendered in the anchor selector in the Backend | ||
label: ${node.label} | ||
# Eel Expression that returns a group for the anchor selector (empty string == no grouping) | ||
group: ${I18n.translate(node.nodeType.label)} | ||
# Eel Expression that returns an icon for the anchor selector (empty string = no icon) | ||
icon: ${node.nodeType.fullConfiguration.ui.icon} | ||
|
||
# Eel Helpers that are available in the Eel expressions above | ||
eelContext: | ||
String: Neos\Eel\Helper\StringHelper | ||
Array: Neos\Eel\Helper\ArrayHelper | ||
Date: Neos\Eel\Helper\DateHelper | ||
Configuration: Neos\Eel\Helper\ConfigurationHelper | ||
Math: Neos\Eel\Helper\MathHelper | ||
Json: Neos\Eel\Helper\JsonHelper | ||
I18n: Neos\Flow\I18n\EelHelper\TranslationHelper |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
'Paessler.AnchorLink:AnchorMixin': | ||
abstract: true | ||
ui: | ||
inspector: | ||
groups: | ||
anchor: | ||
label: i18n | ||
properties: | ||
anchor: | ||
type: string | ||
ui: | ||
reloadIfChanged: true | ||
label: i18n | ||
inspector: | ||
group: anchor | ||
help: | ||
message: i18n | ||
validation: | ||
'Neos.Neos/Validation/RegularExpressionValidator': | ||
regularExpression: '/^([a-zA-Z\d\-._~\!$&()*+,;=:@%\/?]*)$/' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Paessler.AnchorLink | ||
|
||
Extends the Neos CKE5 link-editor with server-side resolvable anchor links. | ||
|
||
 | ||
|
||
## Installation | ||
|
||
1. Install the package: `composer require paessler/anchorlink` | ||
|
||
2. Enable additional linking options with such config: | ||
|
||
```yaml | ||
"Neos.NodeTypes.BaseMixins:TextMixin": # Or other nodetype | ||
properties: | ||
text: | ||
ui: | ||
inline: | ||
editorOptions: | ||
linking: | ||
anchorLink: true | ||
``` | ||
3. For all content nodetypes that you would like to be able to link to, inherit from `Paessler.AnchorLink:AnchorMixin`, e.g.: | ||
|
||
```yaml | ||
Neos.Neos:Content: # Or other nodetype | ||
superTypes: | ||
Paessler.AnchorLink:AnchorMixin: true | ||
``` | ||
|
||
4. Adjust the rendering for those nodes to insert anchors before them, e.g. there is included a Fusion processor to help with that: | ||
|
||
``` | ||
prototype(Neos.Neos:Content).@process.anchor = Paessler.AnchorLink:AnchorLinkAugmenter | ||
``` | ||
|
||
Note: this will add an `id` attribute to the corresponding output. For this to work reliably the corresponding prototype should render | ||
a single root element. Otherwise an additional wrapping `div` element will be rendered. | ||
Also the rendered content must not already contain an `id` attribute because it would be merged with the one from the augmentor in that case. | ||
|
||
## Configuration | ||
|
||
It's possible to configure the content node nodetype that is used for linking. Also it's possible to use a different property for the anchor value and the label via Settings.yaml. | ||
|
||
These are the defaults: | ||
|
||
```yaml | ||
Paessler: | ||
AnchorLink: | ||
# Only nodes of this type will appear in the "Choose link anchor" selector | ||
contentNodeType: "Paessler.AnchorLink:AnchorMixin" | ||
# Eel Expression that returns the anchor (without leading "#") for a given node | ||
anchor: ${node.properties.anchor || node.name} | ||
# Eel Expression that returns the label to be rendered in the anchor selector in the Backend | ||
label: ${node.label} | ||
# Eel Expression that returns a group for the anchor selector (empty string == no grouping) | ||
group: ${I18n.translate(node.nodeType.label)} | ||
# Eel Expression that returns an icon for the anchor selector (empty string = no icon) | ||
icon: ${node.nodeType.fullConfiguration.ui.icon} | ||
``` | ||
|
||
It's possible to disable the searchbox or adjust its threshold via Settings.yaml, the default settings are: | ||
|
||
```yaml | ||
Neos: | ||
Neos: | ||
Ui: | ||
frontendConfiguration: | ||
"Paessler.AnchorLink": | ||
displaySearchBox: true | ||
threshold: 0 | ||
``` | ||
|
||
## Low-level Customization | ||
|
||
Finally, it is possible to create a completely custom anchor nodes resolver. | ||
|
||
Create a class implementing `AnchorLinkResolverInterface` that would take the current content node, link and a searchTerm and return an array of options for the link anchor selector and configure it in `Objects.yaml` like this: | ||
|
||
``` | ||
'Paessler\AnchorLink\Controller\AnchorLinkController': | ||
properties: | ||
resolver: | ||
object: Your\Custom\AnchorLinkResolver | ||
``` | ||
|
||
## Development | ||
|
||
If you need to adjust anything in this package, just do so and then rebuild the code like this: | ||
|
||
``` | ||
cd Resources/Private/JavaScript/AnchorLink | ||
yarn && yarn build | ||
``` | ||
|
||
And then commit changed filed including Plugin.js | ||
|
||
## About | ||
|
||
The package is based on the `DIU.Neos.AnchorLink` package. We thank the DIU team for all the efforts. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Meant to be used as a processor, e.g.: | ||
# prototype(Neos.Neos:Content).@process.anchor = Paessler.AnchorLink:AnchorLinkAugmenter | ||
# @neoscs-ignore-next-line | ||
prototype(Paessler.AnchorLink:AnchorLinkAugmenter) < prototype(Neos.Fusion:Augmenter) { | ||
id = ${Neos.Node.isOfType(node, 'Paessler.AnchorLink:AnchorMixin') && !String.isBlank(q(node).property('anchor')) ? q(node).property('anchor') : node.name} | ||
} |
Oops, something went wrong.