<section id="app" class="section">
  <div class="container">
    <div class="columns is-centerd">
      <div class="column">
        <h1 class="title has-text-centered">Bookmarklet Maker</h1>
      </div>
    </div>
    <div class="columns">
      <div class="column">
        <form class="box">
          <div class="field">
            <div class="field-label">
              <label class="label">Title</label>
            </div>
            <div class="control">
              <input class="input" type="text"  v-model="title" />
            </div>
          </div>
          <div class="field">
            <div class="field-label is-normal">
              <label class="label">Script</label>
            </div>
            <div class="control">
              <textarea id="input-text" class="textarea" v-model="inputCode" placeholder="Input your script here." autocomplete="off"></textarea>
            </div>
          </div>
          <div class="field">
             <div class="field-label is-normal">
              <label class="label">bookmark URL</label>
            </div>
           <div class="control is-expanded">
              <textarea id="out-text" v-bind:class="[textareaClass, resultClass]" v-model="encodedOutputCode" readonly placeholder="Input your code here"></textarea>
            </div>
          </div>
          <div class="field is-grouped">
            <a class="button" v-bind:href="outputCode">{{ title }}</a>
          </div>
          <div class="notification">
            Please drag the above button to the bookmark bar or edit the bookmark and enter the bookmark URL.
          </div>
        </form>
      </div>
    </div>
  </div>
</section>
h1.title {
  font-size: 1.5rem;
}

#app {
  min-height: 100vh;
  background: #10c1a2;
}

label.label {
  text-align: left;
}
const vue = new Vue({
  el: "#app",
  data: {
    title: 'Hello',
    inputCode: '{\n  const message = "Hello World"\n  alert(`👋 ${message}`)\n}',
    textareaClass: "textarea",
    isError: false,
    outputCode: "#",
    errorText: ""
  },
  computed: {
    resultClass() {
      return this.isError ? "is-danger" : "is-success";
    },
    encodedOutputCode() {
      return this.isError ? this.errorText : encodeURI(this.outputCode);
    }
  },
  watch: {
    inputCode: {
      immediate: true,
      handler: function() {
        const result = UglifyJS.minify(this.inputCode);
        if (result.error) {
          this.isError = true;
          this.errorText = result.error;
        } else {
          this.isError = false;
          this.outputCode = `javascript:${result.code}`;
        }
      }
    }
  },
  methods: {}
});
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css
  2. https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js
  2. https://s3-us-west-2.amazonaws.com/s.cdpn.io/1388885/uglify-es-self-3.3.9.js