Skip to content

Instantly share code, notes, and snippets.

@AzrizHaziq
Last active August 7, 2021 06:55
Show Gist options
  • Save AzrizHaziq/adcfdbf12c3b30b6523495e19f282b58 to your computer and use it in GitHub Desktop.
Save AzrizHaziq/adcfdbf12c3b30b6523495e19f282b58 to your computer and use it in GitHub Desktop.
This is for my blog post gist collection
// read here: https://dev.to/azrizhaziq/how-self-xss-work-in-bookmark-15ok
// code copied from https://developer.mozilla.org/en-US/docs/Web/API/notification
// and was changed into iife
(() => {
// Let's check if the browser supports notifications
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
}
// Let's check whether notification permissions have already been granted
else if (Notification.permission === "granted") {
// If it's okay let's create a notification
var notification = new Notification("Hi there!");
}
// Otherwise, we need to ask the user for permission
else if (Notification.permission !== "denied") {
Notification.requestPermission().then(function (permission) {
// If the user accepts, let's create a notification
if (permission === "granted") {
var notification = new Notification("Hi there!");
}
});
}
// At last, if the user has denied notifications, and you
// want to be respectful there is no need to bother them any more.
})()

https://dev.to/azrizhaziq/i-ve-been-using-vim-in-total-a-year-and-i-ll-stick-using-it-2e8k

