A Free, Lightweight, And Hackable Open-Source Code Editor For The Web | copenhagen

Copenhagen is a free, lightweight, and hackable open-source code editor for the web. It’s responsible for running the code editing experiment on Autocode, and it’s written entirely in Vanilla JavaScript with only tokens. You can start playing with it yourself directly by following the installation instructions: Show on GitHub or install (fork) on Autocode.

The documents are available at copenhagen.autocode.com. You can also manipulate your installation right away by creating this repository in AutocodeCopenhagen, which is a simple, lightweight, and extensible code editor that supports popular languages ​​like HTML, CSS, JavaScript, JSON, Markdown, and Plain Text.

free code editor, online code editor, atom code editor, sublime text, best code editor for beginners, open source text editor, code editor download

Features:

  • A simple, intuitive API
  • Extensible code completion via typeahead
  • Configurable hotkeys
  • Multi-cursor selection
  • Find and replace
  • Support for large files (currently up to 100kloc)
  • Configurable language settings and highlighting
  • Small package size (50kB minified)
  • Autogrow mode (default) or maximized view
  • Custom autocomplete dropdown support (WIP)
  • Mobile support (WIP)

How to make use of it:

1. Load Copenhagen’s JavaScript and CSS information.

<link rel=”stylesheet” href=”./compiled/copenhagen.min.css”>
<script src=”./compiled/copenhagen.min.js”></script>

2. Create a container for the editor and decide which language you wish to use: “javascript”, “JSON”, “markdown”, “HTML”, “css” and “text”.

<div class="editor" data-language="javascript" data-maxrows="20">
  // JS Code Here
</div>

3. Initialize the Copenhagen editor and finished.

window.addEventListener('DOMContentLoaded', function () {
  var editor = Copenhagen.initSelectorAll('.editor');
});

4. All configurations that may be passed by way of both JavaScript or data-option attributes:

var editor = new Copenhagen.Editor({
    // enable readonly here
    readonly: false,

    // hide the editor
    hidden: false,

    // disable the editor
    booleandisabled: false,

    // determine whether to take up the entirety of the relative parent
    maximized: false,

    // minimum number of rows of the editor
    rows: 1,

    // maximum number of rows of the editor
    rmaxrows: 30,

    // determine whether you can "tab out" of the editor
    tabout: false,

    // disable line numbers here
    nolines: false,

});

5. Add your personal autocomplete to the editor.

