Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions src/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,44 +141,6 @@ Let's customize your experience in our Bot Designer For Discord wiki world!
Added!
```

<div class="settingembed">
<h2>Code Highlighting</h2>
<p>Input your highlighting code here! Reload the page when you finish.</p>
<button class="resetSettingButton" id="resetHG" onClick="resetHGInput()" title="Reset" aria-label="Reset">
<i class="fa fa-refresh" aria-hidden="true"></i>
</button>
<div class="codehighlighting">
<button id="copyHG" onClick="copyHGInput()" class="hgButton">
<p><i class="fa fa-clipboard" aria-hidden="true"></i> Copy</p>
</button>
<button id="reloadHG" onClick="reloadHGPage()" class="hgButton">
<p><i class="fa fa-circle-o-notch" aria-hidden="true"></i> Save and reload</p>
</button>
<button class="hgButton">
<p><a href="https://www.youtube.com/watch?v=xvFZjo5PgG0"><i class="fa fa-book" aria-hidden="true"></i> What is this?</a></p>
</button>
<textarea id="jsonhginput" oninput="updateCodeHG()" maxlength="25000"></textarea>
</div>
<p class="charCount">0 / 25000</p>
</div>

```
$nomention
$allowUserMentions[]
$reply
$botTyping

$try
$sendMessage[Hello, $username 👋, ping: $ping ms]
$if[$toLowercase[$message]==secret]
$footer[BDFD 🤩]
$endif
$catch
$sendMessage[Bye!]
$botLeave $c[Magic😉]
$endtry
```

<div class="importantReset">
<button class="resetToDefault" onmousedown="resetAllHover()" onmouseup="resettAllNone()" onmouseleave="resetAllLeave()">
<span>Reset to default settings</span>
Expand Down
8 changes: 5 additions & 3 deletions src/theme/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ if (window.playground_copyable) {
clipButton.className = "fa fa-regular fa-paste clip-button";
clipButton.title = "Copy";
clipButton.setAttribute("aria-label", clipButton.title);
clipButton.innerHTML = '<i class="tooltiptext"></i>';
const tooltipEl = document.createElement('i');
tooltipEl.className = 'tooltiptext';
clipButton.appendChild(tooltipEl);

const wrapButton = document.createElement("button");
wrapButton.className = "fa fa-solid fa-paragraph wrap-button";
Expand Down Expand Up @@ -223,12 +225,12 @@ if (window.playground_copyable) {
const clipButtons = document.querySelectorAll(".clip-button");

function hideTooltip(elem) {
elem.firstChild.innerText = "";
elem.firstChild.textContent = "";
elem.className = "fa far fa-clipboard clip-button";
}

function showTooltip(elem, msg) {
elem.firstChild.innerText = msg;
elem.firstChild.textContent = msg;
elem.className = "fa far fa-clipboard tooltipped";
}

Expand Down
45 changes: 34 additions & 11 deletions src/theme/breadcrumbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,38 @@ for (let i = 0; i < paths.length; i++) {
}
}

document.write(`<a href="${root}">Home</a><p>/</p>`);
breadcrumbLinks.forEach((link, index) => {
if (link.href) {
document.write(`<a href="${link.href}">${link.name}</a>`);
if (index < breadcrumbLinks.length - 1) {
// Add separator if not last
document.write(`<p>/</p>`);
}
} else if (link.name !== "Introduction") {
document.write(`<a>${link.name}</a>`);
// Helper to safely create elements
function createBreadcrumbLink(href, text) {
const link = document.createElement('a');
if (href) {
link.href = href;
}
});
link.textContent = text;
return link;
}

function createSeparator() {
const sep = document.createElement('p');
sep.textContent = '/';
return sep;
}

// Build breadcrumbs using DOM methods instead of document.write
(function renderBreadcrumbs() {
const container = document.currentScript.parentElement;

// Home link
container.appendChild(createBreadcrumbLink(root, 'Home'));
container.appendChild(createSeparator());

breadcrumbLinks.forEach((link, index) => {
if (link.href) {
container.appendChild(createBreadcrumbLink(link.href, link.name));
if (index < breadcrumbLinks.length - 1) {
container.appendChild(createSeparator());
}
} else if (link.name !== "Introduction") {
container.appendChild(createBreadcrumbLink(null, link.name));
}
});
})();
37 changes: 22 additions & 15 deletions src/theme/livetime.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,54 @@ document.addEventListener("DOMContentLoaded", function () {

var dayElement = document.getElementById("day-mark");
if (dayElement) {
dayElement.innerHTML = "Current Day: " + day;
dayElement.textContent = "Current Day: " + day;
}

var unixElement = document.getElementById("unix-mark");
if (unixElement) {
unixElement.innerHTML = "Current Unix-time: " + unixTimeSec;
unixElement.textContent = "Current Unix-time: " + unixTimeSec;
}

var moreUnixElement = document.getElementById("moreunix-mark");
if (moreUnixElement) {
moreUnixElement.innerHTML = `Unix Timestamp<br>
In Seconds - ${unixTimeSec}<br>
In Milliseconds - ${unixTimeMs}<br>
In Nanoseconds - ${unixTimeMs * 1000000}`;
moreUnixElement.textContent = '';
moreUnixElement.appendChild(document.createTextNode('Unix Timestamp'));
moreUnixElement.appendChild(document.createElement('br'));
moreUnixElement.appendChild(document.createTextNode('In Seconds - ' + unixTimeSec));
moreUnixElement.appendChild(document.createElement('br'));
moreUnixElement.appendChild(document.createTextNode('In Milliseconds - ' + unixTimeMs));
moreUnixElement.appendChild(document.createElement('br'));
moreUnixElement.appendChild(document.createTextNode('In Nanoseconds - ' + (unixTimeMs * 1000000)));
}

var secondElement = document.getElementById("second-mark");
if (secondElement) {
secondElement.innerHTML = "Current Second: " + second;
secondElement.textContent = "Current Second: " + second;
}

var minuteElement = document.getElementById("minute-mark");
if (minuteElement) {
minuteElement.innerHTML = "Current Minute: " + minute;
minuteElement.textContent = "Current Minute: " + minute;
}

var hourElement = document.getElementById("hour-mark");
if (hourElement) {
hourElement.innerHTML = "Current Hour: " + hour;
hourElement.textContent = "Current Hour: " + hour;
}

var yearElement = document.getElementById("year-mark");
if (yearElement) {
yearElement.innerHTML = "Current Year: " + year;
yearElement.textContent = "Current Year: " + year;
}

var monthElement = document.getElementById("month-mark");
if (monthElement) {
monthElement.innerHTML = "Current Month: " + month;
monthElement.textContent = "Current Month: " + month;
}

var dateElement = document.getElementById("date-mark");
if (dateElement) {
dateElement.innerHTML = "Current Date: " + formattedDate;
dateElement.textContent = "Current Date: " + formattedDate;
}

function getFormattedTime(timezone) {
Expand All @@ -75,7 +79,10 @@ In Nanoseconds - ${unixTimeMs * 1000000}`;
var utcTime = getFormattedTime("UTC");
var moscowTime = getFormattedTime("Europe/Moscow");
var utcDay = now.getUTCDate();

timeElement.innerHTML = `New York Time: ${utcTime}, ${utcDay}<br>Moscow Time: ${moscowTime}, ${utcDay}`;

timeElement.textContent = '';
timeElement.appendChild(document.createTextNode('New York Time: ' + utcTime + ', ' + utcDay));
timeElement.appendChild(document.createElement('br'));
timeElement.appendChild(document.createTextNode('Moscow Time: ' + moscowTime + ', ' + utcDay));
}
});
});
87 changes: 64 additions & 23 deletions src/theme/playground.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,43 @@
// Helper to escape HTML special characters
function escapeHTML(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}

// Helper to create error message element safely
function createErrorMessage(functionName, lineNumber, position, errorText) {
const playOutput = document.getElementById('play-output');
playOutput.textContent = '';

const container = document.createDocumentFragment();

container.appendChild(document.createTextNode('\u274C Function '));

const funcNameEl = document.createElement('span');
funcNameEl.id = 'errorFunctionName';
funcNameEl.textContent = functionName;
container.appendChild(funcNameEl);

container.appendChild(document.createTextNode(' at '));

const lineNumEl = document.createElement('span');
lineNumEl.id = 'errorLineNumber';
lineNumEl.textContent = `${lineNumber}:${position}`;
container.appendChild(lineNumEl);

container.appendChild(document.createTextNode(` returned an error: ${errorText}`));

playOutput.appendChild(container);
}

