Naviga Writer
8.1.7
8.1.7
  • Naviga Writer
  • Release notes
    • 8.1.7
    • 8.1.6
    • 8.1.5
    • 8.1.4
    • 8.1.3
    • 8.1.2
    • 8.1.1
    • 8.1
    • 8.0
    • 7.2
    • 7.1.0
    • 7.0.0
    • 6.5.x
    • 6.5.0
    • 6.4.1
    • 6.4.0
    • 6.3.5
    • 6.3.4
    • 6.3.3
    • 6.3.2
    • 6.3.1
    • 6.2.2
    • 6.2.1
    • 6.2.0
    • 6.1.2
    • 6.1.1
    • 6.1.0
    • 6.0.0
    • 5.3.0
  • Introduction
    • Authoring
    • Developing
    • Publishing
    • History
  • User Guide
    • Writer User Guide
      • Create a new article
      • Top bar
        • Setting menu
        • Article name
        • Search and replace words
        • Version history of an article
          • List of versions
          • Changes in each version
          • Restore to an older version
        • Locked article
        • Active Users
        • Copy article url
        • Save and publish flow
        • History Button
      • Content area
        • Image gallery
        • Embed map
        • Table
        • Teaser
        • Content part
        • HTML embed
        • Upload image
        • Upload PDF
        • Textstyles
        • Lists
        • Special character
        • Marker tool
      • Right Sidebar
        • Meta
          • Author
          • Channels
        • Integrations
        • Image and Article search
      • Bottom bar
        • Article information
        • Edit metadata on linked images
        • Article size
        • Text information
        • Language menu
      • Images User Guide
        • Upload images
        • Metadata of the image
        • Cropping images
        • Download
      • Personal Writer Template
      • Writer Keyboard Shortcuts
      • Text Management
      • Common questions when starting using Writer
  • Admin Guide
    • Configuration Files
    • Configurations Guide
      • Right Sidebar
      • Text Information
      • Content menu
    • Article Templates Configuration
    • Byline configuration
    • Language Configuration
    • Publish Flow
      • Default configuration definitions
      • Publish flow config details
      • Preconditions for roles in the publish flow
    • Generic Properties
      • Configuration
    • Image Services
      • ImEngine
      • Imgix
    • Plugins
      • Naviga developed plugins
        • Plugins in earlier versions of Writer
      • Deprecated Plugins
      • Third-party plugins
  • Developer guide
    • Upgrade Guides
      • 8.0 - Image/PDF upload changes
      • 8.0 - Opening an Article
    • Writer Plugin Development
      • Quickstart
      • Type Definitions (beta)
      • Plugin overview
      • Creating a content object plugin
      • Validation and hooks
      • Interacting with external resources
    • Writer Plugin Building Blocks
      • Package
      • Component
      • Node
      • Converter
      • Events
    • Writer Plugin Style Guide
      • CSS Guidelines
      • CSS variables, colors and fonts
      • UI Components
    • Tutorials
      • Popover & text analysis
      • Search & replace
      • Concept interaction
      • Integrating External Spell Checking
    • Infomaker NewsML
      • Overview
      • Important: About inline notes
      • Document relations and types
      • Extensions XSD
      • NewsItem
      • ConceptItem
      • PlanningItem
      • Examples
        • NewsItem - Text
        • NewsItem - Picture
        • NewsItem - PDF
        • ConceptItem - Author
        • ConceptItem - Category
        • ConceptItem - Channel
        • ConceptItem - Content Profile
        • ConceptItem - Event
        • ConceptItem - Organisation
        • ConceptItem - Person
        • ConceptItem - Place (point)
        • ConceptItem - Place (polygon)
        • ConceptItem - Section
        • ConceptItem - Story
        • ConceptItem - Topic
        • PlanningItem
    • Media Enrichment
      • Images
  • API Reference
    • Writer Api
      • Api
      • Article
      • Browser
      • Concept
      • ConceptService
      • Document
      • Events
      • NewsItem
      • Router
      • Ui
      • Upload
      • User
      • settings
      • History
      • Settings
    • UI Components
      • UIAvatar
      • UIButton
      • UIByline
      • UICheckbox
      • UIChip
      • UIDatePicker
      • UIDatetimeFieldEditor
      • UIDropdown
      • UIFieldEditor
      • UIIconButton
      • UIInlineImage
      • UIPagination
      • UISelect
      • UITimePicker
      • UIToggle
      • UITooltip
      • UIInputText
      • UITextarea
      • UIButtonGroup
      • UIConceptSearch
      • UIDateTimePicker
      • UIInputSearch
      • UIIcon
      • UIPill
      • UISpinner
      • UIButtonList
      • UIIconBadge
      • UIIconButtonMenu
      • UIInputPassword
