Commit 43068933 authored by anon's avatar anon

First Linkit 8.x-4.x commit

parents
# Linkit
Linkit for D8
{
"name": "drupal/linkit",
"description": "Linkit",
"type": "drupal-module",
"license": "GPL-2.0+"
}
# Schema for the configuration files of the Linkit module.
linkit.linkit_profile.*:
type: config_entity
mapping:
label:
type: label
label: 'Name'
id:
type: string
description:
type: string
autocomplete_configuration:
type: mapping
mapping:
character_limit:
type: integer
key_press_delay:
type: integer
timeout:
type: integer
attributePlugins:
type: sequence
sequence:
type: mapping
mapping:
id:
type: string
weight:
type: integer
selectionPlugins:
type: linkit.plugin.selection.[%parent.id]
linkit.plugin.selection:
type: sequence
sequence:
type: mapping
mapping:
id:
type: string
data:
type: linkit.plugin.selection.[%parent.id]
weight:
type: integer
linkit.selection_plugin.*:
type: linkit.plugin.selection
linkit.selection_plugin.entity:
type: linkit.plugin.selection
mapping:
result_description:
type: string
bundles:
type: sequence
sequence:
type: string
group_by_bundle:
type: boolean
nullable: false
linkit.selection_plugin.entity:*:
type: linkit.selection_plugin.entity
linkit.selection_plugin.entity:node:
type: linkit.selection_plugin.entity
mapping:
include_unpublished:
type: boolean
/**
* @file
* Stylesheet for the Linkit module.
*/
.js input.form-linkit-autocomplete {
background: url('/core/misc/throbber-inactive.png') no-repeat 100% center;
}
.js[dir="rtl"] input.form-linkit-autocomplete {
background-position: 0 center;
}
.js input.form-linkit-autocomplete.ui-autocomplete-loading {
background: url('/core/misc/throbber-active.gif') 100% center;
}
.js[dir="rtl"] input.form-linkit-autocomplete.ui-autocomplete-loading {
background-position: 0 center;
}
/**
* @file
* Linkit Autocomplete based on jQuery UI.
*/
(function ($, Drupal) {
"use strict";
var autocomplete;
/**
* JQuery UI autocomplete source callback.
*
* @param {object} request
* @param {function} response
*/
function sourceData(request, response) {
var elementId = this.element.attr('id');
if (!(elementId in autocomplete.cache)) {
autocomplete.cache[elementId] = {};
}
/**
* @param {object} suggestions
*/
function showSuggestions(suggestions) {
response(suggestions);
}
/**
* Transforms the data object into an array and update autocomplete results.
*
* @param {object} data
*/
function sourceCallbackHandler(data) {
console.log(data);
autocomplete.cache[elementId][term] = data;
showSuggestions(data);
}
// Get the desired term and construct the autocomplete URL for it.
var term = request.term;
// Check if the term is already cached.
if (autocomplete.cache[elementId].hasOwnProperty(term)) {
showSuggestions(autocomplete.cache[elementId][term]);
}
else {
var options = $.extend({success: sourceCallbackHandler, data: {q: term}}, autocomplete.ajax);
$.ajax(this.element.attr('data-autocomplete-path'), options);
}
}
/**
* Handles an autocompleteselect event.
*
* @param {jQuery.Event} event
* @param {object} ui
*
* @return {bool}
*/
function selectHandler(event, ui) {
console.log(ui.item);
event.target.value = ui.item.path;
return false;
}
/**
* Override jQuery UI _renderItem function to output HTML by default.
*
* @param {object} ul
* @param {object} item
*
* @return {object}
*/
function renderItem(ul, item) {
return $("<li>")
.append($("<span>").html(item.title))
.append($("<span>").html(item.description))
.appendTo(ul);
}
/**
* Override jQuery UI _renderMenu function to group items.
*
* @param {object} ul
* @param {object} item
*
*/
//function renderMenu(ul, item) {
// var that = this;
// $.each(items, function(index, item) {
// autocomplete.options._renderItemData(ul, item);
// });
// $(ul).find("li:odd").addClass("odd");
//}
/**
* Attaches the autocomplete behavior to all required fields.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.linkit_autocomplete = {
attach: function (context) {
// Act on textfields with the "form-autocomplete" class.
var $autocomplete = $(context).find('input.form-linkit-autocomplete').once('linkit-autocomplete');
if ($autocomplete.length) {
// Use jQuery UI Autocomplete on the textfield.
$autocomplete.autocomplete(autocomplete.options)
.data("ui-autocomplete")
._renderItem = autocomplete.options.renderItem;
}
},
detach: function (context, settings, trigger) {
if (trigger === 'unload') {
$(context).find('input.form-linkit-autocomplete')
.removeOnce('linkit-autocomplete')
.autocomplete('destroy');
}
}
};
/**
* Autocomplete object implementation.
*/
autocomplete = {
cache: {},
options: {
source: sourceData,
renderItem: renderItem,
select: selectHandler,
minLength: 1
},
ajax: {
dataType: 'json'
}
};
})(jQuery, Drupal);
/**
* @file
* Linkit plugin.
*
* @ignore
*/
(function ($, Drupal, drupalSettings, CKEDITOR) {
"use strict";
// Alter the dialog settings to make a bigger dialog.
$(window).on('dialog:beforecreate', function (event, dialog, $element, settings) {
settings.dialogClass = settings.dialogClass.replace('ui-dialog--narrow', '');
settings.width = 700;
});
CKEDITOR.plugins.add('linkit', {
init: function (editor) {
// Add the commands for link and unlink.
editor.addCommand('linkit', {
allowedContent: new CKEDITOR.style({
element: 'a',
attributes: {
'!href': '',
'target': ''
}
}),
requiredContent: new CKEDITOR.style({
element: 'a',
attributes: {
href: ''
}
}),
modes: {wysiwyg: 1},
canUndo: true,
exec: function (editor) {
var linkElement = getSelectedLink(editor);
var linkDOMElement = null;
// Set existing values based on selected element.
var existingValues = {};
if (linkElement && linkElement.$) {
linkDOMElement = linkElement.$;
// Populate an array with the link's current attributes.
var attribute = null;
var attributeName;
for (var attrIndex = 0; attrIndex < linkDOMElement.attributes.length; attrIndex++) {
attribute = linkDOMElement.attributes.item(attrIndex);
attributeName = attribute.nodeName.toLowerCase();
// Don't consider data-cke-saved- attributes; they're just there
// to work around browser quirks.
if (attributeName.substring(0, 15) === 'data-cke-saved-') {
continue;
}
// Store the value for this attribute, unless there's a
// data-cke-saved- alternative for it, which will contain the
// quirk-free, original value.
existingValues[attributeName] = linkElement.data('cke-saved-' + attributeName) || attribute.nodeValue;
}
}
// Prepare a save callback to be used upon saving the dialog.
var saveCallback = function (returnValues) {
editor.fire('saveSnapshot');
// Create a new link element if needed.
if (!linkElement && returnValues.attributes.href) {
var selection = editor.getSelection();
var range = selection.getRanges(1)[0];
// Use link URL as text with a collapsed cursor.
if (range.collapsed) {
// Shorten mailto URLs to just the email address.
var text = new CKEDITOR.dom.text(returnValues.attributes.href.replace(/^mailto:/, ''), editor.document);
range.insertNode(text);
range.selectNodeContents(text);
}
// Ignore a disabled target attribute.
if (returnValues.attributes.target === 0) {
delete returnValues.attributes.target;
}
// Create the new link by applying a style to the new text.
var style = new CKEDITOR.style({element: 'a', attributes: returnValues.attributes});
style.type = CKEDITOR.STYLE_INLINE;
style.applyToRange(range);
range.select();
// Set the link so individual properties may be set below.
linkElement = getSelectedLink(editor);
}
// Update the link properties.
else if (linkElement) {
for (var attrName in returnValues.attributes) {
if (returnValues.attributes.hasOwnProperty(attrName)) {
// Update the property if a value is specified.
if (returnValues.attributes[attrName].length > 0) {
var value = returnValues.attributes[attrName];
linkElement.data('cke-saved-' + attrName, value);
linkElement.setAttribute(attrName, value);
}
// Delete the property if set to an empty string.
else {
linkElement.removeAttribute(attrName);
}
}
}
}
// Save snapshot for undo support.
editor.fire('saveSnapshot');
};
// Drupal.t() will not work inside CKEditor plugins because CKEditor
// loads the JavaScript file instead of Drupal. Pull translated
// strings from the plugin settings that are translated server-side.
var dialogSettings = {
title: linkElement ? editor.config.drupalLink_dialogTitleEdit : editor.config.drupalLink_dialogTitleAdd,
dialogClass: 'editor-linkit-dialog'
};
// Open the dialog for the edit form.
Drupal.ckeditor.openDialog(editor, Drupal.url('linkit/dialog/linkit/' + editor.config.drupal.format), existingValues, saveCallback, dialogSettings);
}
});
// CTRL + L.
editor.setKeystroke(CKEDITOR.CTRL + 76, 'linkit');
// Add buttons for link and unlink.
if (editor.ui.addButton) {
editor.ui.addButton('Linkit', {
label: Drupal.t('Link'),
command: 'linkit',
icon: this.path + '/linkit.png'
});
}
editor.on('doubleclick', function (evt) {
var element = getSelectedLink(editor) || evt.data.element;
if (!element.isReadOnly()) {
if (element.is('a')) {
editor.getSelection().selectElement(element);
editor.getCommand('linkit').exec();
}
}
});
// If the "menu" plugin is loaded, register the menu items.
if (editor.addMenuItems) {
editor.addMenuItems({
link: {
label: Drupal.t('Edit Link'),
command: 'drupallink',
group: 'link',
order: 1
}
});
}
// If the "contextmenu" plugin is loaded, register the listeners.
if (editor.contextMenu) {
editor.contextMenu.addListener(function (element, selection) {
if (!element || element.isReadOnly()) {
return null;
}
var anchor = getSelectedLink(editor);
if (!anchor) {
return null;
}
var menu = {};
if (anchor.getAttribute('href') && anchor.getChildCount()) {
menu = {link: CKEDITOR.TRISTATE_OFF, unlink: CKEDITOR.TRISTATE_OFF};
}
return menu;
});
}
}
});
/**
* Get the surrounding link element of current selection.
*
* The following selection will all return the link element.
*
* @example
* <a href="#">li^nk</a>
* <a href="#">[link]</a>
* text[<a href="#">link]</a>
* <a href="#">li[nk</a>]
* [<b><a href="#">li]nk</a></b>]
* [<a href="#"><b>li]nk</b></a>
*
* @param {CKEDITOR.editor} editor
* The CKEditor editor object
*
* @return {?HTMLElement}
* The selected link element, or null.
*
*/
function getSelectedLink(editor) {
var selection = editor.getSelection();
var selectedElement = selection.getSelectedElement();
if (selectedElement && selectedElement.is('a')) {
return selectedElement;
}
var range = selection.getRanges(true)[0];
if (range) {
range.shrink(CKEDITOR.SHRINK_TEXT);
return editor.elementPath(range.getCommonAncestor()).contains('a', 1);
}
return null;
}
})(jQuery, Drupal, drupalSettings, CKEDITOR);
name: Linkit
description: Linkit
package: Custom
type: module
version: 4.0
core: 8.x
<?php
/**
* @file
* Installation functions for Linkit module.
*/
/**
* Implements hook_install().
*/
function linkit_install() {
}
linkit.autocomplete:
version: VERSION
js:
js/autocomplete.js: {}
css:
component:
css/linkit.module.css: {}
dependencies:
- core/jquery
- core/drupal
- core/drupalSettings
- core/drupal.ajax
- core/jquery.ui.autocomplete
linkit_profile.add_form:
route_name: entity.linkit_profile.add_form
title: 'Add profile'
appears_on:
- entity.linkit_profile.collection
linkit.selection_plugin.add:
route_name: linkit.selection_plugin.add
title: 'Add selection plugins'
appears_on:
- entity.linkit_profile.selection_plugins
linkit.attribute_plugin.add:
route_name: linkit.attribute_plugin.add
title: 'Add attribute plugins'
appears_on:
- entity.linkit_profile.attribute_plugins
entity.linkit_profile.collection:
title: 'Linkit'
parent: system.admin_config_content
description: 'Manage Linkit profiles.'
route_name: entity.linkit_profile.collection
entity.linkit_profile.edit_form:
route_name: entity.linkit_profile.edit_form
title: 'Edit'
base_route: entity.linkit_profile.edit_form
weight: 0
entity.linkit_profile.selection_plugins:
route_name: entity.linkit_profile.selection_plugins
title: 'Manage selection plugins'
base_route: entity.linkit_profile.edit_form
weight: 5
entity.linkit_profile.attribute_plugins:
route_name: entity.linkit_profile.attribute_plugins
title: 'Manage attributes plugins'
base_route: entity.linkit_profile.edit_form
weight: 10
<?php
/**
* @file
*
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function linkit_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'entity.linkit_profile.attributes':
return '<p>' . t('Attributes are HTML attributes that will be attached to the insert plugin.') . '</p>';
break;
}
}
administer linkit profiles:
title: 'Administer linkit profiles'
\ No newline at end of file
entity.linkit_profile.collection:
path: '/admin/config/content/linkit'
defaults:
_entity_list: 'linkit_profile'
_title: 'Linkit profiles'
requirements:
_permission: 'administer linkit profiles'
entity.linkit_profile.add_form:
path: '/admin/config/content/linkit/add'
defaults:
_entity_form: linkit_profile.add
_title: 'Add profile'
requirements:
_permission: 'administer linkit profiles'
entity.linkit_profile.edit_form:
path: '/admin/config/content/linkit/manage/{linkit_profile}'
defaults:
_entity_form: linkit_profile.edit
_title: 'Edit profile'
requirements:
_permission: 'administer linkit profiles'
entity.linkit_profile.delete_form:
path: '/admin/config/content/linkit/manage/{linkit_profile}/delete'
defaults:
_entity_form: linkit_profile.delete
_title: 'Delete profile'
requirements:
_permission: 'administer linkit profiles'
entity.linkit_profile.attribute_plugins:
path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes-plugins'
defaults:
_form: '\Drupal\linkit\Form\Attribute\OverviewForm'
_title: 'Manage attribute plugins'
requirements:
_permission: 'administer linkit profiles'
linkit.attribute_plugin.add:
path: '/admin/config/content/linkit/manage/{linkit_profile}/attributes-plugins/add'
defaults:
_form: '\Drupal\linkit\Form\Attribute\AddForm'
_title: 'Add attribute plugins'
requirements:
_permission: 'administer linkit profiles'
linkit.attribute_plugin.remove:
path: '/admin/config/content/linkit/manage/{linkit_profile}/attribute-plugins/remove/{plugin_id}'
defaults:
_form: '\Drupal\linkit\Form\Attribute\DeleteForm'
_title: 'Remove an attribute plugin'
requirements:
_permission: 'administer linkit profiles'
entity.linkit_profile.selection_plugins:
path: '/admin/config/content/linkit/manage/{linkit_profile}/selection-plugins'
defaults:
_form: '\Drupal\linkit\Form\Selection\OverviewForm'
_title: 'Manage selection plugins'
requirements:
_permission: 'administer linkit profiles'
linkit.selection_plugin.add:
path: '/admin/config/content/linkit/manage/{linkit_profile}/selection-plugins/add'
defaults:
_form: '\Drupal\linkit\Form\Selection\AddForm'
_title: 'Add selection plugins'
requirements:
_permission: 'administer linkit profiles'
linkit.selection_plugin.remove:
path: '/admin/config/content/linkit/manage/{linkit_profile}/selection-plugins/remove/{plugin_id}'
defaults:
_form: '\Drupal\linkit\Form\Selection\DeleteForm'
_title: 'Remove a selection plugin'
requirements:
_permission: 'administer linkit profiles'
linkit.selection_plugin.edit:
path: '/admin/config/content/linkit/manage/{linkit_profile}/selection-plugins/{plugin_id}'
defaults:
_form: '\Drupal\linkit\Form\Selection\EditForm'
_title: 'Edit selection plugin'
requirements:
_permission: 'administer linkit profiles'
linkit.linkit_dialog:
path: '/linkit/dialog/linkit/{filter_format}'
defaults:
_form: '\Drupal\linkit\Form\LinkitEditorDialog'
_title: 'Add link'
requirements:
_entity_access: 'filter_format.use'
linkit.autocomplete:
path: '/linkit/autocomplete/{linkit_profile_id}'
defaults:
_controller: '\Drupal\linkit\Controller\AutocompleteController::autocomplete'
requirements:
_access: 'TRUE'
services:
plugin.manager.linkit.attribute_plugin:
class: Drupal\linkit\AttributePluginManager
parent: default_plugin_manager
plugin.manager.linkit.selection_plugin:
class: Drupal\linkit\SelectionPluginManager
parent: default_plugin_manager
#!/usr/bin/env bash
drush si --site-name=Linkit8 --account-pass=admin -yvd --notify; drush en linkit devel config_inspector simpletest -y
<?php
/**
* @file
* Contains \Drupal\linkit\Annotation\AttributePlugin.
*/
namespace Drupal\linkit\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines an attribute annotation object.
*
* Plugin Namespace: Plugin\Linkit\Attribute
*
* For a working example, see \Drupal\linkit\Plugin\Linkit\Attribute\Title
*
* @see \Drupal\linkit\AttributePluginInterface
* @see \Drupal\linkit\AttributePluginBase
* @see \Drupal\linkit\AttributePluginManager
* @see plugin_api
*
* @Annotation
*/
class AttributePlugin extends Plugin {
/**
* The plugin ID.
*
* @var string
*/
public $id;
/**
* The human-readable name of the attribute plugin.
*
* The string should be wrapped in a @Translation().
*
* @var \Drupal\Core\Annotation\Translation
*/