SkillAgentSearch skills...

Writeaway

No description available

Install / Use

/learn @writeaway/Writeaway
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

WriteAway

WriteAway is a JavaScript library for editing CMS pieces inline on pages on the client side.

Based on React and Redux

Created by SpiralScout.

WriteAway comes like a core controller with set of plugins for different types of media.

@writeaway/core - Core controller for all plugins, includes editor floating bar and manages state of editors

@writeaway/plugin-medium - Plugin for supporting rich text editing, editing images and block backgrounds

@writeaway/plugin-coremirror - Plugin for editing block's source code, i.e. for embedded iframes or scrips

@writeaway/plugin-seo - Plugin for editing SEO meta tags

Installation On Top Of Existing Project

To use on top of existing project you would need to create a custom bundle using your favorite packaging tool. You can see 2 samples of such bundles on demo website and in spiral framework bridge

This bundle will scan an existing page for specific selectors and will attach editors on them

npm install --save @writeaway/core
npm install --save @writeaway/plugin-medium
npm install --save @writeaway/plugin-codemirror
npm install --save @writeaway/plugin-seo

And then in code of bundle

    import { WriteAwayCore } from '@writeaway/core';
    import { WriteAwaySeoData, EditorSeo } from '@writeaway/plugin-seo';
    import { EditorSourceCode } from '@writeaway/plugin-codemirror';
    import { EditorBlockBackground, EditorImage, EditorRichText } from '@writeaway/plugin-medium';
    
    // Define which piece type is handled by which editor
    const components = {
      html: EditorRichText,
      image: EditorImage,
      background: EditorBlockBackground,
      source: EditorSourceCode,
      seo: EditorSeo,
    };
    
    const writeaway = new WriteAwayCore({
      piecesOptions: {
        selector: '.js-piece', // Selector to look for
        attribute: 'data-type', // Attribute containing piece type, that will define what editor to attach
        attributeId: 'data-id', // Attribute containing unique piece id
        attributeName: 'data-name', // Attribute containing human readable piece name that will be shown as header in hover block
        components,
      },
    });

Attach resulting bundle in bottom of the page

For styling you can either write own styles or include default to bundle .less file like so

@import "~@writeaway/core/src/styles/writeaway";
@import "~@writeaway/plugin-medium/src/medium-editor";
@import "~@writeaway/plugin-medium/src/writeaway-medium";
@import "~@writeaway/plugin-seo/src/google-preview";
@import "~@writeaway/plugin-seo/src/styles";

Alternatively, include compiled CSS files

@import "~@writeaway/core/dist/css/core.css";
@import "~@writeaway/plugin-medium/dist/css/plugin-medium.css";
@import "~@writeaway/plugin-seo/dist/css/plugin-seo.css";

Integrating in React application

Setup Store

WriteAway uses redux and redux-thunk middleware so you need to add redux provider on top level of your application

  import {
    defaultState as writeAwayState,
    reducerKey as writeAwayReducerKey,
    reducer as writeAwayReducer,
    IWriteAwayState
  } from '@writeaway/core';

  /**
   * Configure reducers
   */
  const reducers = combineReducers({
    // Required: Add WriteAway reducer
    [writeAwayReducerKey as '@writeaway']: writeAwayReducer as Reducer<IWriteAwayState>,
    // Options: Add toastr reducer if you use react-redux-toastr. If not, handle react-redux-toastr actions manually in your app to show toasts from WriteAway.  
    toastr, 
    // Add any other application specific reducers
    app: appReducer,
  });

  const defaultAppState = {};

  /**
   * Configure initial default state
   */
  const initialState: IApplicationState = {
    [writeAwayReducerKey]: writeAwayState as IWriteAwayState,
    toastr: undefined as any,
    app: defaultAppState,
  };

  // Compose middlewares
  const middlewares = [
    // WriteAway relies on thunk middleware
    thunk as ThunkMiddleware,
    // Add other middlewares if you need them 
    // sagaMiddleware, 
    // routerMiddleware(history)
  ];

  const enhancers = [applyMiddleware(...middlewares)];
  const store = createStore<IApplicationState, AnyAction, {}, unknown>(
    reducers as any,
    initialState,
    composeWithDevTools({
      name: 'WriteAway React Demo',
      serialize: {
        // If you are using redux devtools you may want to add this snippet to
        // serialize section as WriteAway stores node refences in store
        replacer: (key: string, value: any) => {
          if (value instanceof HTMLElement) { // use your custom data type checker
            return `HTMLElement:${value.tagName}`;
          }
          if (value && value.prototype && value.prototype.isReactComponent) { // use your custom data type checker
            return `IComponent:${(value as any).label}`;
          }
          return value;
        },
      } as any,
    })(...enhancers),
  );
<>
    <Provider store={store}>
      <MyApplication />
    </Provider>
</>

Use React Pieces

When enabling edit mode, render editable pieces with react components from plugins and to render editors.

import { ReactPieceSourceCode } from '@writeaway/plugin-codemirror';
import { ReactPieceBlockBackground, ReactPieceImage, ReactPieceRichText } from '@writeaway/plugin-medium';
import { ReactPieceSeo } from '@writeaway/plugin-seo';

export const App = () => (
  <main>
          <ReactPieceBlockBackground
            id="bg-1"
            name="Background For Rich Text"
            bgColor="#FFcccc"
            className="p-4"
          >
            <article>
              <h2>Rich Text Block</h2>
              <ReactPieceRichText
                id="rich-1"
                name="Rich Text"
                html="<div>Editable Rich Text</div>"
              />
            </article>
          </ReactPieceBlockBackground>
          <ReactPieceBlockBackground
            id="bg-2"
            name="Background For Image"
            bgColor="#ccFFcc"
            className="p-4"
          >
            <article>
              <h2>Image Block</h2>
              <ReactPieceImage
                id="image-1"
                name="image"
                src="https://writeaway.github.io/images/image-06.jpg"
                title="Editable Image"
                alt="Sample Image"
              />
            </article>
          </ReactPieceBlockBackground>
          <ReactPieceBlockBackground
            id="bg-3"
            bgColor="#ccccff"
            name="Background For Source Code Block"
            className="p-4"
            src="https://writeaway.github.io/images/sayagata-400px.png"
          >
            <article>
              <h2>Source Code Block</h2>
              <ReactPieceSourceCode
                id="source-1"
                name="Source edit"
                html={codeStr}
                updateNode
              />
            </article>
          </ReactPieceBlockBackground>
          <article className="p-4">
            <h2>SEO data block</h2>
            <div className="btn">
              <ReactPieceSeo
                id="seo-1"
                name="SEO Data"
                label="Click to Edit SEO Meta Data"
                header="<meta></meta>"
                title="Page Title"
                description="Page Descriptions"
                keywords="Page Keywords"
              />
            </div>
          </article>
</main>);

In the body, render navbar, toast controller, overlay and editors

        <WriteAwayOverlay />
        <WriteAwayNavBar options={
          {
            navBarDraggable: true,
            navBarCollapsable: true,
            pieceNameGroupSeparator: ':',
          }
        }
        />
        <WriteAwayEditors />
        <ReduxToastr
          className="r_toast-container"
          timeOut={4000}
          position="top-right"
        />

WriteAwayEditors is mandatory for editor functionalities as it renders popups and required overlays for editing inside.

WriteAwayOverlay is optional and renders hover effect for nodes

WriteAwayNavBar is optional and renders control panel that has switches for editors

ReduxToastr container is needed if you need to render redux toast messages from WriteAway

Special Actions

Few special redux actions are exposed

    import {
      externalPieceUpdateAction, setAPIAction, setMetaAction
    } from '@writeaway/core';

externalPieceUpdateAction - explicitly updates data of specific node. You can use it for real-time updates of content from WebSockets connection. Note funtionality relies on api.resolveConflicts method that decides if update should be applied.

    // There is a server update of `source-1` node by John Doe 
    dispatch(externalPieceUpdateAction(
        {
          id: 'source-1',
          data: { html: "<div>New HTML</div>" },
          meta: { id: 'user-b', label: 'John Doe', time: Date.now() }
        }
    ));

setAPIAction - sets pieces api dynamically. Usefull when you need to create HTTP instances asyncrously.

 
    dispatch(setAPIAction(
        {
          getPieceData: async (piece: IPieceItem) => fetchPieceFromServer(piece.id),
          /* ... */
        }
    ));

setMetaAction - sets piece meta, that will be attached to pieces u

View on GitHub
GitHub Stars15
CategoryDevelopment
Updated1y ago
Forks3

Languages

HTML

Security Score

55/100

Audited on May 17, 2024

No findings