Powered by GitBook
On this page
  • Plugin Structure
  • Example Plugin Structure
  • MyPluginPackage.js
  • The configurator object
  • Common Add-functions
  • Tools and Commands

Was this helpful?

  1. Developer guide
  2. Writer Plugin Building Blocks

Package

This text will explore the Package file used to define the parts included in, and used by a Writer plugin.

Plugin Structure

A plugin is a collection of many different resources, and the Package file is that collection's bootstrap. Label definitions, node- and converter-registration, adding validatiors, and registering tools and commands, are all placed in the Package file, using the Writer's NPWriterConfigurator-class.

The Package file also contains the plugin's name and id.

Example Plugin Structure

/ se.mydomain.myplugin
  / components
    MyPluginComponent.js
    ChildComponent.js
  MyPluginNode.js
  MyPluginConverter.js 
  MyPluginPackage.js
  index.js

In this example, index.js is the plugin's entrypoint. It's here where the Package file is imported and the plugin is registered in the Writer.

MyPluginPackage.js contains information about the plugin, and registers MyPluginNode.js as a substance node, MyPluginConverter.js as a NewsML-converter, and MyPluginComponent.js as the component used to present MyPluginNode.js.

Depending on the type of plugin, the Package will contain different definitions and registrations.

MyPluginPackage.js

import './scss/link.scss' // Provide an entrypoint for the plugin's style
import MyPluginNode from './MyPluginNode'
import MyPluginConverter from './MyPluginConverter'
import MyPluginComponent from './components/MyPluginComponent'

export default {
    name: 'my-plugin',
    id: 'se.mydomain.myplugin',
    configure: function (configurator, pluginConfig) {

        configurator.addNode(MyPluginNode)
        configurator.addComponent(MyPluginNode.type, MyPluginComponent)
        configurator.addConverter('newsml', MyPluginConverter)

        configurator.addLabel('Hello World', {
            sv: 'Tjena Världen'
        })
    }
}

This example Package file contains definitions for a Node, a Component linked to the Node's type-property, a Converter to import and export the Node-data using NewsML. It also adds a label which can be used within the plugin's components.

The configurator object

As seen in the Package example above, the supplied configurator-object is used to add different resources used in the plugin. Below are relevant configurator-functions which are useful when developing a plugin.

Common Add-functions

addNode(NodeClass) Registers a node in Substance configuration for use later.

addComponent(type, ComponentClass) Registers a class which extends Substance's Component-class for a Node type. A Component in this instance is a UI representation of a Node class. Only on Component can be registered to one specific type.

addConverter(converterObject) Registers a converter object for a specific output type. A converter is an object used for exporting and importing the data stored in a Node object.

addLabel(label, { translations }) Adds a localized label string which can be fetched in the plugin's components using this.getLabel(string), assuming that the component is extending Substance's Component-class. The first string property is used as fallback if none of the supplied translations are found.

Label Example:

configurator.addLabel('Hello World', {
    sv: 'Hejsan Världen'
})

this.getLabel('Hello World') 
// If the Writer's configured "labelLanguage" property is set 
// to "sv", "Hejsan Världen" is returned, any other language
// will return "Hello World"
configurator.addIcon('my-icon', {'fontawesome': 'fa-external-link'})

$$(Button, {
    icon: 'my-icon'
}).on('click', () => { console.info('Foobar') })

addKeyboardShortcut(combo, spec, globalCombo, description = '') Add keyboard shortcut and connect to a Command.

