Skip to content

Instantly share code, notes, and snippets.

View Munawwar's full-sized avatar
🍪
Cookies

Munawwar Munawwar

🍪
Cookies
View GitHub Profile
@Munawwar
Munawwar / intercept.js
Last active April 9, 2024 21:32
Utility to intercept / stub methods of an object for unit test purpose
/*
* This function was created with a realization that once you override a method for mocking
* and run a test, you can't undo the override, because shared code (test runner without
* test isolation) will hold on to closures to the overridden function.
*
* So a solution it to intercept once before all tests, mock for a test and "undoMock()" at
* end of a test will cause the intercept to "proxy" future calls to the original method.
*/
const mocked = new Set();
@Munawwar
Munawwar / TypeClipboard.md
Created September 23, 2023 10:12 — forked from ethack/TypeClipboard.md
Scripts that simulate typing the clipboard contents. Useful when pasting is not allowed.

It "types" the contents of the clipboard.

Why can't you just paste the contents you ask? Sometimes pasting just doesn't work.

  • One example is in system password fields on OSX.
  • Sometimes you're working in a VM and the clipboard isn't shared.
  • Other times you're working via Remote Desktop and again, the clipboard doesn't work in password boxes such as the system login prompts.
  • Connected via RDP and clipboard sharing is disabled and so is mounting of local drives. If the system doesn't have internet access there's no easy way to get things like payloads or Powershell scripts onto it... until now.

Windows

The Windows version is written in AutoHotKey and easily compiles to an executable. It's a single line script that maps Ctrl-Shift-V to type the clipboard.

@Munawwar
Munawwar / README.md
Last active July 11, 2023 08:23
Reduce DOM creation for repeated updates to same child nodes

Problem: Say you have a function that takes a parent node and HTML string, which then renders the HTML as child nodes. On the next render, how would you know how much of the previous HTML was in the new HTML without having to parse the new HTML / create DOM nodes?

Another way to define the problem: I do a DOM diff for rendering HTML into a node. Think of it as a more efficient innerHTML update. However I am normally forced to parse the full HTML before even doing the diff. Even if html.startsWith() 90% of the previous HTML used. DOM creation is slower than string comparisons if and when possible.

E.g. Say the first HTML rendered was <b>1</b> and 2nd HTML rendered is <b>1</b><b>2</b>. Clearly <b>1</b> is already in the DOM and dont need an update. It is a substring of the previous HTML. Ideally we don't even need to create the DOM for diffing purpose.

Potential solution:

@Munawwar
Munawwar / parse-html-sax.js
Last active June 6, 2023 10:24
Tiny HTML5 SAX Parser for browser
/*
* The smallest html sax parser - 0.5kb gzipped
*
* Usage: Find the comments/jsdoc of export below.
*/
// Regular Expressions for parsing tags and attributes
let startTagRegex = /(?:<([a-zA-Z][^\s\/>]*)(?:\s+[^\s\/>"'=]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*\s*(\/?)\s*>)|(?:<\/\s*([a-zA-Z][^\s\/>]*)>)|(?:<!--(.+?)-->)|(?:<!\[CDATA\[([^>]+)\]\]>)/ig,
// Void Tags - HTML 5
voidTags = new Set('area,base,br,col,embed,hr,img,input,keygen,link,meta,param,source,track,wbr'.split(',')),
@Munawwar
Munawwar / generate-image.js
Created April 24, 2023 20:24
JSX to PNG via Satori and resvg-js
const htm = require('htm');
const { default: satori } = require('satori');
const { Resvg } = require('@resvg/resvg-js')
const { promises } = require('node:fs');
const { join } = require('node:path')
const html = htm.bind(function jsxToObject(type, props, ...children) {
return {
type,
props: {
@Munawwar
Munawwar / httpPing.js
Created April 7, 2023 17:58
Measure Time to first byte
// time to first byte
const https = require('https');
const http = require('http');
/**
* @param {Object} arg
* @param {String} arg.host
* @param {String} arg.path
* @param {{ [k: string]: string }} arg.headers
*/
@Munawwar
Munawwar / useObjectState.jsx
Last active September 26, 2021 11:02
Object state hook
import { useState } from 'react';
import { merge } from 'lodash';
function useObjectState(defaultVal = {}) {
const [state, setState] = useState(defaultVal);
const updateState = (newState) => {
setState((previousState) => ({ ...previousState, ...newState }));
};
const deepMergeState = (newState) => {
setState((previousState) => merge({}, previousState, newState));
@Munawwar
Munawwar / useAsyncState.js
Last active July 22, 2021 15:23
Async state fetching hook (for react)
import { useEffect, useState } from 'react';
/**
* @template T
* @param {(previousState: T) => Promise<T>} getAsyncState async function to fetch state
* @param {T} initialState
* @param {any[]} [dependencies=[]] similar to useEffect dependencies. change in dependencies will
* automatically call getAsyncState again
* @returns {[T, (newState: T) => void, () => Promise<void>]} [state, setState, refetch]
*/
@Munawwar
Munawwar / Dockerfile
Created June 22, 2021 15:31
node.js + puppeteer minimal docker file
# A minimal Docker file for node.js and Puppeteer
# debian 10 (buster slim) amd64 + node v14
# https://hub.docker.com/layers/node/library/node/14.17.1-buster-slim/images/sha256-10c6bf7204614c18b0734a218f576082ea2d15e9af7b7817a07eddcd7d05a255?context=explore
FROM node:14.17.1-buster-slim@sha256:10c6bf7204614c18b0734a218f576082ea2d15e9af7b7817a07eddcd7d05a255
RUN apt-get update \
# Install dependencies of Chromium that Puppeteer installs
# Dependency list for puppeteer v10.0.0 taken from https://github.com/puppeteer/puppeteer/blob/v10.0.0/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix
# Puppeteer v10.0.0 installs Chromium 92.0.4512.0 / r884014
@Munawwar
Munawwar / regex-test.js
Last active April 13, 2021 06:25
Testing the speed of regex replace approach
const whitespace = '[\\x20\\t\\r\\n\\f]';
const unescapeRegExp = new RegExp('\\\\([\\da-f]{1,6}' + whitespace + '?|(' + whitespace + ')|.)', 'ig');
function unescOrig(str) {
return str.replace(unescapeRegExp, (_, escaped, escapedWhitespace) => {
const high = '0x' + escaped - 0x10000;
// NaN means non-codepoint
// Workaround erroneous numeric interpretation of +"0x"
// eslint-disable-next-line no-self-compare