function CodeCompleter () {
  this.suggestions = this.generateSuggestions(this.suggestionMap);
};
CodeCompleter.prototype.cursorCharacter = '·';
CodeCompleter.prototype.wildcardWordCharacter = '¤';
CodeCompleter.prototype.wildcardPhraseCharacter = '…';
CodeCompleter.prototype.wildcardReplaceCharacter = '\\$1';
CodeCompleter.prototype.suggestionMap = {
  'javascript': [
    'const ',
    'const ¤ = ',
    'const {…} = ',
    'const […] = ',
    'console.log(`·Got here: A·`);',
    'console.error(`·Error·`);',
    'let ',
    'let ¤ = ',
    'let {…} = ',
    'let […] = ',
    'var ',
    'var ¤ = ',
    'var {…} = ',
    'var […] = ',
    'lib.',
    'module.exports = ',
    'module.exports = async ',
    'return ',
    'require(\'·\')',
    'class ',
    'class ¤ {·}',
    'function ',
    'function (·)',
    'function ¤ (·)',
    'function () {·}',
    'function ¤ () {·}',
    'function (…) {·}',
    'function ¤ (…) {·}',
    'if (·true·)',
    'if () {·}',
    'if (…) {·}',
    'else ',
    'else {·}',
    'else if (·true·)',
    'for (let i = 0; i < ·10·; i++)',
    'for () {·}',
    'for (…) {·}',
    'while (·true·)',
    'while () {·}',
    'while (…) {·}',
    'await ',
    'await lib.',
    'await new Promise((resolve, reject) => {·});',
    'async ',
    'async (·)',
    '() => {·}',
    '(…) => {·}',
    '/**\n * ·\n */',
    '* @param {·}',
    '* @param {…} ·paramName·',
    '* @returns {·}',
    '* @returns {…} ·returnValue·',
    'true',
    'false',
    'null',
    'new ',
    'new Promise((resolve, reject) => {·});',
    'Promise((resolve, reject) => {·});',
    'Promise.all([·]);',
    'setTimeout(() => {·}, 1);',
    'setInterval(() => {·}, 1);',
    'try {·}',
    'catch (e) {·}',
    'catch (…) {·}',
    'throw ',
    'throw new Error(`·Oops!·`);',
    'new Error(`·Oops!·`)',
    'Error(`·Oops!·`)',
    'Error(…)'
  ]
};
CodeCompleter.prototype.generateSuggestions = function () {
  var suggestionMap = this.suggestionMap;
  var cursorCharacter = this.cursorCharacter;
  return Object.keys(suggestionMap).reduce(function (suggestions, language) {
    var phraseList = suggestionMap[language].map(function (value) {
      var cursorStart = value.indexOf(cursorCharacter);
      var cursorEnd = value.lastIndexOf(cursorCharacter);
      var cursorLength = 0;
      if (cursorStart !== cursorEnd) {
        cursorLength = cursorEnd - cursorStart - 1;
        value = value.slice(0, cursorEnd) + value.slice(cursorEnd + 1);
      }
      var adjust = cursorStart === -1
        ? 0
        : cursorStart - value.length + 1;
      if (adjust) {
        value = value.substr(0, value.length + adjust - 1) + value.substr(value.length + adjust);
      }
      return {
        value: value,
        adjust: adjust,
        cursorLength: cursorLength
      };
    }.bind(this));
    suggestions[language] = {
      lookup: this.generateLookupTrie(phraseList),
    };
    return suggestions;
  }.bind(this), {});
};
CodeCompleter.prototype.generateLookupTrie = function (phraseList) {
  var wildcardWord = this.wildcardWordCharacter;
  var wildcardPhrase = this.wildcardPhraseCharacter;
  var root = {};
  var curNode, node, phrase, value;
  var i, j, k;
  for (i = 0; i < phraseList.length; i++) {
    phrase = phraseList[i];
    value = phrase.value;
    for (j = value.length - 1; j >= 0; j--) {
      curNode = root;
      for (k = j; k >= 0; k--) {
        char = value[k];
        curNode[char] = curNode[char] || {};
        if (char === wildcardWord || char === wildcardPhrase) {
          curNode[char][char] = curNode[char][char] || curNode[char];
        }
        curNode = curNode[char];
      }
      curNode.phrases = curNode.phrases || [];
      curNode.phrases.push({
        value: value,
        ranking: i,
        adjust: phrase.adjust,
        cursorLength: phrase.cursorLength,
        re: phrase.re
      });
    }
  }
  return root;
};
CodeCompleter.prototype.complete = function (tree, value, index, subs, inWildcard) {
  index = index || 0;
  subs = subs || [];
  inWildcard = inWildcard || '';
  var wildcardWord = this.wildcardWordCharacter;
  var wildcardPhrase = this.wildcardPhraseCharacter;
  var wildcardReplace = this.wildcardReplaceCharacter;
  var char;
  var results = [];
  var node = tree;
  for (var i = value.length - 1; i >= 0; i--) {
    index++;
    var char = value[i];
    if (node[wildcardWord]) {
      if (char.match(/[0-9a-z_$]/i)) {
        var newSubs = subs.slice();
        if (inWildcard) {
          newSubs[0] = char + newSubs[0];
        } else {
          newSubs.unshift(char);
        }
        results = results.concat(
          this.complete(node[wildcardWord], value.substr(0, i), index - 1, newSubs, wildcardWord)
        );
      }
    }
    if (node[wildcardPhrase]) {
      if (char.match(/[^\(\)\[\]\{\}\"\'\`]/i)) {
        var newSubs = subs.slice();
        if (inWildcard) {
          newSubs[0] = char + newSubs[0];
        } else {
          newSubs.unshift(char);
        }
        results = results.concat(
          this.complete(node[wildcardPhrase], value.substr(0, i), index - 1, newSubs, wildcardPhrase)
        );
      }
    }
    if (node[char]) {
      inWildcard = '';
      if (node.phrases && (char === ' ')) {
        results = results.concat(
          node.phrases.map(function (p) {
            var curSubs = subs.slice();
            return {
              value: p.value.replace(
                new RegExp('(' + [wildcardWord, wildcardPhrase, wildcardReplace].join('|') + ')', 'gi'),
                function ($0) { return curSubs.shift() || ''; }
              ),
              ranking: p.ranking,
              adjust: p.adjust,
              offset: index - 1 + subs.join('').length,
              cursorLength: p.cursorLength
            };
          })
        );
      }
      node = node[char];
    } else {
      break;
    }
  }
  if (node.phrases && (i < 0 || value[i] === ' ')) {
    (i < 0) && index++;
    results = results.concat(
      node.phrases.map(function (p) {
        var curSubs = subs.slice();
        return {
          value: p.value.replace(
            new RegExp('(' + [wildcardWord, wildcardPhrase, wildcardReplace].join('|') + ')', 'gi'),
            function ($0) { return curSubs.shift() || ''; }
          ),
          ranking: p.ranking,
          adjust: p.adjust,
          offset: index - 1 + subs.join('').length,
          cursorLength: p.cursorLength
        };
      })
    );
  }
  return results
    .sort(function (p1, p2) { return p2.offset - p1.offset || p1.ranking - p2.ranking; })
    .filter(function (p) { return p.offset < p.value.length; });
};
CodeCompleter.protot

6. API strategies.

// Create a custom autocompletion detector to add your own autocomplete box
editor.addAutocomplete(name, function(editor, selection, inString, inComment){
// ...
})

// Add custom hotkeys
editor.addHotkey(keys, function(value, cursors){
// ...
})

// Disable animation
editor.animateNo()

// Blur the editor
editor.blur()

// Enable autocomplete
editor.canSuggest()

// Clear history
editor.clearHistory()

// Clear meta data
editor.clearMetadata(metadata)

// Disable
editor.disable()

// Emulate a user action
editor.emulateUserAction(userAction)

// Enable
editor.enable()

// Show find and replace dialog
editor.find(value)

// Find the complement of a character at a specific index based on the language dictionary
editor.findComplements(value, index)

// Set focus to the editor
editor.focus()

// Retrieve the active formatter function based on the active language
editor.getActiveFormatter()

// Retrieve the currently active language for the editor
editor.getActiveLanguage()

// Retrieve the currently active language dictionary for the editor
editor.getActiveLanguageDictionary()

// Retrieves the formatter function for a language or return the text formatter if it is not found
editor.getFormatter(language)

// Retrieve metadata from the editor
editor.getMetadata(metadata, defaultValue)

// Retrieve the current value of the editor
editor.getValue()

// Navigate the user action history
editor.gotoHistory(amount)

// Determine whether the editor is focused
editor.hasFocus()

// Hide the editor
editor.hide()

// Determine whether a specific character index is within a comment or not based on the language dictionary
editor.inComment(index)

// Determine whether a specific character index is within a string or not based on the language dictionary.
editor.inString(index)

// Retrieve the current read-only status of the editor.
editor.isReadOnly()

// Open the editor instance
editor.open(element, focus, replaceText)

// Remove an autocompletion detector
editor.removeAutocomplete()

// Remove a hotkey handler
editor.removeHotkey(hotkey)

// Render the editor on the next available frame
editor.render(value, forceRender)

// Dispatches a "save" event and creates a history entry if the user has performed an action
editor.save(value)

// Scrolls the editor by a visible "page" amount based on the height of the editor
// "up" or "down"
editor.scrollPage(direction)

// Scrolls to the currently selected text in the editor
editor.scrollToText()

// Scrolls to a specific line index in the editor
editor.scrollToLine(index)

// Scrolls the editor to a specific (x, y) coordinate from the top left of the editor
editor.scrollTo(x, y)

// Select text in the editor at a specific start and end index
editor.select(start, end)

// Set emulation mode.
editor.setEmulationMode(true/false)

// Set an error state in the editor
editor.setError(lineIndex, column)

// Set a custom formatter for a language
editor.setFormatter(language, function(){
// ...
})

// Set the language
editor.setLanguage(language)

// Set maximized mode on the editor so that it takes up all of its relative parent's height
editor.setMaximized(true/false)

// Sets metadata on the editor
editor.setMetadata(metadata, value)

// Set read-only mode on the editor
editor.setReadOnly(true/false)

// Set the value of the editor
editor.setValue(value)

// Show the editor
editor.show()

// Perform a user action
editor.userAction(userAction)

Simple Extensible Code Editor, Copenhagen Editor Plugin/Github

code-copenhagen-editor


See Demo And Download

Official Website(acode): Click Here

This superior jQuery/javascript plugin is developed by acode. For extra advanced usage, please go to the official website.

Related Posts

Cookie-Consent-Using-Bootstrap

How to Create a Simple Cookie Banner Consent Using Bootstrap 4

Cookie Consent Popup Javascript – Quick and simple tutorial for creating a simple Bootstrap cookie banner. If you have a website or blog with people visiting or…

Create-HTML-Terminals

Create Custom HTML Terminals With Pure JavaScript | shell.js

Custom HTML Terminals is A JavaScript library to create HTML terminals on web pages. The shell js JavaScript library offers a straightforward method to create Ubuntu, OS X,…

Bootstrap-Alert-Bootbox

Bootstrap Alert, Confirm, and Flexible Dialog Boxes | Bootbox

Bootbox.js is a small JavaScript library that allows you to create programming dialogs using Bootstrap templates, without having to worry about creating, managing, or removing any required…

Slider-fg-carousel

An Accessible Touch-enabled Slider Web Component | fg-carousel

fg-carousel Slider – A simple & modern slider web component to create versatile, accessible, touch-enabled picture carousels utilizing CSS scroll snap, Custom Element, and Intersection Observer API….

Tags-Input-Component

A Lightweight and Efficient Tags Input Component in Vanilla JS | tagify

tagify transforms an input field or textarea into a tags component, in an easy and customizable way, with great performance and a small code footprint, full of…

copy-to-clipboard-javascript

A Lightweight Library to Copy Text to Clipboard | CopyJS

CopyJS is a lightweight JavaScript library that allows you to copy plain text or HTML content to the clipboard. Must Read: Tiny Library for Copy Text In…