Keyboard Shortcut Example:

  // configure function in a Package file

  const combo = {
    standard: {
        'default': 'ctrl+d',
        'mac': 'cmd+d'
    }
  }

  configurator.addKeyboardShortcut(combo, {command: 'my-amazing-command'}, true, 'Runs my amazing command in the global context.')

addValidator(Validator) Adds a class which inherits from Validator to validate the Article's content and metadata before saving.

Validator Example:

import {Validator, api} from 'writer'

class MyHeadlineValidator extends Validator {

    constructor(...args) {
        super(...args)
    }

    /**
     * Main validation method
     */
    validate() {
        this.validateHeadline()
    }

    /**
     * Ensure that a valid headline exists
     */
    validateHeadline() {
        const headlines = this.newsItem.querySelectorAll('idf > group element[type="headline"]')
        const headline = headlines[0].childNodes.length === 0 ? '' : headlines[0].firstChild.textContent.trim()

        if (headlines.length === 0 || headline === '') {
            this.addError(
                api.getLabel('Headline is missing or empty!')
            )
        }
    }
}

export {MyHeadlineValidator}

addToSidebar(tabId, pluginConfig, ComponentClass) Registers a Component to be rendered in the Sidebar. tabId is a string, which is the id of the tab, but also the label which is used for the tab. If the tab does not exist, it will be created, and the Component added to this new tab.

addTopBarComponent(id, def, component) Registers a Component to be rendered in the Top bar. The parameter def is an object which contains alignment, whether the Component is placed on the left, or right, side of the top bar.

Topbar Example:

configurator.addTopBarComponent(
    'my-amazing-topbar-component',
    {
        align: 'left' // Or 'right'
    },
    MyAmazingTopBarComponent
)

addPopover(id, def, component) Similar to addTopBarComponent, this function adds an icon in the Top bar which, when clicked opens a popover overlay with its component rendered inside.

Popover Example:

configurator.addPopover(
    'my-amazing-popover',
    {
        icon: 'fa-smiley',
        align: 'right',
        sticky: true    // Set to `true` to keep the popover open when clicking somewhere else, default `false`
    },
    MyAmazingComponent
)

Tools and Commands

Tool class Example:

import {Tool} from 'substance'
import {UIIcon} from 'writer'


class MyAmazingTool extends Tool {

    render($$) {
        return $$('div').attr('title', this.getLabel('Cheers you up'))
            .append(
                $$('button').addClass('se-tool').append($$(UIIcon, {
                    name: 'check-bold'
                }))
                    .on('click', this.executeCommand) // This will execute the command which name was used to register the Tool 
            )
      }
}

export {MyAmazingTool}

addCommand(name, CommandClass, options) Adds a Command which can be executed by a Tool, or manually using EditorSession. In its simplest form, a Command contains the logic for a Tool.

Command Example:

import {WriterCommand} from 'writer'

class MyAmazingCommand extends WriterCommand {

  /**
  * Executes command with supplied params.
  * When called from Tool class, props from Tools is contained in params.
  * 
  * @param params
  */
  execute(params) {
      console.info('Have a great day!')
      console.info('Also, here\'s the supplied data', params)
  }
}

export {MyAmazingCommand}

addContentMenuTool(commandName, ToolClass) Adds a Tool to the Content Menu, it should return a rendered ContextMenuItem instance.

addContentMenuTopTool(commandName, ToolClass) Adds a Tool to the top of the Content Menu.

addContextMenuTool(commandName, ToolClass) Adds a Tool to the context menu, e.g when right clicking on the editing surface.

addOverlayTool(commandName, ToolClass) Adds a Tool which is displayed when selecting text, such as annotation plugins.

PreviousWriter Plugin Building BlocksNextComponent

Was this helpful?

To learn more about Nodes, Converters, and Components, have look at .

addIcon(iconName, options) Registers an icon from , or another registered icon provider for use in the plugin. Example:

Adding a Tool is a simple way to add a button, or some text, which can execute a Command when clicked. The only difference between the add***Tool()-functions is where in the Writer the Tool is added. When adding a Tool, it needs the name of the Command (which was previously registered) it should be bound to, and a class which is used to render the Tool. For a visual representation of all the Writer sections, see the .

their respective documents
FontAwesome
Plugin Overview