1. Inside (ciw)

  • It's stand for change inside word.

  • You also can change w to any char like (,}.

  • Below are some other variation that you can use:

    • diw delete inside word
    • vi( visual inside bracket
    • yiw yank inside word
    • dis delete inside sentence.
    • dip delete inside paragraph.
    • ci3w change inside 3 words

    Example

    Below I have a word inside bracket, and I would like to change it to my name:

    # before
    Lorem ipsum dolor sit amet, (inven<cursor here>tore) adipisicing elit.
    
    # type: ciwazrizhaziq
    # after
    Lorem ipsum dolor sit amet, (azrizhaziq) adipisicing elit.

2. Around (caw)

  • It's stand for change around word.

  • Most of the points here is the same as point number 1.

  • For the variations of around, just change i to a:

    • daw delete around word
    • va( visual around bracket

    Examples

    1. Given below scenario you want to change around bracket to your name
    # before
    Lorem ipsum dolor sit amet, (inven<cursor here>tore) adipisicing elit.
    
    # type: ca(azrizhaziq<esc>
    # after
    Lorem ipsum dolor sit amet, azrizhaziq adipisicing elit.
    1. Change this to implicit arrow function (remove return keyword and braces)
    // before
    const average = (...numbers: number[]): number => {
      return /* <cursor here> */ numbers.reduce((acc, n) => acc + n, 0) / numbers.length
    }
    
    // type: Dva{p
    // Delete all right chars until the end, visual around {, and then paste
    // after
    const average = (...numbers: number[]): number => numbers.reduce((acc, n) => acc + n, 0) / numbers.length  

3. t, f and then followed by any char that you want to search

  • t I'm not sure what it's stand for, f is find. Both used to find a char after cursor in current line.

  • The different is t will put cursor before the search char, while f will put at the char.

  • Now that you know small case t & f does, T and K does the opposite. Both will search before cursor in current line.

    Examples

    1. below example is not properly assign to string[]
    // typescript
        // before
    /* <cursor here> */ const names: string[] = ['azriz', 'haziq', 1985, 02, 30, true]
    
    // type f1dt]X
    // find 1, and put the cursor at it, find ] but put cursor before it, and delete a left char
    // after
    const names: string[] = ['azriz', 'haziq',]
    • If you want to find the next occurrence of searched char in a line use ;
    // below you want to change GBP $ to GBP £
    // before
    /* <cursor here> */ const currencies: string[] = ['MYR RM', 'AUD $', 'CNY ¥', 'SGD $', 'GBP $', 'JPY ¥']
    
    // type: f$;;r€
    // find $, find next, find next, replace €
    // after
    const currencies: string[] = ['MYR RM', 'AUD $', 'CNY ¥', 'SGD $', 'GBP $', 'JPY ¥'] 

4. :wq to save and quit

  • Instead of hit 5 keystrokes with below command its only 3 keystroke
    • ZZ save and quit
    • ZQ discard changes and quit

5. zc close folds, zo open folds

  • Used to fold codes. If you have 1k LOC(line of code), this will be handy.
  • You can focus on which chunk of code to focus.
  • This command it's not in both video as I remember.

6. J (not in the video)

  • It join the whole line below current cursor and append to current cursor.

  • Kinda hard to put in words, let's see in action

    Example

    // before
    /* <cursor here> */ var json = {
      name: 'azriz haziq', // see this line
      dob: '30 02 1985',
      hobbies: ['smash keyboard', 'press esc key']
    }
    
    // type: J
    // after
    var json = {
      name: 'azriz haziq',
      dob: '30 02 1985',
      hobbies: ['smash keyboard', 'press esc key']
    }
    
    // type: JJJ or 3J
    // after
    var json = { name: 'azriz haziq', dob: '30 02 1985', hobbies: ['smash keyboard', 'press esc key'] }

7. Mostly if you use with SHIFTchar, it will perform an action to before

  • I had a hard time at first how to differentiate certain key action. Some perform at before and sometime at after.
  • So how I remember it usually, capital char will perform action before current cursor/char/line.
  • O will add a new line before current line, while o will add new line after current line.
  • I will move the cursor at beginning of current line, while i will change to insert mode and put the cursor before char.
  • Same goes to P paste before a char, p paste after char.
  • After you search a term, and then you can hit N to find previous, n and find after.
  • But not all the case is like this, G, A, C, D perform differently.

8. Macros

  • Killer feature in vim.

  • Records all your keystrokes, and then you can replay the keystroke later.

  • AFAIK(as far as I know), you can't do this in any normal GUI editor like VS Code, Webstorm, notepad++, etc.

  • Macros only uses 2 keys which is q, and @.

  • The sequence to start macro is like this: qd...q.

    • first q is to start recording, while the last q is stop recording.
    • d save macro into 'd'. You can save this to any char.
    • ... stand for any command you want to record.
    • To run the macro that you just save in d, press it with @d.

    Examples

    1. Let's start with first example:

      • Below is CSP response header from twitter.com

      • It's quite hard to read since it is a one line of string

      • So let chunk it up with macro.

        # before
        <cursor here> connect-src 'self' blob: https://*.giphy.com https://*.pscp.tv https://*.video.pscp.tv https://*.twimg.com https://api.twitter.com https://api-stream.twitter.com https://ads-api.twitter.com https://aa.twitter.com https://caps.twitter.com https://media.riffsy.com https://pay.twitter.com https://sentry.io https://ton.twitter.com https://twitter.com https://upload.twitter.com https://www.google-analytics.com https://app.link https://api2.branch.io https://bnc.lt wss://*.pscp.tv https://vmap.snappytv.com https://vmapstage.snappytv.com https://vmaprel.snappytv.com https://vmap.grabyo.com https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net ; default-src 'self'; form-action 'self' https://twitter.com https://*.twitter.com; font-src 'self' https://*.twimg.com; frame-src 'self' https://twitter.com https://mobile.twitter.com https://pay.twitter.com https://cards-frame.twitter.com  https://accounts.google.com/; img-src 'self' blob: data: https://*.cdn.twitter.com https://ton.twitter.com https://*.twimg.com https://analytics.twitter.com https://cm.g.doubleclick.net https://www.google-analytics.com https://www.periscope.tv https://www.pscp.tv https://media.riffsy.com https://*.giphy.com https://*.pscp.tv https://*.periscope.tv https://prod-periscope-profile.s3-us-west-2.amazonaws.com https://platform-lookaside.fbsbx.com https://scontent.xx.fbcdn.net https://scontent-sea1-1.xx.fbcdn.net https://*.googleusercontent.com; manifest-src 'self'; media-src 'self' blob: https://twitter.com https://*.twimg.com https://*.vine.co https://*.pscp.tv https://*.video.pscp.tv https://*.giphy.com https://media.riffsy.com https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net; object-src 'none'; script-src 'self' 'unsafe-inline' https://*.twimg.com   https://www.google-analytics.com https://twitter.com https://app.link https://apis.google.com/js/platform.js https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js  'nonce-YmY0NTUzYjUtODYyYy00OGI0LTliZjctOTU4MDYxY2JkMjA2'; style-src 'self' 'unsafe-inline' https://*.twimg.com; worker-src 'self' blob:; report-uri https://twitter.com/i/csp_report?a=O5RXE===&ro=false
        
        # type below
        # qd                # start record and save to d
        # f;a<enter><esc>   # find ;, enter insert mode, enter and escape
        # q                 # stop recording
        # @d                # run once the record command
        # @@                # run previous macros command
        # 5@d               # run command 5 time
        connect-src 'self' blob: https://*.giphy.com https://*.pscp.tv https://*.video.pscp.tv https://*.twimg.com https://api.twitter.com https://api-stream.twitter.com https://ads-api.twitter.com https://aa.twitter.com https://caps.twitter.com https://media.riffsy.com https://pay.twitter.com https://sentry.io https://ton.twitter.com https://twitter.com https://upload.twitter.com https://www.google-analytics.com https://app.link https://api2.branch.io https://bnc.lt wss://*.pscp.tv https://vmap.snappytv.com https://vmapstage.snappytv.com https://vmaprel.snappytv.com https://vmap.grabyo.com https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net ;
        default-src 'self';
        form-action 'self' https://twitter.com https://*.twitter.com;
        font-src 'self' https://*.twimg.com;
        frame-src 'self' https://twitter.com https://mobile.twitter.com https://pay.twitter.com https://cards-frame.twitter.com  https://accounts.google.com/;
        img-src 'self' blob: data: https://*.cdn.twitter.com https://ton.twitter.com https://*.twimg.com https://analytics.twitter.com https://cm.g.doubleclick.net https://www.google-analytics.com https://www.periscope.tv https://www.pscp.tv https://media.riffsy.com https://*.giphy.com https://*.pscp.tv https://*.periscope.tv https://prod-periscope-profile.s3-us-west-2.amazonaws.com https://platform-lookaside.fbsbx.com https://scontent.xx.fbcdn.net https://scontent-sea1-1.xx.fbcdn.net https://*.googleusercontent.com;
        manifest-src 'self';
        media-src 'self' blob: https://twitter.com https://*.twimg.com https://*.vine.co https://*.pscp.tv https://*.video.pscp.tv https://*.giphy.com https://media.riffsy.com https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net;
        object-src 'none';
        script-src 'self' 'unsafe-inline' https://*.twimg.com   https://www.google-analytics.com https://twitter.com https://app.link https://apis.google.com/js/platform.js https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js  'nonce-YmY0NTUzYjUtODYyYy00OGI0LTliZjctOTU4MDYxY2JkMjA2';
        style-src 'self' 'unsafe-inline' https://*.twimg.com;
        worker-src 'self' blob:;
        report-uri https://twitter.com/i/csp_report?a=O5RXE===&ro=false
      • This example its pretty easy and can be done with normal IDE, just search everything ;, move 1 right and then hit enter, it will have the same result as above.

    2. Next, an example that is hard to achieve with normal editor.

      • So I have a pretty html here, and I want to change this to correct <table> markup.

      • Based on the snippet below, you can see children of <li> does not have proper structure. Sometime, the children is in same lime with <li>, and its also have multiline nested children.

        <!-- before -->
        <!-- <cursor-here> -->
        <ul>
          <li data-testId="1" class="abc"><span><svg /></span></li>
          <li data-testId="2" class="def">
            <p><small>1 + 2 = 3</small><b>3</b></p>
          </li>
          <li data-testId="3" class="qwe">
            <div>
              <button type="submit">
                <span>Click me</span>
              </button>
            </div>
          </li>
          <li data-testId="4" class="zxc"><!-- this is empty --></li>
          <li data-testId="5" class="asd">🧑‍💻❤️🐈</li>
        </ul>
      • So what we are going to do is, change <li> to <tr>, and <tr> children will have ${class}-${testId}

        <!-- before -->
        <li data-testId="1" class="abc"><span><svg /></span></li>
        
        <!-- after -->
        <tr data-testId="1" class="abc">abc-1</tr>
      • I believe if we are going to do with normal editor it will take a lot of time. You will be spending hitting CTRL /CMD/SHIFT/Arrow-right/Arrow-left a lot.

      • Bear with me as this is going to be very long steps.

        <!-- type: <esc> is escape key, <enter> is enter key
        qq                     # start recording
        /data<enter>           # search data
        dit                    # delete inside tag, I just knew this!!
        0w                     # put cursor at starting line
        fd                     # find d
        dt>                    # delete up until before >, d also save into clipboard     
        O                      # create new line above       
        <tr <esc>pa></tr><esc> # please make after you type this line the result will be <tr data-testId="1" class="abc"></td>
        0w                     # put cursor at starting line              
        fcf"lywf>p             # find c, find ", move 1 right, yank a word, find >, and paste
        0w                     # put cursor at starting line             
        f"lywt<a-<esc>p        # find ", move 1 right, yank a word, find a put cursor before <, paste
        jdd                    # go down, delete whole line
        q                      # stop recording
        -->
        <!-- after running above commands -->
        <ul>
          <tr data-testId="1" class="abc">abc-1</tr>   <!-- notice this line changed -->
          <li data-testId="2" class="def">
            <p><small>1 + 2 = 3</small><b>3</b></p>
          </li>
          <li data-testId="3" class="qwe">
            <div>
              <button type="submit">
                <span>Click me</span>
              </button>
            </div>
          </li>
          <li data-testId="4" class="zxc"><!-- this is empty --></li>
          <li data-testId="5" class="asd">🧑‍💻❤️🐈</li>
        </ul>
         <!-- since we save the macro to q, then we can type below -->
        <!-- type: @q -->
        <ul>
          <tr data-testId="1" class="abc">abc-1</tr>  <!-- notice this line changed -->
          <tr data-testId="2" class="def">def-2</tr>  <!-- notice this line changed -->
          <li data-testId="3" class="qwe">
            <div>
              <button type="submit">
                <span>Click me</span>
              </button>
            </div>
          </li>
          <li data-testId="4" class="zxc"><!-- this is empty --></li>
          <li data-testId="5" class="asd">🧑‍💻❤️🐈</li>
        </ul>
      • If you manage to reach here, Congratulation 🎉🎉.

      • Actually, we can shortcut few steps above with substitution :%s/tr/li/g<enter>, but I'll leave this for you to discover yourself.

9. Rerun previous command with .

  • This is a continuation from point 8.

  • please make sure your last command is @q

  • please note that this is no limited to macros only, you can literally use this . with any kind of command.

    <!-- type: .... -->
    <ul>
      <tr data-testId="1" class="abc">abc-1</tr>
      <tr data-testId="2" class="def">def-2</tr>
      <tr data-testId="3" class="qwe">qwe-3</tr>
      <tr data-testId="4" class="zxc">zxc-4</tr>
      <tr data-testId="5" class="asd">asd-5</tr>
    </ul>
  • Lastly, as you can see it's not a correct html <table> markup. Hence, please feel free to change it by putting children of <tr> to have <td>, and change <ul> to <table>.

10. :help <char/word>

  • last but not least, vim have its own massive docs. Just try to find any keyword that you want to know more.
    • :help del
    • :help v_it search visual inside tag:
  1. Bonus tips
  • In 1st and 2nd point, we learned inside and around.
  • There is another vim plugin which is to handle surround.
  • They have comprehensive examples on their readme, do check it out https://github.com/tpope/vim-surround.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment