Last active
February 8, 2025 14:08
-
-
Save Rinidh/60ea73d4285acf1364d1bb96b2bea6ef to your computer and use it in GitHub Desktop.
js-code #code-only
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
This file accesses all HTMLCanvasElement instances on the page/DOM, and applies a 50-unit grid, easily visible dark and light modes | |
Prefer to call this script at the end of all canvas renderings or after all other scripts to prevent hiding of grids behind drawings | |
*/ | |
const canvases = document.querySelectorAll('canvas'); | |
function drawGrids() { | |
//log cleaner, concise console error about no canvases detected | |
try { | |
canvases[0].getContext | |
} catch (err) { | |
if (err.message.includes("Cannot read properties of undefined (reading 'getContext')")) | |
return console.warn("canvasGrid: No canvases seen on the page!") | |
} | |
if (canvases[0].getContext) { //if canvas has a meth to get 2D context ie if the browser supports canvas API | |
canvases.forEach((canvas) => { | |
const ctx = canvas.getContext("2d") | |
const theme = getTheme() | |
//defaults & adjustments | |
canvas.style.backgroundColor = theme === "dark" ? "rgb(55, 55, 55)" : "rgb(248, 248, 248)" | |
ctx.fillStyle = theme === "dark" ? 'white' : 'black' | |
ctx.font = "0.7rem calibri" | |
ctx.textAlign = 'center' | |
ctx.strokeStyle = theme === "dark" ? '#f5f5f5' : '#5c5c5c' | |
ctx.lineWidth = 0.5; | |
ctx.setLineDash([3, 5]) | |
const canvasWidth = canvas.clientWidth | |
const canvasHeight = canvas.clientHeight | |
const startPoint = 0 | |
//clear canvas | |
ctx.clearRect(0, 0, canvasWidth, canvasHeight) | |
//horizontal lines (varyingCoordinate is y) | |
let endPoint = canvasWidth | |
for (let varyingCoordinate = 50.5; varyingCoordinate < canvasHeight; varyingCoordinate += 50) { //varyingCoordinate is xxx.5 for crisp lines | |
ctx.beginPath() | |
ctx.moveTo(startPoint, varyingCoordinate) | |
ctx.lineTo(endPoint, varyingCoordinate) | |
ctx.stroke() | |
//coordinate label | |
ctx.fillText(`${varyingCoordinate - 0.5}`, 10, varyingCoordinate + 10) | |
ctx.fillText(`${varyingCoordinate - 0.5}`, canvasWidth - 15, varyingCoordinate + 10) | |
} | |
//vertical lines (varyingCoordinate is x) | |
endPoint = canvasHeight | |
for (let varyingCoordinate = 50.5; varyingCoordinate < canvasWidth; varyingCoordinate += 50) { | |
ctx.beginPath() | |
ctx.moveTo(varyingCoordinate, startPoint) | |
ctx.lineTo(varyingCoordinate, endPoint) | |
ctx.stroke() | |
//coordinate label | |
ctx.fillText(`${varyingCoordinate - 0.5}`, varyingCoordinate + 3, 10) | |
ctx.fillText(`${varyingCoordinate - 0.5}`, varyingCoordinate + 3, canvasHeight - 6) | |
} | |
}) | |
} | |
} | |
drawGrids() //initial call | |
function getTheme() { | |
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) { | |
console.log('dark') | |
return "dark" | |
} else { | |
console.log('light') | |
return "light" | |
} | |
} | |
// observe & adapt to theme changes | |
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", drawGrids) //redraw the grids (whoch internally again fetch the new theme and apply colors) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NORMAL fetch() DEMO: | |
// fetch("https://jsonplaceholder.typicode.com/posts?_limit=3") | |
// .then(res => | |
// res.json() | |
// ) | |
// .then(data => | |
// console.log(data) | |
// ) | |
// .catch(err => | |
// console.error(err) | |
// ) | |
//no need for 'for await...of' if iterable is normal array instead of async *func (generators) or Promise | |
async function getResults(...resultsIds) { | |
for (let id of resultsIds) { | |
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`) | |
const data = await res.json() | |
console.log(data) | |
} | |
} | |
getResults(1, 3, 10) | |
//use 'for await...of' if async iterable or async *func (gen func): | |
const LIMIT = 3 | |
const asyncIterable = { | |
[Symbol.asyncIterator]() { | |
let i = 0 | |
return { | |
next() { | |
const value = i | |
const done = i === LIMIT | |
i++; | |
return Promise.resolve({ value, done }) //each next() call returns an async value that's awaited for before being assigned to block scoped variable 'val' in the loop | |
}, | |
return() { //if 'break' in btn | |
return { done: true } | |
} | |
} | |
} | |
} | |
async function run() { | |
for await (const val of asyncIterable) { | |
console.log(val) | |
} | |
} | |
run() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//A CUSTOM ITERATOR | |
function funcThatReturnsIteratorObj(start, finish) { | |
let index = start; | |
let count = 0; | |
return { | |
next() { | |
let result; | |
if (index < finish) { | |
result = { value: index, done: false } | |
index += 1; | |
count++; | |
return result; | |
} | |
return { | |
value: count, | |
done: true | |
} | |
} | |
} | |
} | |
const it = funcThatReturnsIteratorObj(0, 10); | |
let res = it.next(); | |
while (!res.done) { | |
console.log(res.value); | |
res = it.next(); | |
} | |
//A CUSTOM ITERABLE | |
let idx = 0; | |
const myIterable = { | |
[Symbol.iterator]() { | |
return { | |
[Symbol.iterator]() { return this; },//to make the obj an "iterable". May or may not be put | |
next() { | |
const current = idx; | |
idx++; | |
if (current <= 3) { | |
return { value: current, done: false }; | |
} else { | |
return { value: current, done: true }; | |
} | |
} | |
} | |
} | |
} | |
for (let val of myIterable) {//the for...of loop is designed defaultly to run the [Sym.itr]() method of the iterable(myIterable) and access the return obj (the iterator) with the next() method | |
//and call it again and again until done is true | |
//val here is set, by the for..of loop, to the value prop of the obj returned by next() method again and again until done is true | |
console.log(val); | |
} | |
//A GEN FUNC THAT RUNS FOREVER, RETURNING AN OBJ WITH THE VALUE PROP HOLDING A RANDOM NUM | |
function* randomNum() { | |
while (true) { | |
yield Math.floor(math.randomNum() * 100) | |
} | |
} | |
let it = randomNum() | |
console.log(it.next()) | |
console.log(it.next()) | |
/* | |
//FIND WHAT THIS DOES IN NODE | |
const CAF = require("caf") | |
const jsonServer = require("json-server") | |
const server = jsonServer.create() | |
const router = jsonServer.router("src/db.json") | |
const middlewares = jsonServer.defaults() | |
server.use(middlewares) | |
server.use(router) | |
server.listen(3000, ()=>{ | |
console.log("json server is running!") | |
}) | |
*/ | |
//CAFs | |
const CAF = require("caf") | |
const token = new CAF.cancelToken() | |
//const token2 = new CAF.timeout(300, "This message will display after 300 millisecs of waiting by the timeout token") | |
//the above timeout token will cancel/abort the fetchCAF func and the CAF.delay setTimeOut() within after 3 secs | |
const fetchCAF = CAF(function* fetchData(signal) { | |
CAF.delay(signal, 400)//to simulate or act as a time consuming process of 4 secs | |
const promise = yield axios.get("http://localhost:3000/users") | |
return promise; | |
}) | |
fetchCAF(token.signal).then(res => { console.log(res.data) })//gives errors | |
//fetchCAF(token).then(res => {console.log(res.data)})//use token instead of token.signal to canel even the CAF.delay() inside |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file contains general js functions, classes etc for reference | |
//HELPER/UTILITY FUNCTIONS: | |
function reverseWords(sentence) { | |
//get array of indices of spaces | |
const indicesOfSpaces = Array.from(SENTENCE).map((character, index) => { | |
return character === " " ? index : null | |
}) | |
const indicesOfSpaces_AllTruthy = indicesOfSpaces.filter(Boolean) | |
//get array of sentence's words only | |
let wordsArray = []; | |
let startIndex = 0; | |
indicesOfSpaces_AllTruthy.forEach((endIndex) => { | |
const word = SENTENCE.substring(startIndex, endIndex) | |
wordsArray.push(word) | |
startIndex = endIndex + 1 | |
}) | |
const lastWord = SENTENCE.substring(startIndex) | |
wordsArray.push(lastWord) | |
//OR | |
const wordsArray2 = SENTENCE.split(" ") | |
wordsArray2 | |
//get array of words in reversed order | |
let wordsArrayReversed = [] | |
for (let index = wordsArray2.length - 1; index > -1; index--) { | |
wordsArrayReversed.push(wordsArray2[index]) | |
} | |
wordsArrayReversed | |
//join into string with spaces again | |
const reversedSentence = wordsArrayReversed.join(" ") | |
// return reversedSentence | |
// OR EASIER: | |
// return sentence.split(" ").reverse().join(" ") | |
} | |
function escapeHTML(strings, ...values) { | |
const replaceSpecialChars = (str) => { //helper func | |
return str.replace(/&/g, "&") | |
.replace(/</g, "<") | |
.replace(/>/g, ">") | |
.replace(/"/g, """) | |
.replace(/'/g, "'"); | |
} | |
const safeString = strings.reduce((accumulatedResultString, currentStringPart, i) => { //hacker's text comes in values array | |
return accumulatedResultString + | |
currentStringPart + | |
(values[i] ? replaceSpecialChars(String(values[i])) : "") | |
}, "") | |
return safeString | |
} | |
// const userInput = "<script>alert('hacker's message!') //or other malicious code</script>" //if browser parses this raw string, the js script may run | |
// const res = escapeHTML`Hacker input: ${userInput}` | |
function formatWithCommas(strings, ...values) { | |
function putCommas(value) { | |
if (typeof value === "number") return value.toLocaleString() | |
} | |
const formattedString = strings.reduce((accumulatedString, currentString, index) => { | |
return accumulatedString + currentString + (putCommas(values[index]) || "") | |
}, "") | |
return formattedString; | |
} | |
// console.log(formatWithCommas`your qty is ${1234} and bill $${23000} e`) | |
function canvasGrid(canvas) { //add more fucntionality like stroke width, gap, color, numbers etc | |
if (canvas.getContext) { | |
const ctx = canvas.getContext("2d") | |
//defaults | |
ctx.shadowOffsetX = 0 | |
ctx.shadowOffsety = 0 | |
ctx.shadowBlur = 0 | |
ctx.shadowColor = 'rgb(0 0 0 /0%)' | |
ctx.fillStyle = 'black' | |
ctx.strokeStyle = '#5c5c5c' | |
ctx.lineWidth = 0.5; | |
ctx.setLineDash([3, 5]) | |
const canvasWidth = canvas.clientWidth | |
const canvasHeight = canvas.clientHeight | |
const startPoint = 0 | |
//horizontal lines (varyingCoordinate is y) | |
let endPoint = canvasWidth | |
for (let varyingCoordinate = 50.5; varyingCoordinate < canvasHeight; varyingCoordinate += 50) { //varyingCoordinate is xxx.5 for crisp lines | |
ctx.beginPath() | |
ctx.moveTo(startPoint, varyingCoordinate) | |
ctx.lineTo(endPoint, varyingCoordinate) | |
ctx.stroke() | |
//coordinate label | |
ctx.font = "0.7rem calibri" | |
ctx.fillText(`${varyingCoordinate - 0.5}`, 3, varyingCoordinate + 10) | |
ctx.fillText(`${varyingCoordinate - 0.5}`, canvasWidth - 25, varyingCoordinate + 10) | |
} | |
//vertical lines (varyingCoordinate is x) | |
endPoint = canvasHeight | |
for (let varyingCoordinate = 50.5; varyingCoordinate < canvasWidth; varyingCoordinate += 50) { | |
ctx.beginPath() | |
ctx.moveTo(varyingCoordinate, startPoint) | |
ctx.lineTo(varyingCoordinate, endPoint) | |
ctx.stroke() | |
ctx.font = "0.7rem calibri" | |
ctx.fillText(`${varyingCoordinate - 0.5}`, varyingCoordinate + 3, 10) | |
ctx.fillText(`${varyingCoordinate - 0.5}`, varyingCoordinate + 3, canvasHeight - 6) | |
} | |
} | |
//SEE ADVANCED FORM of this in the GIST: js-code/canvasGrid.js | |
} | |
function roundedRect(ctx, x, y, width, height, radius) { // A utility function to draw a rectangle with rounded corners. | |
ctx.beginPath(); | |
ctx.moveTo(x, y + radius); | |
ctx.arcTo(x, y + height, x + radius, y + height, radius); | |
ctx.arcTo(x + width, y + height, x + width, y + height - radius, radius); | |
ctx.arcTo(x + width, y, x + width - radius, y, radius); | |
ctx.arcTo(x, y, x, y + radius, radius); | |
ctx.stroke(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const winston = require("winston"); | |
const logger = winston.createLogger({ | |
level: "verbose", //messages with level verbose or higher can be logged with this 'logger' instance. logger.verbose() won't work | |
format: winston.format.json(), //others: | |
defaultMeta: { service: "eg user-service" }, //appears in all logs as end-messages | |
transports: [ | |
new winston.transports.File({ | |
filename: "warnOrHigher.log", | |
level: "warn", // warn or higher level msgs | |
}), | |
new winston.transports.File({ filename: "combined.log" }), //all logs that are logged with this 'logger' ie all logs that are level verbose or higher | |
new winston.transports.Console({ | |
format: winston.format.simple(), | |
}), | |
], | |
}); | |
logger.error("error lvl"); //goes into both warnOrHigher.log and combined.log | |
logger.info("info lvl"); //goes into only combined.log | |
logger.silly("silly lvl"); //doesn't work | |
//NOTES | |
//LEVELS | |
// error: 0, | |
// warn: 1, | |
// info: 2, | |
// http: 3, | |
// verbose: 4, | |
// debug: 5, | |
// silly: 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment