-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Site: Update for ASF site guidelines (#9729)
Co-authored-by: Muna Bedan <[email protected]>
- Loading branch information
1 parent
45a086b
commit bcbcbb2
Showing
11 changed files
with
617 additions
and
101 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
/** | ||
* termynal.js | ||
* A lightweight, modern and extensible animated terminal window, using | ||
* async/await. | ||
* | ||
* @author Ines Montani <[email protected]> | ||
* @version 0.0.1 | ||
* @license MIT | ||
*/ | ||
|
||
'use strict'; | ||
|
||
/** Generate a terminal widget. */ | ||
class Termynal { | ||
/** | ||
* Construct the widget's settings. | ||
* @param {(string|Node)=} container - Query selector or container element. | ||
* @param {Object=} options - Custom settings. | ||
* @param {string} options.prefix - Prefix to use for data attributes. | ||
* @param {number} options.startDelay - Delay before animation, in ms. | ||
* @param {number} options.typeDelay - Delay between each typed character, in ms. | ||
* @param {number} options.lineDelay - Delay between each line, in ms. | ||
* @param {number} options.progressLength - Number of characters displayed as progress bar. | ||
* @param {string} options.progressChar – Character to use for progress bar, defaults to █. | ||
* @param {number} options.progressPercent - Max percent of progress. | ||
* @param {string} options.cursor – Character to use for cursor, defaults to ▋. | ||
* @param {Object[]} lineData - Dynamically loaded line data objects. | ||
* @param {boolean} options.noInit - Don't initialise the animation. | ||
*/ | ||
constructor(container = '#termynal', options = {}) { | ||
this.container = (typeof container === 'string') ? document.querySelector(container) : container; | ||
this.pfx = `data-${options.prefix || 'ty'}`; | ||
this.startDelay = options.startDelay | ||
|| parseFloat(this.container.getAttribute(`${this.pfx}-startDelay`)) || 600; | ||
this.typeDelay = options.typeDelay | ||
|| parseFloat(this.container.getAttribute(`${this.pfx}-typeDelay`)) || 90; | ||
this.lineDelay = options.lineDelay | ||
|| parseFloat(this.container.getAttribute(`${this.pfx}-lineDelay`)) || 1500; | ||
this.progressLength = options.progressLength | ||
|| parseFloat(this.container.getAttribute(`${this.pfx}-progressLength`)) || 40; | ||
this.progressChar = options.progressChar | ||
|| this.container.getAttribute(`${this.pfx}-progressChar`) || '█'; | ||
this.progressPercent = options.progressPercent | ||
|| parseFloat(this.container.getAttribute(`${this.pfx}-progressPercent`)) || 100; | ||
this.cursor = options.cursor | ||
|| this.container.getAttribute(`${this.pfx}-cursor`) || '▋'; | ||
this.lineData = this.lineDataToElements(options.lineData || []); | ||
if (!options.noInit) this.init() | ||
} | ||
|
||
/** | ||
* Initialise the widget, get lines, clear container and start animation. | ||
*/ | ||
init() { | ||
// Appends dynamically loaded lines to existing line elements. | ||
this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat(this.lineData); | ||
|
||
/** | ||
* Calculates width and height of Termynal container. | ||
* If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS. | ||
*/ | ||
const containerStyle = getComputedStyle(this.container); | ||
this.container.style.width = containerStyle.width !== '0px' ? | ||
containerStyle.width : undefined; | ||
this.container.style.minHeight = containerStyle.height !== '0px' ? | ||
containerStyle.height : undefined; | ||
|
||
this.container.setAttribute('data-termynal', ''); | ||
this.container.innerHTML = ''; | ||
this.start(); | ||
} | ||
|
||
/** | ||
* Start the animation and rener the lines depending on their data attributes. | ||
*/ | ||
async start() { | ||
await this._wait(this.startDelay); | ||
|
||
for (let line of this.lines) { | ||
const type = line.getAttribute(this.pfx); | ||
const delay = line.getAttribute(`${this.pfx}-delay`) || this.lineDelay; | ||
|
||
if (type == 'input') { | ||
line.setAttribute(`${this.pfx}-cursor`, this.cursor); | ||
await this.type(line); | ||
await this._wait(delay); | ||
} | ||
|
||
else if (type == 'progress') { | ||
await this.progress(line); | ||
await this._wait(delay); | ||
} | ||
|
||
else { | ||
this.container.appendChild(line); | ||
await this._wait(delay); | ||
} | ||
|
||
line.removeAttribute(`${this.pfx}-cursor`); | ||
} | ||
} | ||
|
||
/** | ||
* Animate a typed line. | ||
* @param {Node} line - The line element to render. | ||
*/ | ||
async type(line) { | ||
const chars = [...line.textContent]; | ||
const delay = line.getAttribute(`${this.pfx}-typeDelay`) || this.typeDelay; | ||
line.textContent = ''; | ||
this.container.appendChild(line); | ||
|
||
for (let char of chars) { | ||
await this._wait(delay); | ||
line.textContent += char; | ||
} | ||
} | ||
|
||
/** | ||
* Animate a progress bar. | ||
* @param {Node} line - The line element to render. | ||
*/ | ||
async progress(line) { | ||
const progressLength = line.getAttribute(`${this.pfx}-progressLength`) | ||
|| this.progressLength; | ||
const progressChar = line.getAttribute(`${this.pfx}-progressChar`) | ||
|| this.progressChar; | ||
const chars = progressChar.repeat(progressLength); | ||
const progressPercent = line.getAttribute(`${this.pfx}-progressPercent`) | ||
|| this.progressPercent; | ||
line.textContent = ''; | ||
this.container.appendChild(line); | ||
|
||
for (let i = 1; i < chars.length + 1; i++) { | ||
await this._wait(this.typeDelay); | ||
const percent = Math.round(i / chars.length * 100); | ||
line.textContent = `${chars.slice(0, i)} ${percent}%`; | ||
if (percent>progressPercent) { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Helper function for animation delays, called with `await`. | ||
* @param {number} time - Timeout, in ms. | ||
*/ | ||
_wait(time) { | ||
return new Promise(resolve => setTimeout(resolve, time)); | ||
} | ||
|
||
/** | ||
* Converts line data objects into line elements. | ||
* | ||
* @param {Object[]} lineData - Dynamically loaded lines. | ||
* @param {Object} line - Line data object. | ||
* @returns {Element[]} - Array of line elements. | ||
*/ | ||
lineDataToElements(lineData) { | ||
return lineData.map(line => { | ||
let div = document.createElement('div'); | ||
div.innerHTML = `<span ${this._attributes(line)}>${line.value || ''}</span>`; | ||
|
||
return div.firstElementChild; | ||
}); | ||
} | ||
|
||
/** | ||
* Helper function for generating attributes string. | ||
* | ||
* @param {Object} line - Line data object. | ||
* @returns {string} - String of attributes. | ||
*/ | ||
_attributes(line) { | ||
let attrs = ''; | ||
for (let prop in line) { | ||
attrs += this.pfx; | ||
|
||
if (prop === 'type') { | ||
attrs += `="${line[prop]}" ` | ||
} else if (prop !== 'value') { | ||
attrs += `-${prop}="${line[prop]}" ` | ||
} | ||
} | ||
|
||
return attrs; | ||
} | ||
} | ||
|
||
/** | ||
* HTML API: If current script has container(s) specified, initialise Termynal. | ||
*/ | ||
if (document.currentScript.hasAttribute('data-termynal-container')) { | ||
const containers = document.currentScript.getAttribute('data-termynal-container'); | ||
containers.split('|') | ||
.forEach(container => new Termynal(container)) | ||
} |
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 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
@font-face { | ||
font-family: 'Nunito Sans'; | ||
font-style: italic; | ||
font-weight: 300; | ||
font-stretch: normal; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/nunitosans/v15/pe1kMImSLYBIv1o4X1M8cce4OdVisMz5nZRqy6cmmmU3t2FQWEAEOvV9wNvrwlNstMKW3Y6K5WMwXeVy3GboJ0kTHmrR92UnK_c.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Nunito Sans'; | ||
font-style: italic; | ||
font-weight: 400; | ||
font-stretch: normal; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/nunitosans/v15/pe1kMImSLYBIv1o4X1M8cce4OdVisMz5nZRqy6cmmmU3t2FQWEAEOvV9wNvrwlNstMKW3Y6K5WMwXeVy3GboJ0kTHmqP92UnK_c.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Nunito Sans'; | ||
font-style: italic; | ||
font-weight: 700; | ||
font-stretch: normal; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/nunitosans/v15/pe1kMImSLYBIv1o4X1M8cce4OdVisMz5nZRqy6cmmmU3t2FQWEAEOvV9wNvrwlNstMKW3Y6K5WMwXeVy3GboJ0kTHmpo8GUnK_c.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Nunito Sans'; | ||
font-style: normal; | ||
font-weight: 300; | ||
font-stretch: normal; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/nunitosans/v15/pe1mMImSLYBIv1o4X1M8ce2xCx3yop4tQpF_MeTm0lfGWVpNn64CL7U8upHZIbMV51Q42ptCp5F5bxqqtQ1yiU4GiClXs1Ug.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Nunito Sans'; | ||
font-style: normal; | ||
font-weight: 400; | ||
font-stretch: normal; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/nunitosans/v15/pe1mMImSLYBIv1o4X1M8ce2xCx3yop4tQpF_MeTm0lfGWVpNn64CL7U8upHZIbMV51Q42ptCp5F5bxqqtQ1yiU4G1ilXs1Ug.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Nunito Sans'; | ||
font-style: normal; | ||
font-weight: 700; | ||
font-stretch: normal; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/nunitosans/v15/pe1mMImSLYBIv1o4X1M8ce2xCx3yop4tQpF_MeTm0lfGWVpNn64CL7U8upHZIbMV51Q42ptCp5F5bxqqtQ1yiU4GMS5Xs1Ug.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Roboto Mono'; | ||
font-style: italic; | ||
font-weight: 400; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/robotomono/v23/L0xoDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnANW6Cpw.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Roboto Mono'; | ||
font-style: italic; | ||
font-weight: 700; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/robotomono/v23/L0xoDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrmAB9W6Cpw.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Roboto Mono'; | ||
font-style: normal; | ||
font-weight: 400; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/robotomono/v23/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_ROW9.ttf) format('truetype'); | ||
} | ||
@font-face { | ||
font-family: 'Roboto Mono'; | ||
font-style: normal; | ||
font-weight: 700; | ||
font-display: fallback; | ||
src: url(https://fonts.gstatic.com/s/robotomono/v23/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_Of2_ROW9.ttf) format('truetype'); | ||
} |
Oops, something went wrong.