1,315 Matching Annotations
  1. Jun 2023
    1. ```js self.addEventListener('fetch', event => { const { headers, url } = event.request; const isSSERequest = headers.get('Accept') === 'text/event-stream';

      // We process only SSE connections if (!isSSERequest) { return; }

      // Response Headers for SSE const sseHeaders = { 'content-type': 'text/event-stream', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', }; // Function formatting data for SSE const sseChunkData = (data, event, retry, id) => Object.entries({ event, id, data, retry }) .filter(([, value]) => ![undefined, null].includes(value)) .map(([key, value]) => ${key}: ${value}) .join('\n') + '\n\n'; // Table with server connections, where key is url, value is EventSource const serverConnections = {}; // For each url, we open only one connection to the server and use it for subsequent requests const getServerConnection = url => { if (!serverConnections[url]) serverConnections[url] = new EventSource(url);

      return serverConnections[url];
      

      }; // When we receive a message from the server, we forward it to the browser const onServerMessage = (controller, { data, type, retry, lastEventId }) => { const responseText = sseChunkData(data, type, retry, lastEventId); const responseData = Uint8Array.from(responseText, x => x.charCodeAt(0)); controller.enqueue(responseData); }; const stream = new ReadableStream({ start: controller => getServerConnection(url).onmessage = onServerMessage.bind(null, controller) }); const response = new Response(stream, { headers: sseHeaders });

      event.respondWith(response); }); ```

    1. Security considerations When inserting HTML into a page by using insertAdjacentHTML(), be careful not to use user input that hasn't been escaped.

      ```html <select id="position"> <br /> <option>beforebegin</option>

      <option>afterbegin</option> <option>beforeend</option> <option>afterend</option>

      </select>

      <button id="insert">Insert HTML</button> <button id="reset">Reset</button>

      Some text, with a code-formatted element inside it.

      ```

      ```js const insert = document.querySelector("#insert"); insert.addEventListener("click", () => { const subject = document.querySelector("#subject"); const positionSelect = document.querySelector("#position"); subject.insertAdjacentHTML( positionSelect.value, "inserted text" ); });

      const reset = document.querySelector("#reset"); reset.addEventListener("click", () => { document.location.reload(); });

      ```

    1. Use insertAdjacentHTML(). It works with all current browsers, even with IE11.

      js var mylist = document.getElementById('mylist'); mylist.insertAdjacentHTML('beforeend', '<li>third</li>');

      ```html

      • first
      • second

      ```

    2. HTML 5 introduced the <template> element which can be used for this purpose (as now described in the WhatWG spec and MDN docs). A <template> element is used to declare fragments of HTML that can be utilized in scripts. The element is represented in the DOM as a HTMLTemplateElement which has a .content property of DocumentFragment type, to provide access to the template's contents. This means that you can convert an HTML string to DOM elements by setting the innerHTML of a <template> element, then reaching into the template's .content property.

      ```js /* * @param {String} HTML representing a single element * @return {Element} / function htmlToElement(html) { var template = document.createElement('template'); html = html.trim(); // Never return a text node of whitespace as the result template.innerHTML = html; return template.content.firstChild; }

      var td = htmlToElement('<td>foo</td>'), div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');

      /* * @param {String} HTML representing any number of sibling elements * @return {NodeList} / function htmlToElements(html) { var template = document.createElement('template'); template.innerHTML = html; return template.content.childNodes; }

      var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>'); ```

  2. May 2023
    1. With TypeScript 3.7, TypeScript added support for generating .d.ts files from JavaScript using JSDoc syntax. This set up means you can own the editor experience of TypeScript-powered editors without porting your project to TypeScript, or having to maintain .d.ts files in your codebase.

      npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types

    1. js /** * This component is just a Box with border. * It serves as an example of how you can incorporate * components together. * * Component also has slots, methods and events. * * @component * @example <caption>Basic usage just with the default slot</caption> * <Box> * I am inside a slot * </Box> * * @example <caption>Using second component inside</caption> * <Box> * <ProgressBar :spent="spent" :remaining="50"></ProgressBar> * </Box> * * @example <caption>Example of passing an entire component in a preview</caption> * { * template: `<Box> * <ProgressBar :spent="spent" :remaining="50"></ProgressBar> * <ProgressBar :spent="50" :remaining="50" style="margin-top: 20px"></ProgressBar> * </Box>`, * data: function() { * return {spent: 223}; * } * } */ export default { name: "Box", props: { /** * This will be in the header */ title: { type: String, default: "My box" } }, methods: { /** * Also, you can describe methods for each component * the same as you would do this in regular @jsdoc * documented file * * @param {string} prop1 some example property * @param {string} prop2 other property */ exampleMethod(prop1, prop2) { // method body // The method could even throw an event /** * This event could be thrown by component in case * of some kind of unexpected behaviour. * * @category API * @event unexpectedEvent */ this.$emit('unexpecteEvent') } } }

    1. 🥳

      ```js import { connect } from 'cloudflare:sockets';

      export default { async fetch(req: Request) { const gopherAddr = "gopher.floodgap.com:70"; const url = new URL(req.url);

      try {
        const socket = connect(gopherAddr);
      
        const writer = socket.writable.getWriter()
        const encoder = new TextEncoder();
        const encoded = encoder.encode(url.pathname + "\r\n");
        await writer.write(encoded);
      
        return new Response(socket.readable, { headers: { "Content-Type": "text/plain" } });
      } catch (error) {
        return new Response("Socket connection failed: " + error, { status: 500 });
      }
      

      } }; ts connect(address: SocketAddress | string, options?: SocketOptions): Socket

      declare interface Socket { get readable(): ReadableStream; get writable(): WritableStream; get closed(): Promise<void>; close(): Promise<void>; startTls(): Socket; }

      declare interface SocketOptions { secureTransport?: string; allowHalfOpen: boolean; }

      declare interface SocketAddress { hostname: string; port: number; } ```

    1. ```ts

      /* * Initiates a connection to the selected port. / async function connectToServer(): Promise<void> { hostInput.disabled = true; portInput.disabled = true; connectButton.textContent = 'Connecting...'; connectButton.disabled = true;

      try { socket = new TCPSocket(hostInput.value, parseInt(portInput.value)); connection = await socket.opened; term.writeln('<CONNECTED>'); connectButton.textContent = 'Disconnect'; connectButton.disabled = false; } catch (e) { console.error(e); term.writeln(<ERROR: ${e.message}>); markDisconnected(); return; }

      try { reader = connection?.readable.getReader(); for (;;) { const {value, done} = await reader.read(); if (value) { await new Promise<void>((resolve) => { term.write(value, resolve); }); } if (done) { break; } } reader.releaseLock(); reader = undefined; } catch (e) { console.error(e); term.writeln(<ERROR: ${e.message}>); }

      markDisconnected(); }

      /* * Closes the currently active connection. / async function disconnectFromServer(): Promise<void> { // Canceling |reader| will close the connection and cause the read loop in // connectToServer() to exit when read() returns with done set to true. if (reader) { await reader.cancel(); } } ```

  3. Apr 2023
  4. Mar 2023
    1. ```js var name = 'Alfred'; var age = 47;

      function greet(){ console.log(arguments[0]); console.log(arguments[1]); console.log(arguments[2]); } greetI'm ${name}. I'm ${age} years old.; ```

    1. ```js

      window.onSpotifyIframeApiReady = (IFrameAPI) => { let element = document.getElementById('embed-iframe'); let options = { uri: 'spotify:episode:7makk4oTQel546B0PZlDM5' }; let callback = (EmbedController) => {}; IFrameAPI.createController(element, options, callback); }; ```

    1. ```js // Adds an entry to the event log on the page, optionally applying a specified // CSS class.

      let currentTransport, streamNumber, currentTransportDatagramWriter;

      // "Connect" button handler. async function connect() { const url = document.getElementById('url').value; try { var transport = new WebTransport(url); addToEventLog('Initiating connection...'); } catch (e) { addToEventLog('Failed to create connection object. ' + e, 'error'); return; }

      try { await transport.ready; addToEventLog('Connection ready.'); } catch (e) { addToEventLog('Connection failed. ' + e, 'error'); return; }

      transport.closed .then(() => { addToEventLog('Connection closed normally.'); }) .catch(() => { addToEventLog('Connection closed abruptly.', 'error'); });

      currentTransport = transport; streamNumber = 1; try { currentTransportDatagramWriter = transport.datagrams.writable.getWriter(); addToEventLog('Datagram writer ready.'); } catch (e) { addToEventLog('Sending datagrams not supported: ' + e, 'error'); return; } readDatagrams(transport); acceptUnidirectionalStreams(transport); document.forms.sending.elements.send.disabled = false; document.getElementById('connect').disabled = true; }

      // "Send data" button handler. async function sendData() { let form = document.forms.sending.elements; let encoder = new TextEncoder('utf-8'); let rawData = sending.data.value; let data = encoder.encode(rawData); let transport = currentTransport; try { switch (form.sendtype.value) { case 'datagram': await currentTransportDatagramWriter.write(data); addToEventLog('Sent datagram: ' + rawData); break; case 'unidi': { let stream = await transport.createUnidirectionalStream(); let writer = stream.getWriter(); await writer.write(data); await writer.close(); addToEventLog('Sent a unidirectional stream with data: ' + rawData); break; } case 'bidi': { let stream = await transport.createBidirectionalStream(); let number = streamNumber++; readFromIncomingStream(stream, number);

          let writer = stream.writable.getWriter();
          await writer.write(data);
          await writer.close();
          addToEventLog(
              'Opened bidirectional stream #' + number +
              ' with data: ' + rawData);
          break;
        }
      }
      

      } catch (e) { addToEventLog('Error while sending data: ' + e, 'error'); } }

      // Reads datagrams from |transport| into the event log until EOF is reached. async function readDatagrams(transport) { try { var reader = transport.datagrams.readable.getReader(); addToEventLog('Datagram reader ready.'); } catch (e) { addToEventLog('Receiving datagrams not supported: ' + e, 'error'); return; } let decoder = new TextDecoder('utf-8'); try { while (true) { const { value, done } = await reader.read(); if (done) { addToEventLog('Done reading datagrams!'); return; } let data = decoder.decode(value); addToEventLog('Datagram received: ' + data); } } catch (e) { addToEventLog('Error while reading datagrams: ' + e, 'error'); } }

      async function acceptUnidirectionalStreams(transport) { let reader = transport.incomingUnidirectionalStreams.getReader(); try { while (true) { const { value, done } = await reader.read(); if (done) { addToEventLog('Done accepting unidirectional streams!'); return; } let stream = value; let number = streamNumber++; addToEventLog('New incoming unidirectional stream #' + number); readFromIncomingStream(stream, number); } } catch (e) { addToEventLog('Error while accepting streams: ' + e, 'error'); } }

      async function readFromIncomingStream(stream, number) { let decoder = new TextDecoderStream('utf-8'); let reader = stream.pipeThrough(decoder).getReader(); try { while (true) { const { value, done } = await reader.read(); if (done) { addToEventLog('Stream #' + number + ' closed'); return; } let data = value; addToEventLog('Received data on stream #' + number + ': ' + data); } } catch (e) { addToEventLog( 'Error while reading from stream #' + number + ': ' + e, 'error'); addToEventLog(' ' + e.message); } }

      function addToEventLog(text, severity = 'info') { let log = document.getElementById('event-log'); let mostRecentEntry = log.lastElementChild; let entry = document.createElement('li'); entry.innerText = text; entry.className = 'log-' + severity; log.appendChild(entry);

      // If the most recent entry in the log was visible, scroll the log to the // newly added element. if (mostRecentEntry != null && mostRecentEntry.getBoundingClientRect().top < log.getBoundingClientRect().bottom) { entry.scrollIntoView(); } } ```

    1. ```js /! devtools-detect https://github.com/sindresorhus/devtools-detect By Sindre Sorhus MIT License / const devtools = { isOpen: false, orientation: undefined, };

      const threshold = 170;

      const emitEvent = (isOpen, orientation) => { globalThis.dispatchEvent(new globalThis.CustomEvent('devtoolschange', { detail: { isOpen, orientation, }, })); };

      const main = ({ emitEvents = true } = {}) => { const widthThreshold = globalThis.outerWidth - globalThis.innerWidth > threshold; const heightThreshold = globalThis.outerHeight - globalThis.innerHeight > threshold; const orientation = widthThreshold ? 'vertical' : 'horizontal';

      if ( !(heightThreshold && widthThreshold) && ((globalThis.Firebug && globalThis.Firebug.chrome && globalThis.Firebug.chrome.isInitialized) || widthThreshold || heightThreshold) ) { if ((!devtools.isOpen || devtools.orientation !== orientation) && emitEvents) { emitEvent(true, orientation); }

      devtools.isOpen = true;
      devtools.orientation = orientation;
      

      } else { if (devtools.isOpen && emitEvents) { emitEvent(false, undefined); }

      devtools.isOpen = false;
      devtools.orientation = undefined;
      

      } };

      main({ emitEvents: false }); setInterval(main, 500);

      export default devtools; ```

    1. Thanks to a collaboration with Bloomberg, Babel now supports transforming the "Records and Tuples" stage 2 proposal.The Babel plugin transforms records and tuples syntax using the global Record and Tuple functions:
      Records and Tuples support (#12145)
      <table><tbody style="width:100%;display:table;table-layout:fixed"><tr><th>Input</th><th>Output</th></tr><tr><td><div class="language-js codeBlockContainer_mQmQ theme-code-block" style="--prism-color: #4d4d4c; --prism-background-color: #fdfaeb;"><div class="codeBlockTitle_x_ju">JavaScript</div><div class="codeBlockContent_D5yF">
      <span class="token-line" style="color: rgb(77, 77, 76);"><span class="token keyword" style="color: rgb(137, 89, 168);">let</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> #</span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color: rgb(77, 77, 76);"><span class="token plain">  </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color: rgb(113, 140, 0);">"Babel"</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color: rgb(77, 77, 76);"><span class="token plain">  </span><span class="token literal-property property">ids</span><span class="token operator">:</span><span class="token plain"> #</span><span class="token punctuation">[</span><span class="token number" style="color: rgb(245, 135, 31);">1</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color: rgb(245, 135, 31);">2</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color: rgb(245, 135, 31);">3</span><span class="token punctuation">]</span><span class="token plain"></span><br></span><span class="token-line" style="color: rgb(77, 77, 76);"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span>
      <div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg class="copyButtonIcon_FoOz" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_L0B6" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></td><td><div class="language-js codeBlockContainer_mQmQ theme-code-block" style="--prism-color: #4d4d4c; --prism-background-color: #fdfaeb;"><div class="codeBlockTitle_x_ju">JavaScript</div><div class="codeBlockContent_D5yF">
      <span class="token-line" style="color: rgb(77, 77, 76);"><span class="token keyword" style="color: rgb(137, 89, 168);">let</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color: rgb(66, 113, 174);">Record</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color: rgb(77, 77, 76);"><span class="token plain">  </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color: rgb(113, 140, 0);">"Babel"</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color: rgb(77, 77, 76);"><span class="token plain">  </span><span class="token literal-property property">ids</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color: rgb(66, 113, 174);">Tuple</span><span class="token punctuation">(</span><span class="token number" style="color: rgb(245, 135, 31);">1</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color: rgb(245, 135, 31);">2</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color: rgb(245, 135, 31);">3</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color: rgb(77, 77, 76);"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br></span>
      <div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg class="copyButtonIcon_FoOz" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_L0B6" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></td></tr></tbody></table>
    1. Record

      ``js const proposal = #{ id: 1234, title: "Record & Tuple proposal", contents:...`, // tuples are primitive types so you can put them in records: keywords: #["ecma", "tc39", "proposal", "record", "tuple"], };

      // Accessing keys like you would with objects! console.log(proposal.title); // Record & Tuple proposal console.log(proposal.keywords[1]); // tc39

      // Spread like objects! const proposal2 = #{ ...proposal, title: "Stage 2: Record & Tuple", }; console.log(proposal2.title); // Stage 2: Record & Tuple console.log(proposal2.keywords[1]); // tc39

      // Object functions work on Records: console.log(Object.keys(proposal)); // ["contents", "id", "keywords", "title"] ```

      Tuple

      ```js const measures = #[42, 12, 67, "measure error: foo happened"];

      // Accessing indices like you would with arrays! console.log(measures[0]); // 42 console.log(measures[3]); // measure error: foo happened

      // Slice and spread like arrays! const correctedMeasures = #[ ...measures.slice(0, measures.length - 1), -1 ]; console.log(correctedMeasures[0]); // 42 console.log(correctedMeasures[3]); // -1

      // or use the .with() shorthand for the same result: const correctedMeasures2 = measures.with(3, -1); console.log(correctedMeasures2[0]); // 42 console.log(correctedMeasures2[3]); // -1

      // Tuples support methods similar to Arrays console.log(correctedMeasures2.map(x => x + 1)); // #[43, 13, 68, 0] ```

    1. The nullish coalescing operator can be seen as a special case of the logical OR (||) operator.
    1. js const arr = ["a", "b", "c", "d", "e"]; const arrIter = arr[Symbol.iterator](); console.log(arrIter.next().value); // a console.log(arrIter.next().value); // b console.log(arrIter.next().value); // c console.log(arrIter.next().value); // d console.log(arrIter.next().value); // e

    1. ```js function makeDocument() { let frame = document.getElementById("theFrame");

      let doc = document.implementation.createHTMLDocument("New Document"); let p = doc.createElement("p"); p.textContent = "This is a new paragraph.";

      try { doc.body.appendChild(p); } catch (e) { console.log(e); }

      // Copy the new HTML document into the frame

      let destDocument = frame.contentDocument; let srcNode = doc.documentElement; let newNode = destDocument.importNode(srcNode, true);

      destDocument.replaceChild(newNode, destDocument.documentElement); } ```

      • Matches by Object property ```js const { matches } = require('z')

      const person = { name: 'Maria' } matches(person)( (x = { name: 'John' }) => console.log('John you are not welcome!'), (x) => console.log(Hey ${x.name}, you are welcome!) ) - Matches by type or instancesjs const { matches } = require('z')

      const result = matches(1)( (x = 2) => 'number 2 is the best!!!', (x = Number) => number ${x} is not that good, (x = Date) => 'blaa.. dates are awful!' )

      console.log(result) // output: number 1 is not that good - Matches Array contentjs const { matches } = require('z')

      matches([1, 2, 3, 4, 5])( (a, b, c, tail) => 'a = 1, b = 2, c = 3, tail = [4, 5]'<br /> )

      matches([1, 2])( (a, tail) => 'a = 1, tail = [2]'<br /> )

      matches([1])( (a, b, tail) => 'Will not match here', (a = 2, tail = []) => 'Will not match here', (a = 1, tail) => 'Will match here, tail = []' ) ```

      • Powerful recursive code which will remove sequential repeated items from Array ```js const { matches } = require('z')

      const compress = (numbers) => { return matches(numbers)( (x, y, xs) => x === y ? compress([x].concat(xs)) : [x].concat(compress([y].concat(xs))), (x, xs) => x // stopping condition ) }

      compress([1, 1, 2, 3, 4, 4, 4]) //output: [1, 2, 3, 4] ```

    1. Microdata DOM API

      Warning: Microdata were implemented in some browsers for a long time. Nowadays, they have been abandoned and removed from all browsers and are therefore deprecated. You can't use them anymore and this document is kept as information only.

    1. The microdata becomes even more useful when scripts can use it to expose information to the user, for example offering it in a form that can be used by other applications.The document.getItems(typeNames) method provides access to the top-level microdata items. It returns a NodeList containing the items with the specified types, or all types if no argument is specified.Each item is represented in the DOM by the element on which the relevant itemscope attribute is found. These elements have their element.itemScope IDL attribute set to true.The type of items can be obtained using the element.itemType IDL attribute on the element with the itemscope attribute.

      ```js // This sample shows how the getItems() method can be used to obtain a list // of all the top-level microdata items of one type given in the document:

      var cats = document.getItems("http://example.com/feline"); ```

      ```js // This sample gets the first item of type "http://example.net/user" // and then pops up an alert using the "name" property from that item.

      var user = document.getItems('http://example.net/user')[0]; alert('Hello ' + user.properties['name'][0].content + '!'); ```

      ```js // The HTMLPropertiesCollection object, when indexed by name in this way, // actually returns a PropertyNodeList object with all the matching properties. // The PropertyNodeList object can be used to obtain all the values at once // using its values attribute, which returns an array of all the values.

      var cat = document.getItems('http://example.org/animals#cat')[0]; var colors = cat.properties['http://example.com/color'].values; var result; if (colors.length == 0) { result = 'Color unknown.'; } else if (colors.length == 1) { result = 'Color: ' + colors[0]; } else { result = 'Colors:'; for (var i = 0; i < colors.length; i += 1) result += ' ' + colors[i]; } ```