// Math
function handlePlaygroundInput(inputValue, functionName, operation) {
const playOutput = document.getElementById('play-output');

if (!isNaN(inputValue) && inputValue !== "") {
if (functionName === '$sqrt' && parseFloat(inputValue) < 0) {
playOutput.innerHTML = `❌ Function <p id="errorFunctionName">${functionName}</p> at <p id="errorLineNumber">1:${functionName.length + 4}</p> returned an error: the input number can't be negative`;
createErrorMessage(functionName, 1, functionName.length + 4, "the input number can't be negative");
} else {
const result = operation(inputValue);
playOutput.textContent = `Result: ${result}`;
Expand All @@ -13,21 +46,21 @@ function handlePlaygroundInput(inputValue, functionName, operation) {
if (inputValue === "") {
outputEmptyValueError(functionName, 1, 1);
} else {
let nonNumericIndex = inputValue.search(/[^0-9\.]/);
let nonNumericIndex = inputValue.search(/[^0-9\.]/);
nonNumericIndex = nonNumericIndex === -1 ? inputValue.length : nonNumericIndex + functionName.length + 3;
playOutput.innerHTML = `❌ Function <p id="errorFunctionName">${functionName}</p> at <p id="errorLineNumber">1:${nonNumericIndex}</p> returned an error: expected integer in position 1, got '${inputValue}'`;
createErrorMessage(functionName, 1, nonNumericIndex, `expected integer in position 1, got '${escapeHTML(inputValue)}'`);
}
}
}

// $ceil[]
function ceilPlayground(inputValue) {
handlePlaygroundInput(inputValue, '$ceil', Math.ceil);
handlePlaygroundInput(inputValue, '$ceil', Math.ceil);
}

// $floor[]
function floorPlayground(inputValue) {
handlePlaygroundInput(inputValue, '$floor', Math.floor);
handlePlaygroundInput(inputValue, '$floor', Math.floor);
}

// $sqrt[]
Expand All @@ -37,7 +70,7 @@ function sqrtPlayground(inputValue) {

// $round[]
function roundPlayground(inputValue) {
handlePlaygroundInput(inputValue, '$round', Math.round);
handlePlaygroundInput(inputValue, '$round', Math.round);
}

// $charCount[]
Expand All @@ -64,7 +97,7 @@ function argCountPlayground(inputValue) {
// $isNumber[]
function isNumberPlayground(inputValue) {
const playOutput = document.getElementById('play-output');
playOutput.textContent = `Is number? ${!isNaN(parseFloat(inputValue)) && isFinite(inputValue)}`;
playOutput.textContent = `Is number? ${!isNaN(parseFloat(inputValue)) && isFinite(inputValue)}`;
}

// $isInteger[]
Expand All @@ -90,42 +123,51 @@ function isBooleanPlayground(inputValue) {
playOutput.textContent = `Is boolean? ${booleanValues.includes(inputValue)}`;
}

function preserveLineBreaks(text) {
return text.replace(/\n/g, '<br>');
}

function limitLines(text, maxLines) {
const lines = text.split('\n');
return lines.slice(0, maxLines).join('\n');
}

// Helper to safely display multiline text
function displayMultilineText(element, text) {
element.textContent = '';
const lines = text.split('\n');
lines.forEach((line, index) => {
element.appendChild(document.createTextNode(line));
if (index < lines.length - 1) {
element.appendChild(document.createElement('br'));
}
});
}

// $trimSpace[]
function trimSpacePlayground(inputValue) {
const playOutput = document.getElementById('play-output');
playOutput.innerHTML = preserveLineBreaks(limitLines(inputValue.trim(), 20));
displayMultilineText(playOutput, limitLines(inputValue.trim(), 20));
editInputHeight()
}

// $toLowercase[]
function toLowercasePlayground(inputValue) {
const playOutput = document.getElementById('play-output');
playOutput.innerHTML = preserveLineBreaks(limitLines(inputValue.toLowerCase(), 20));
displayMultilineText(playOutput, limitLines(inputValue.toLowerCase(), 20));
editInputHeight()
}

// $toUppercase[]
function toUppercasePlayground(inputValue) {
const playOutput = document.getElementById('play-output');
playOutput.innerHTML = preserveLineBreaks(limitLines(inputValue.toUpperCase(), 20));
displayMultilineText(playOutput, limitLines(inputValue.toUpperCase(), 20));
editInputHeight()
}

// $toTitleCase[]
function toTitleCasePlayground(inputValue) {
const playOutput = document.getElementById('play-output');
playOutput.innerHTML = preserveLineBreaks(limitLines(inputValue.replace(/\w\S*/g, (word) =>
word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
), 20));
const titleCased = inputValue.replace(/\w\S*/g, (word) =>
word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
);
displayMultilineText(playOutput, limitLines(titleCased, 20));
editInputHeight()
}

Expand All @@ -139,11 +181,11 @@ function randomStringPlayground(inputValue) {
} else if (isNaN(inputValue)) {
let nonNumericIndex = inputValue.search(/[^0-9]/);
nonNumericIndex = nonNumericIndex === -1 ? inputValue.length : nonNumericIndex + functionName.length + 3;
playOutput.innerHTML = `❌ Function <p id="errorFunctionName">${functionName}</p> at <p id="errorLineNumber">1:${nonNumericIndex}</p> returned an error: expected integer in position 1, got '${inputValue}'`;
createErrorMessage(functionName, 1, nonNumericIndex, `expected integer in position 1, got '${escapeHTML(inputValue)}'`);
} else if (parseInt(inputValue) > 10) {
playOutput.innerHTML = `❌ Function <p id="errorFunctionName">${functionName}</p> at <p id="errorLineNumber">1:${functionName.length + 3}</p> returned an error: String length has to be leser than 10`;
} else if (parseInt(inputValue) < 1) {
playOutput.innerHTML = `❌ Function <p id="errorFunctionName">${functionName}</p> at <p id="errorLineNumber">1:${functionName.length + 3}</p> returned an error: String length has to be bigger than 0`;
createErrorMessage(functionName, 1, functionName.length + 3, "String length has to be leser than 10");
} else if (parseInt(inputValue) < 1) {
createErrorMessage(functionName, 1, functionName.length + 3, "String length has to be bigger than 0");
} else {
let length = parseInt(inputValue);
playOutput.textContent = `Random String: ` + generateRandomString(length);
Expand All @@ -162,8 +204,7 @@ function generateRandomString(length) {

// Empty value error
function outputEmptyValueError(functionName, lineNumber, position) {
const playOutput = document.getElementById('play-output');
playOutput.innerHTML = `❌ Function <p id="errorFunctionName">${functionName}</p> at <p id="errorLineNumber">${lineNumber}:${functionName.length + 2}</p> returned an error: expected valid value in position ${position}, got empty value`;
createErrorMessage(functionName, lineNumber, functionName.length + 2, `expected valid value in position ${position}, got empty value`);
}

// Better input size for large values
Expand Down
Loading