Skip to content

Commit

Permalink
Merge pull request #14 from Ovski4/typescript-build
Browse files Browse the repository at this point in the history
Typescript support
  • Loading branch information
Ovski4 authored Feb 6, 2024
2 parents c94b1d3 + 40034ed commit 3c734a7
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 33 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,31 @@ jekyllTabs.init({
```

Default styles for the toast message are present in the [css file](https://github.com/Ovski4/jekyll-tabs/blob/master/docs/tabs.css#L50-L70).

Development
-----------

### Building the script

Execute:

```bash
npm run build
```

The add the following content to the `tabs.js` file.

```js
window.addEventListener('load', function () {
jekyllTabs.init();
});
```

### Building and pushing the gem

Update the version number in `jekyll-tabs/version.rb`, then execute:

```bash
gem build jekyll-tabs.gemspec
gem push jekyll-tabs-{version_here}.gem
```
2 changes: 1 addition & 1 deletion docs/tabs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @type {import('jest').Config} */
const config = {
preset: 'ts-jest',
verbose: true,
testEnvironment: 'jsdom',
collectCoverage: true,
Expand Down
10 changes: 5 additions & 5 deletions js/domHelpers.js → js/domHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* Then getChildPosition(document.querySelector('.one')) would return 1.
*/
const getChildPosition = (element) => {
const getChildPosition = (element: HTMLElement) => {
const parent = element.parentNode;

for (let i = 0; i < parent.children.length; i++) {
Expand All @@ -24,7 +24,7 @@ const getChildPosition = (element) => {
/**
* Returns a list of elements that match the given selector and text content.
*/
const findElementsWithTextContent = (selector, text) => {
const findElementsWithTextContent = (selector: string, text: string) => {
const elementsMatchingSelector = document.querySelectorAll(selector);
const elementsWithTextContent = [];

Expand All @@ -42,7 +42,7 @@ const findElementsWithTextContent = (selector, text) => {
/**
* Create a javascript element from HTML markup.
*/
const createElementFromHTML = (html) => {
const createElementFromHTML = (html: string) => {
const template = document.createElement('template');
template.innerHTML = html.trim();

Expand All @@ -52,7 +52,7 @@ const createElementFromHTML = (html) => {
/**
* Add the class on the given element for the duration of the timeout.
*/
const addClass = (element, addedClass, timeout) => {
const addClass = (element: HTMLElement, addedClass: string, timeout: number) => {
element.className = element.className
? `${element.className} ${addedClass}`
: addedClass;
Expand All @@ -63,7 +63,7 @@ const addClass = (element, addedClass, timeout) => {
}, timeout);
}

module.exports = {
export {
getChildPosition,
findElementsWithTextContent,
createElementFromHTML,
Expand Down
29 changes: 22 additions & 7 deletions js/jekyllTabs.js → js/jekyllTabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,23 @@ const {
appendToastMessageHTML,
} = require('./tabsHelpers');

const init = (overriddenConfiguration = {}) => {
const defaultConfiguration = {
interface CopyToClipboardSettings {
buttonHTML: string,
showToastMessageOnCopy: boolean,
toastMessage: string,
toastDuration: number,
}

interface Configuration {
syncTabsWithSameLabels: boolean;
activateTabFromUrl: boolean;
addCopyToClipboardButtons: boolean;
copyToClipboardSettings: CopyToClipboardSettings;
}

const init = (overriddenConfiguration: any = {}) => {

const defaultConfiguration: Configuration = {
syncTabsWithSameLabels: false,
activateTabFromUrl: false,
addCopyToClipboardButtons: false,
Expand All @@ -20,7 +35,7 @@ const init = (overriddenConfiguration = {}) => {
}
};

const configuration = {
const configuration: Configuration = {
...defaultConfiguration,
...overriddenConfiguration,
copyToClipboardSettings: {
Expand All @@ -29,10 +44,10 @@ const init = (overriddenConfiguration = {}) => {
}
};

const tabLinks = document.querySelectorAll('ul.tab > li > a');
const tabLinks: NodeList = document.querySelectorAll('ul.tab > li > a');

Array.prototype.forEach.call(tabLinks, (link) => {
link.addEventListener('click', (event) => {
Array.prototype.forEach.call(tabLinks, (link: HTMLAnchorElement) => {
link.addEventListener('click', (event: MouseEvent) => {
event.preventDefault();

handleTabClicked(link);
Expand Down Expand Up @@ -62,6 +77,6 @@ const init = (overriddenConfiguration = {}) => {
}
};

module.exports = {
export {
init,
}
41 changes: 22 additions & 19 deletions js/tabsHelpers.js → js/tabsHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ const {
/**
* Remove all "active" classes on li elements that belong to the given ul element.
*/
const removeActiveClasses = (ulElement) => {
const removeActiveClasses = (ulElement: HTMLUListElement) => {
const liElements = ulElement.querySelectorAll('ul > li');

Array.prototype.forEach.call(liElements, (liElement) => {
Array.prototype.forEach.call(liElements, (liElement: HTMLLIElement) => {
liElement.classList.remove('active');
});
}

/**
* Handle adding or removing active classes on tab list items.
*/
const handleTabClicked = (link) => {
const liTab = link.parentNode;
const ulTab = liTab.parentNode;
const handleTabClicked = (link: HTMLAnchorElement) => {
const liTab = link.parentNode as HTMLLIElement;
const ulTab = liTab.parentNode as HTMLUListElement;
const liPositionInUl = getChildPosition(liTab);

if (liTab.className.includes('active')) {
Expand All @@ -34,7 +34,7 @@ const handleTabClicked = (link) => {
return;
}

const tabContentElement = document.getElementById(tabContentId);
const tabContentElement = document.getElementById(tabContentId) as HTMLUListElement;

// Remove all "active" classes first.
removeActiveClasses(ulTab);
Expand All @@ -50,7 +50,7 @@ const handleTabClicked = (link) => {
*
* See https://stackoverflow.com/questions/51805395/navigator-clipboard-is-undefined
*/
const copyToClipboard = (text, callBack) => {
const copyToClipboard = (text: string, callBack: Function) => {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text);
} else {
Expand Down Expand Up @@ -105,7 +105,7 @@ const activateTabFromUrl = () => {
return;
}

const tabLink = targetedTabs.querySelector('li#' + tabIdToActivate + ' > a');
const tabLink = targetedTabs.querySelector('li#' + tabIdToActivate + ' > a') as HTMLAnchorElement;

if (!tabLink) {
return;
Expand All @@ -117,9 +117,9 @@ const activateTabFromUrl = () => {
/**
* Update the url when clicking on a tab. See method activateTabFromUrl above.
*/
const updateUrlWithActiveTab = (link) => {
const liTab = link.parentNode;
const ulTab = liTab.parentNode;
const updateUrlWithActiveTab = (link: HTMLAnchorElement) => {
const liTab = link.parentNode as HTMLLIElement;
const ulTab = liTab.parentNode as HTMLUListElement;

const searchParams = new URLSearchParams(window.location.search);
searchParams.set('active_tab', liTab.id);
Expand All @@ -131,12 +131,15 @@ const updateUrlWithActiveTab = (link) => {
/**
* Add the "Copy to clipboard" button on the top right hand side of tabs with embedded code (<pre> tags).
*/
const addCopyToClipboardButtons = ({ buttonHTML, showToastMessageOnCopy, toastDuration }) => {
const preElements = document.querySelectorAll('ul.tab-content > li pre');
const addCopyToClipboardButtons = (
{ buttonHTML, showToastMessageOnCopy, toastDuration }:
{ buttonHTML: string, showToastMessageOnCopy: boolean, toastDuration: number }
) => {
const preElements = document.querySelectorAll('ul.tab-content > li pre') as NodeListOf<HTMLPreElement>;

for(let i = 0; i < preElements.length; i++) {
const preElement = preElements[i];
const preParentNode = preElement.parentNode;
const preParentNode = preElement.parentNode as HTMLElement;
const button = createElementFromHTML(buttonHTML);

preParentNode.style.position = 'relative';
Expand All @@ -146,7 +149,7 @@ const addCopyToClipboardButtons = ({ buttonHTML, showToastMessageOnCopy, toastDu

preParentNode.appendChild(button);

let copyToClipboardCallBack;
let copyToClipboardCallBack: Function;

if (showToastMessageOnCopy) {
copyToClipboardCallBack = () => {
Expand All @@ -163,7 +166,7 @@ const addCopyToClipboardButtons = ({ buttonHTML, showToastMessageOnCopy, toastDu
/**
* Insert a div that contains the toast message at the end of the <body> tag.
*/
const appendToastMessageHTML = (toastMessage) => {
const appendToastMessageHTML = (toastMessage: string) => {
const toastMessageDiv = document.createElement('div');

toastMessageDiv.id = 'jekyll-tabs-copy-to-clipboard-message';
Expand All @@ -175,14 +178,14 @@ const appendToastMessageHTML = (toastMessage) => {
/**
* Set '.show' class on the div that contains the toast message for the given duration.
*/
const showToastMessage = (toastDuration) => {
const showToastMessage = (toastDuration: number) => {
addClass(document.getElementById('jekyll-tabs-copy-to-clipboard-message'), 'show', toastDuration);
}

/**
* Activate tabs that have the same label as the one related to the given link.
*/
const syncTabsWithSameLabels = (link) => {
const syncTabsWithSameLabels = (link: HTMLAnchorElement) => {
const linksWithSameName = findElementsWithTextContent('a', link.textContent);

for(let i = 0; i < linksWithSameName.length; i++) {
Expand All @@ -192,7 +195,7 @@ const syncTabsWithSameLabels = (link) => {
}
}

module.exports = {
export {
removeActiveClasses,
handleTabClicked,
copyToClipboard,
Expand Down
Loading

0 comments on commit 3c734a7

Please sign in to comment.