Sweeten your JavaScript.

Overview

Build Status

Join the chat at https://gitter.im/mozilla/sweet.js

Hygienic Macros for JavaScript!

Macros allow you to build the language of your dreams. Sweeten JavaScript by defining new syntax for your code.

Currently, Sweet should be considered experimental and under heavy development (re-development more like). As such, the API will be undergoing a bit of churn until probably the end of the year. So, probably best not to try Sweet in production systems just yet. If you're interested in helping out though we'd love to have you!

Getting started

Install the command line app with npm:

$ npm install -g @sweet-js/cli

Write your sweet code:

syntax hi = function (ctx) {
  return #`console.log('hello, world!')`;
}
hi

And compile:

$ sjs my_sweet_code.js
console.log('hello, world!')

Learning More

Comments
  • Add Readtables back

    Add Readtables back

    Again, apologies for the vague issue, but:

    1. Do readtables exist? If so where are they documented? (Better: some simple examples?)
    2. If not, then make this a feature request to have them...
    type: feature 
    opened by elibarzilay 48
  • Infix progress

    Infix progress

    This is an ongoing PR to track the progress of infix macros. Please chime in at any point. I've broken it down into goals that I'll periodically update so you can see how far along it is:

    • [x] Refactor the macro macro to translate infix rules into infix cases.
    • [x] Refactor syntaxCase to understand the infix form and matching semantics.
    • [x] Add "reverse" support to the pattern matcher (return a shallow-reversed pattern tree)
    • [x] Plumb together enforest and expandTermTree to keep track of previous syntax/terms.
    • [x] Plumb the previous syntax/terms into the macro transformers.
    • [x] Rewrite enforestVarStatement so we can lookbehind match on var assignment
    • [x] Fix withSyntax which is broken for some reason
    • [x] Fix for-let enforestation/hygiene
    • [x] Test cases

    For the time being, I'm using the following form for infix macros because it's the easiest to parse (anything before the bar is lookbehind, anything after is business as usual):

    macro foo {
      rule infix { $lhs | $rhs } => { ... }
      case infix { $lhs | $name $rhs } => { ... }
    }
    

    Another proposed forms for infix cases:

    macro foo {
      rule infix { $lhs | $rhs } => { ... }
      case infix { $lhs |$name| $rhs } => { ... }
    }
    

    And @disnet liked the haskelly:

    macro foo {
      rule infix { $lhs | $rhs } => { ... }
      case infix { $lhs `$name` $rhs } => { ... }
    }
    
    opened by natefaubion 29
  • Extendable syntaxes

    Extendable syntaxes

    Extendable syntaxes would allow for:

    • the usage of independently written macros with the same name, provided that they're used in different contexts
    • the inline extension of an imported macro without forking a module
    • anything that requires backtracking, such as the macro syntax

    The most natural implementation I can think of would be to allow syntax functions to return null, after which the reader tracks back and tries the previous macro with the same name:

    syntax each = ctx => {
        let variable = ctx.next("expr").value,
            OF = ctx.next().value,
            iterable = ctx.next("expr").value,
            body = ctx.next().value
    
        if (variable && iterable && OF.isIdentifier("of") && body.isBraces()) {
            return #`for (${variable} ${OF} ${iterable}) ${body}`
        }
    
    }
    syntax each = ctx => {
        let iterable = ctx.next("expr").value,
            body = ctx.next().value
    
        if (iterable && body.isBraces()) {
            return #`for ($_ of ${iterable}) ${body}` // yeah this wouldn't work because of hygiene
        }
    }
    
    each x of y {
        x()
    }
    
    each y {
        $_()
    }
    

    This would cover a lot of the same ground as readtables.

    opened by bopjesvla 27
  • add

    add "macros" option to install global macros in compile API

    This is a quick tweak to the compile API that lets you pass in additional macros to install globally. This difference between this and simply concat'ing sources is that this generates correct source map information.

    I haven't reflected this in sjs.js, which we probably should do. Whatever is passed to -m should probably use this. I'm writing my own Grunt plugin to use it so I just need the lower-level support.

    Additionally, in my Grunt plugin I'm automatically adding require('source-map-support').install(); at the beginning of the generated source, which nicely makes node use the sourcemaps in stack traces automatically. It might be worth adding an option to sjs for this as well. (I'll publish my grunt plugin at some point)

    Let me know what you think about this, I can continue to tweak this PR based on feedback.

    opened by jlongster 27
  • wiki pseduo-code algorithm for regex literal identification

    wiki pseduo-code algorithm for regex literal identification

    The pseudo-code and accompanying text here:

    https://github.com/mozilla/sweet.js/wiki/design

    ... mentions needing to look for a function declaration vs. a function expression, in terms of determining if a regex-literal can follow a ) character. The text there never seems to address the coming => fat arrow function syntax, only looking for the actual "function" keyword.

    I'm just wondering if your code handles that detail and the wiki needs to be updated, or if that detail is not yet addressed?

    type: bug 
    opened by getify 26
  • Implement tokenization via readtables

    Implement tokenization via readtables

    Note: This work is definitely not complete, functional or ready to be merged.

    This is my first (published) pass at a readtable implementation. It isn't hooked into the pipeline yet but does show the general strategy and initial API. Per some previous discussions https://github.com/sweet-js/sweet.js/issues/535#issuecomment-242791944 I've intentionally implemented a very limited API (utility libs can build on these).

    Readtables can currently be created as follows:

    import { defaultReadtable } from 'src/readtable';
    import CharStream from 'src/char-stream';
    
    const newTable = defaultReadtable.extendReadtable({
      key: '@',
      action(stream) {
        return {
          type: 'Punctuator',
          value: stream.readString(),
          locationInfo: stream.locationInfo
        };
      }
    });
    
    const entry = newTable.getEntry('@');
    const stream = new CharStream('@foo');
    entry.action(stream);
    // =>
    // {
    //   type: 'Punctuator',
    //   value: '@',
    //   locationInfo: {
    //     filename: '',
    //     line: 0,
    //     column: 0,
    //     position: 0
    //   }
    // }
    

    The intention is to allow lookbehind of already read tokens. I'll have to implement this for '/' resolution. So the signature of action will be action(stream: CharStream, prefix: TokenTree?). TokenTree = Token | List<TokenTree>.

    I have not implemented Racket style reader modes as I believe they can be build using the current primitives (i.e. by referencing other readtables in a closure).

    As a note, I'm using some "private" fields (denoted by a _ prefix). I'm reserving the right to truly hide them in the future if there is a reason and efficiencies don't suffer too greatly. So their presence shouldn't be relied upon and shouldn't be part of the public API.

    @disnet I'd appreciate some feedback as soon as you get the chance. I'm going to have a lot of time the next few days to hack on this and don't want to go too far down the wrong path.

    opened by gabejohnson 21
  • Optional syntax

    Optional syntax

    I have a macro

    macro iterate {
    
      // iterate (value: index from items)
    
      rule { ($($key:ident : $value:ident from $dict:expr)) { $body... } }   => { 
        let dict = $dict;
        let keys = Object.keys(dict);
        let length = keys.length;
        let index = 0;
        while (index < length) {
          let $key = keys[index];
          if (!dict.hasOwnProperty($key)) { continue; }
          let $value = dict[$key];
          $body...
          index++;
        }
        dict = undefined;
        keys = undefined;
      }
    }
    

    which allows for

    iterate (key:value from {a: 1, b: 2}) {
      ...
    }
    

    If I use this twice in a row however, jshint complains that I'm re-declaring the variable, and Firefox (this is code for an extension, so it's chrome-javascript, not web-javascript) complains TypeError: redeclaration of variable key. Is there a way to rewrite this so I could do

    iterate (var key: var value from {a: 1, b: 2})
    iterate (key: let value from {a: 1, b: 2})
    

    and follow the hints provided by the var/let to declare (or not) key and value using these?

    opened by retorquere 21
  • Add backquote and comma macros

    Add backquote and comma macros

    It would be helpful to have backquote and comma style macros. My lisp macro knowledge is a bit rusty, but the following code could be more concisely expressed.

     it "should support withSyntax with repeaters" {
        macro m {
            case {_ $x } => {
                return withSyntax($y ... = [makeValue(10, #{here}),
                                                          makePunc('+', #{here}),
                                                          makeValue(20, #{here})],
                                                          $z = [makeValue(30, #{here})]) {
                      return #{$x + $y ... + $z}
                }
           }
        }
        expect(m 5).to.be(65);
    }
    

    as

     it "should support withSyntax with repeaters" {
        macro m {
            case {_ $x } => {
                return  [` #,$x 10 + 20, 30`] 
    
        }
        expect(m 5).to.be(65);
    }
    

    That might a too simple example. instead of comma, I used #, to splice the token $x in.

    type: breaking change 
    opened by paddymul 20
  • ES6 module integration

    ES6 module integration

    First stab. Very much work in progress but you can (sort of) import compiletime code (macros) and import runtime code for use in macros.

    Lots more to do:

    • test coverage
    • more correct import and export syntax
    • better registering of import statements
    • import for templates and arbitrary phases
    • integrate into sjs (it only runs via grunt single atm)

    Some design questions that still need to be hashed out:

    npm integration

    I know @natefaubion has thought a lot about this but basically there's a question of when should we actually expand module from an import. Since lot's of modules won't have compiletime exports we could avoid the expense of expansion for the "common" case when you just want to import runtime code (either for use in a macro body or otherwise).

    There's a few obvious ways of doing this:

    1. special import forms signaling your intention/belief about the compiletime status of the imported names
    2. special folder to place source that includes compiletime values (say "macros/")
    3. file/folder pattern in package.json to signify which source files might contain compiletime values

    Option 1 is not good because the user of a library shouldn't know how a form is implemented to use it.

    Options 2 and 3 bug me because they both rely on macro package authors to know about this (what is at the end of the day) optimization detail.

    Ah! As I was typing this out I thought of a fourth option. Use a pragma at the beginning of all sweet.js sources. This makes it easy to determine if the code might need to be expanded. I think we want to do this anyway as a way of following Racket's tower of languages one day:

    #lang "js"
    
    // ...
    

    Eventually we can make this tie into readtables and all the custom language stuff.

    what to compile for runtime import?

    After we expand all the macros away what should we do with the runtime import? Options:

    1. do nothing, import is only for macros. have authors write their own CJS/AMD require statements
    2. emit node require statements
    3. do everything es6-module-transpiler does
    4. leave imports and use es6-module-transpiler as a backend

    I think 4 is the best. Not sure if escodegen supports import and export yet so might need to get that working first. Perhaps 1 to begin with and 4 as the end goal?

    opened by disnet 19
  • Potential fix for issue #232.

    Potential fix for issue #232.

    The fix is a memoization approach for the expensive recursive resolveCtx function. Although I'm not 100% confident that the memoization approach is correct (though intuitively it feels correct to me), at least all the tests pass ... which I take to mean that the memoized resolveCtx is properly generating hygienic code in the known cases. It certainly does that for the example given in issue #232 without incurring exponential time.

    opened by srikumarks 17
  • Error when using `fromString`

    Error when using `fromString`

    Trying to take operators like < and return something like { op: "<" }:

    syntax foo = function(ctx) {
      const op = ctx.next().value;
      const x = #`dummy`.get(0);
      return #`{ op: ${x.fromString(op.val())} }`;
    }
    
    foo +=;
    

    The above fails with Error: [assertion error]: all tokens must have line info.

    Just doing #{ op: null } works as well as #${x.fromString(op.val())} } so it's a weird combination of the two.

    type: bug 
    opened by jlongster 16
  • Variable binding (hygiene, gensym) not working in 2-level macros

    Variable binding (hygiene, gensym) not working in 2-level macros

    Variable binding in a 2-layer macro (i.e., a macro that calls another macro) is broken, in several cases I've tested.

    Here's a fairly simple one (simpler than what I was using, but still clearly demonstrates the problem):

    syntax shallow = function(ctx) {
        let name = ctx.next().value
        let val = ctx.next().value
        return #`let ${name} = ${val}`
    }
    
    syntax deep = function(ctx) {
        let name = ctx.next().value
        return #`shallow ${name} 42`
    }
    
    shallow foo 42
    deep bar
    
    console.log(foo)
    console.log(bar)
    

    This should result in the value "42" being printed twice to stdout, but will actually result in a ReferenceError on the second console.log. The reason for this, is that Sweet.js expands it to the following code:

    let foo_13 = 42;
    let bar_14 = 42;
    console.log(foo_13);
    console.log(bar);
    

    That deep bar appears to be misbehaving, as the identifier bar is not picked up later on, during the console.log(bar) call.

    opened by HeatherSoron 2
  • Let's fork the project!

    Let's fork the project!

    Last commit is from 2 years ago... Having macros in javascript and typescript is awesome, and we are the most popular programming language in the world! Aren't we capable of forking and maintaining this fundamental project? Any volunteers?

    opened by LifeIsStrange 4
  • [Question] How to render a dynamic expression inside a function?

    [Question] How to render a dynamic expression inside a function?

    Hi, I'm trying to render a dynamic expression inside a function but I was not successful so far (Error: Not implemented yet [object Object]), I'm I missing something or is it not possible in the first place ?

    Here is my example in more details.

    Thanks,

    opened by VBUZZE 0
  • Import not working

    Import not working

    I can use sweet.js fine for most use cases, but any time I try to use imports from standard libraries, it fails to work. Here's an example from the documentation:

    import { isStringLiteral } from '@sweet-js/helpers' for syntax;
    
    syntax m = ctx => {
      return isStringLiteral(ctx.next().value) ? #`'a string'` : #`'not a string'`;
    };
    m 'foo'
    

    the error I get when I try to complie:

    evalmachine.<anonymous>:5
        return isStringLiteral(ctx_1.next().value) ? syntaxTemplate(1) : syntaxTemplate(2);
        ^
    
    ReferenceError: isStringLiteral is not defined
        at ctx_1 (evalmachine.<anonymous>:5:5)
        at Enforester.expandMacro (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/enforester.js:1981:87)
        at Enforester.enforestStatement (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/enforester.js:349:12)
        at Enforester.enforestModuleItem (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/enforester.js:136:17)
        at Enforester.enforestBody (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/enforester.js:123:17)
        at Enforester.enforestModule (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/enforester.js:119:17)
        at Enforester.enforest (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/enforester.js:109:21)
        at TokenExpander.expand (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/token-expander.js:133:37)
        at Compiler.compile (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/compiler.js:50:26)
        at NodeLoader.compileSource (/usr/local/lib/node_modules/@sweet-js/cli/node_modules/@sweet-js/core/dist/sweet-loader.js:211:53)
    
    opened by brandonmack111 4
Releases(v3.0.13)
  • v3.0.13(Jul 19, 2017)

  • v3.0.12(Jul 17, 2017)

  • v3.0.11(Jul 6, 2017)

  • v3.0.10(Jun 12, 2017)

  • v3.0.9(Jun 11, 2017)

  • v3.0.8(May 31, 2017)

  • v3.0.7(May 21, 2017)

  • v3.0.5(May 20, 2017)

  • v3.0.3(Apr 19, 2017)

  • v3.0.2(Apr 18, 2017)

  • v3.0.1(Apr 17, 2017)

  • v3.0.0(Apr 10, 2017)

    Breaking changes:

    • places in a macro where you used to get a Syntax you now get Term
      • ctx.next().value is a Term instead of a TermOrSyntaxWrapper
      • indexing a syntax template gets a RawSyntax instead of a Syntax
    • ctx.contextify() new method instead of .inner() method on the wrapper
    • compile now takes a path and loader instead of just the source to compile

    New Features:

    • custom operators
    • helper library
    • readtables
      • internal only, not exposed to macro authors yet
    • recursive module loading
    • console/process added to syntax scope in node
    • loader API

    And lot's of bug fixes.

    More details in the announcement.

    Source code(tar.gz)
    Source code(zip)
  • v2.2.1(Sep 5, 2016)

  • v2.2.0(Aug 22, 2016)

  • v2.1.0(Aug 7, 2016)

    Additions

    Includes #566 which allows programmatic construction of syntax objects in macros:

    syntax to_str = ctx => {
      let argStr = ctx.next().value.val();
      let dummy = #`here`.get(0);
    
      return #`${dummy.fromString(argStr)}`;
    }
    let s = to_str foo
    // expands to:
    // let s = 'foo'
    
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jul 2, 2016)

    Breaking Changes

    The macro context API has changed. Before you could call ctx.next('expr') to expand until an expression was matched but now this has been separated out into the expand method. The expand method now also understands a lot more grammar productions:

    • Statement with alias stmt
    • AssignmentExpression with alias expr
    • Expression
    • BlockStatement
    • WhileStatement
    • IfStatement
    • ForStatement
    • SwitchStatement
    • BreakStatement
    • ContinueStatement
    • DebuggerStatement
    • WithStatement
    • TryStatement
    • ThrowStatement
    • ClassDeclaration
    • FunctionDeclaration
    • LabeledStatement
    • VariableDeclarationStatement
    • ReturnStatement
    • ExpressionStatement
    • YieldExpression
    • ClassExpression
    • ArrowExpression
    • NewExpression
    • ThisExpression
    • FunctionExpression
    • IdentifierExpression
    • LiteralNumericExpression
    • LiteralInfinityExpression
    • LiteralStringExpression
    • TemplateExpression
    • LiteralBooleanExpression
    • LiteralNullExpression
    • LiteralRegExpExpression
    • ObjectExpression
    • ArrayExpression
    • UnaryExpression
    • UpdateExpression
    • BinaryExpression
    • StaticMemberExpression
    • ComputedMemberExpression
    • AssignmentExpression
    • CompoundAssignmentExpression
    • ConditionalExpression

    In addition, the macro context now has a reset method that resets the iterator. The interface is now:

    TransformerContext = {
      name: () -> Syntax
      next: () -> {
        done: boolean,
        value: Syntax
      }
      expand: (string) -> {
        done: boolean,
        value: Syntax
      }
      reset: () -> undefined
    }
    
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 13, 2016)

    This is the first release with support for phases!

    // log.js
    #lang 'sweet.js';
    
    export function log(msg) {
      console.log(msg);
    }
    
    // main.js
    import { log } from './log.js' for syntax;
    
    syntax m = ctx => {
      log('doing some Sweet things');
      // ...
    }
    

    Phasing is currently only supported for modules with the #lang 'sweet.js' pragma.

    More details in the tutorial.

    Source code(tar.gz)
    Source code(zip)
  • v0.7.4(Feb 9, 2015)

  • v0.7.3(Jan 5, 2015)

    • editor cleanup #439
    • localExpand #310
    • case and rule interleaving #428
    • stack overflow bugfix #309

    local expand

    The experimental function localExpand is now available to case macros. Local expand allows you to force expansion of macros inside of another macro.

    macro PI { rule {} => { 3.14159 }}
    
    macro ex {
      case { { $toks ... } } => {
        var expanded = localExpand(#{$toks ...});
        assert(unwrapSyntax(expanded[0]) === 3.14159)
        return expanded;
      }
    }
    
    ex { PI }
    

    From PR #310.

    case and rule interleaving

    Case and rule macros can now be interleaved:

    macro m {
        rule {  ( $toks ... ) } => { /* handle () as a rule */ }
        case {_ { $toksn... } } => { /* handle {} as a case */ }
    }
    

    From PR #428

    Source code(tar.gz)
    Source code(zip)
  • 0.7.2(Oct 26, 2014)

  • v0.7.1(Aug 19, 2014)

  • v0.7.0(Jul 1, 2014)

  • v0.6.1(Jun 23, 2014)

    Mostly just bug fixes with a couple of minor changes.

    Changes

    • added --version flag to sjs #320
    • you can now name pattern groups. See the docs #325
    • the experimental macroclass syntax has been cleaned up a little. #350

    Bugs

    • #316, #322, #335, #330, #345, #347, #346, #348, #344, #349, #337, #351

    Dev

    You can now fuzz sweet.js with grunt fuzz.

    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(May 4, 2014)

    New Features

    New Documentation

    The documentation for sweet.js has been moved from the home page to its own home here. Lots of changes including sections on features (like literal patterns, :invoke, and the compiler API) that had not been documented yet.

    Custom Operators #296

    Full documentation is here. Allows you to create custom operators with their own precedence and associativity:

    operator (^^) 14 right 
        { $base, $exp } => #{ Math.pow($base, $exp) }
    
    y + x ^^ 10 ^^ 100 - z
    // expands to:
    // y + Math.pow(x, Math.pow(10, 100)) - z;
    

    Loading macros modules in node #295

    Full documentation is here. The basic idea is you can now load macro modules in node (like using the -m flag on the command line).

    // load sweet.js as a library
    var sweet = require('sweet.js');
    // load all `export`ed macros in macros/str.sjs
    sweet.loadMacro('./macros/str');
    // test.sjs can use the macros defined in macros/str.sjs
    require('./test.sjs');
    

    Custom Pattern Classes #203

    Full documentation here. Allows you to abstract pattern classes at a more declarative level than just using :invoke directly. The syntax is very experimental at the moment so try it out but don't rely on it just yet.

    // define the cond_clause pattern class
    macroclass cond_clause {
        pattern { $check:expr => $body:expr }
    }
    
    macro cond {
      rule { $first:cond_clause $rest:cond_clause ... } => {
        // sub-pattern variables in the custom class are 
        // referenced by concatenation
        if ($first$check) {
          $first$body
        } $(else if ($rest$check) {
          $rest$body
        }) ...
      }
    }
    
    cond
      x < 3  => console.log("less than 3")
      x == 3 => console.log("3")
      x > 3  => console.log("greater than 3")
    // expands to:
    // if (x < 3) {
    //     console.log('less than 3');
    // } else if (x == 3) {
    //     console.log('3');
    // } else if (x > 3) {
    //     console.log('greater than 3');
    // }
    

    Changes

    :invoke is no longer recursive by default. If you want recursive behavior use :invokeRec. :invokeOnce no longer exists.

    Bugs And Performance Fixes

    • #232/#303 pref for resolve
    • #291 restrict positions of macro
    • #301/#283 reader edge cases
    • #308 yield/new are now operators
    • #306 multi token export now works
    Source code(tar.gz)
    Source code(zip)
  • v.0.5.0(Mar 10, 2014)

    New feature!

    You can now define custom pattern classes (like :expr) with the new :invoke/:invokeOnce class which inserts the parametrized macro into the token stream before matching the pattern.

    macro color {
      rule { red } => { red }
      rule { green } => { green }
      rule { blue } => { blue }
    }
    macro colors_options {
      rule { ($opt:invoke(color) ...) } => { ... }
    }
    // you can also use a shorthand that automatically inserts invoke:
    macro colors_options {
      rule { ($opt:color ...) } => { ... }
    }
    

    More details at #244.

    Change:

    When defining multi-token macros you must now surround the tokens with parens to prevent ambiguity:

    macro (number?) {
        rule { $x } => {
            typeof $x === "number";
        }
    }
    

    See #258 for discussion.

    Bugs squashed: #231, #256, #259, #257, #258, #260, #264, #272, #274, #275

    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(Feb 14, 2014)

    Bugs squashed:

    #206, #209, #208, #211, #220, #219, #229, #230, #247, #234, #238, #252, #253.

    Two mini features have been added. One is #237, a shorthand form of withSyntax:

    macro m {
      case {_ () } => {
        return withSyntax ($x = [makeValue(42, #{here})]) #{ $x }
      }
    }
    

    And the other #227 sets up the resolve path correctly letting you expand a macro into a call to resolve.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Jan 17, 2014)

Enjoy creating cover image for your hashnode blog like never before, get started in seconds 🎉

Slickr ✨️ View Demo · Report Bug · Request Feature Introducing Slickr ✌️ Slick is the most powerful and the easiest app to create beautiful cover imag

Savio Martin 469 Dec 21, 2022
Create elegant screenshots of your source code. Built with SolidJS

Create elegant code screenshots of your source code. Introduction CodeImage is the newest tool to help developers to create beautiful screenshots of t

Riccardo Perra 602 Jan 3, 2023
Pinging.net - Monitor Your Internet Connection

Pinging.net Pinging.net quickly determines if you are online by running multiple tests. It then continues to monitor your connection via repeated test

Ben Hansen 41 Nov 27, 2022
Customize your README.md file with ready-to-use sections in a simple way with the web editor

myreadme Customize your README.md file with ready-to-use sections in a simple way with the web editor Docker version Docker Hub docker run -p 7000:300

Nelson Hernández 7 Jul 25, 2022
The next generation Javascript WYSIWYG HTML Editor.

Froala Editor V3 Froala WYSIWYG HTML Editor is one of the most powerful JavaScript rich text editors ever. Slim - only add the plugins that you need (

Froala 5k Jan 1, 2023
JavaScript port of Vim

Vim.js : JavaScript port of Vim A Tool/Toy for Non-Beginners by Lu Wang Try it online Variations NW.js Firefox extension Asyncify Streamline.js Recomm

Lu Wang 4.5k Dec 30, 2022
The world's #1 JavaScript library for rich text editing. Available for React, Vue and Angular

TinyMCE TinyMCE is the world's most advanced open source core rich text editor. Trusted by millions of developers, and used by some of the world's lar

Tiny 12.4k Jan 4, 2023
A lightweight and amazing WYSIWYG JavaScript editor - 20kB only (8kB gzip)

Supporting Trumbowyg Trumbowyg is an MIT-licensed open source project and completely free to use. However, the amount of effort needed to maintain and

Alexandre Demode 3.8k Jan 7, 2023
A simple, beautiful, and embeddable JavaScript Markdown editor. Delightful editing for beginners and experts alike. Features built-in autosaving and spell checking.

SimpleMDE - Markdown Editor A drop-in JavaScript textarea replacement for writing beautiful and understandable Markdown. The WYSIWYG-esque editor allo

Sparksuite 9.3k Jan 4, 2023
ppo is a super small and useful utils library for JavaScript 🐝🐜

Overview Every frontend developer has written his own utils library, and we often write methods that are easily forgotten and highly used. ppo is a su

anonymous namespace 105 Jul 21, 2022
A powerful WYSIWYG rich text web editor by pure javascript

KothingEditor A powerful WYSIWYG rich text web editor by pure javascript Demo : kothing.github.io/editor The KothingEditor is a lightweight, flexible,

Kothing 34 Dec 25, 2022
Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.

Importmap for Rails Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling. Installation ... Usage ... License Im

Ruby on Rails 795 Jan 7, 2023
Collaborative JavaScript Debugging App

IMPORTANT: this current version of jsbin (v4.x.x) is no longer actively maintained and the new version of jsbin (v5) is currently in active developmen

Dave, The Bin Bot 4.3k Jan 3, 2023
Projeto voltado para aplicação de conhecimentos referente a manipulação da árvore DOM via JavaScript.

Adivinha-número Opa oi oi! Trago aqui um projeto que fiz visando aplicar e testar meus conhecimentos de manipulação da árvore DOM via JavaScript. Você

Gabriel Rodrigues 0 May 7, 2022
Pure javascript based WYSIWYG html editor, with no dependencies.

SunEditor Pure javscript based WYSIWYG web editor, with no dependencies Demo : suneditor.com The Suneditor is a lightweight, flexible, customizable WY

Yi JiHong 1.1k Jan 2, 2023
Seamlessly connect your web server to Rebrandly so that you can re-use your domain name for both your app and your short links

rebrandly-express Seamlessly connect your web server to Rebrandly so that you can re-use your domain name for both your app and your short links Rebra

null 3 Dec 13, 2022
portfolio-project is a npm package to automatically update your projects section in your portfolio website. It will fetch the selected repositories directly from your GitHub account.

portfolio-project Those days of manually updating portfolio website after every new project made are gone ⚡ Yesss . . . you read that right. ?? portfo

Gaurav Gulati 15 Aug 3, 2021
null 8 Nov 11, 2022
This site compares your GitHub Profile to your friends, and analyses and tells your GitHub profile score too.

GitHub ⚔️ Duel Deployed at ?? : https://githubduel.vercel.app/ Compare your GitHub profiles with your friends It gives score to GitHub profile based o

Anshuman swain 17 Nov 21, 2022