mirror of
https://github.com/LukeHagar/ui-development-kit.git
synced 2025-12-06 04:21:49 +00:00
7645 lines
230 KiB
JavaScript
7645 lines
230 KiB
JavaScript
import { c as create_ssr_component, a as subscribe, v as validate_component, e as escape, b as each, g as getContext, d as add_attribute, s as setContext, f as add_styles, h as compute_rest_props, i as spread, j as escape_attribute_value, k as escape_object, l as createEventDispatcher, m as missing_component, n as compute_slots, o as split_css_unit } from './ssr-pGtI3Kui.js';
|
||
import { s as storeHighlightJs, p as page, C as CodeBlock } from './stores-CEBzDsQs.js';
|
||
import { w as writable } from './index2-CcAcUxny.js';
|
||
import { i as initializeModalStore, g as getModalStore } from './stores2-DhhqrV6P.js';
|
||
import { p as prefersReducedMotionStore, m as modeCurrent, s as setInitialClassState } from './ProgressBar.svelte_svelte_type_style_lang-Lwm3XjGR.js';
|
||
import { d as capitalize, p as parseInitials } from './Utils-BGShQy8a.js';
|
||
import { g as getDefaultExportFromCjs } from './_commonjsHelpers-BFTU3MAI.js';
|
||
import './client-CQ5E_ugM.js';
|
||
import './exports-DuWZopOC.js';
|
||
|
||
/**
|
||
* Custom positioning reference element.
|
||
* @see https://floating-ui.com/docs/virtual-elements
|
||
*/
|
||
|
||
const min = Math.min;
|
||
const max = Math.max;
|
||
const round = Math.round;
|
||
const floor = Math.floor;
|
||
const createCoords = v => ({
|
||
x: v,
|
||
y: v
|
||
});
|
||
const oppositeSideMap = {
|
||
left: 'right',
|
||
right: 'left',
|
||
bottom: 'top',
|
||
top: 'bottom'
|
||
};
|
||
const oppositeAlignmentMap = {
|
||
start: 'end',
|
||
end: 'start'
|
||
};
|
||
function clamp(start, value, end) {
|
||
return max(start, min(value, end));
|
||
}
|
||
function evaluate(value, param) {
|
||
return typeof value === 'function' ? value(param) : value;
|
||
}
|
||
function getSide(placement) {
|
||
return placement.split('-')[0];
|
||
}
|
||
function getAlignment(placement) {
|
||
return placement.split('-')[1];
|
||
}
|
||
function getOppositeAxis(axis) {
|
||
return axis === 'x' ? 'y' : 'x';
|
||
}
|
||
function getAxisLength(axis) {
|
||
return axis === 'y' ? 'height' : 'width';
|
||
}
|
||
function getSideAxis(placement) {
|
||
return ['top', 'bottom'].includes(getSide(placement)) ? 'y' : 'x';
|
||
}
|
||
function getAlignmentAxis(placement) {
|
||
return getOppositeAxis(getSideAxis(placement));
|
||
}
|
||
function getAlignmentSides(placement, rects, rtl) {
|
||
if (rtl === void 0) {
|
||
rtl = false;
|
||
}
|
||
const alignment = getAlignment(placement);
|
||
const alignmentAxis = getAlignmentAxis(placement);
|
||
const length = getAxisLength(alignmentAxis);
|
||
let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
|
||
if (rects.reference[length] > rects.floating[length]) {
|
||
mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
|
||
}
|
||
return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
|
||
}
|
||
function getExpandedPlacements(placement) {
|
||
const oppositePlacement = getOppositePlacement(placement);
|
||
return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
|
||
}
|
||
function getOppositeAlignmentPlacement(placement) {
|
||
return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]);
|
||
}
|
||
function getSideList(side, isStart, rtl) {
|
||
const lr = ['left', 'right'];
|
||
const rl = ['right', 'left'];
|
||
const tb = ['top', 'bottom'];
|
||
const bt = ['bottom', 'top'];
|
||
switch (side) {
|
||
case 'top':
|
||
case 'bottom':
|
||
if (rtl) return isStart ? rl : lr;
|
||
return isStart ? lr : rl;
|
||
case 'left':
|
||
case 'right':
|
||
return isStart ? tb : bt;
|
||
default:
|
||
return [];
|
||
}
|
||
}
|
||
function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
|
||
const alignment = getAlignment(placement);
|
||
let list = getSideList(getSide(placement), direction === 'start', rtl);
|
||
if (alignment) {
|
||
list = list.map(side => side + "-" + alignment);
|
||
if (flipAlignment) {
|
||
list = list.concat(list.map(getOppositeAlignmentPlacement));
|
||
}
|
||
}
|
||
return list;
|
||
}
|
||
function getOppositePlacement(placement) {
|
||
return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]);
|
||
}
|
||
function expandPaddingObject(padding) {
|
||
return {
|
||
top: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
left: 0,
|
||
...padding
|
||
};
|
||
}
|
||
function getPaddingObject(padding) {
|
||
return typeof padding !== 'number' ? expandPaddingObject(padding) : {
|
||
top: padding,
|
||
right: padding,
|
||
bottom: padding,
|
||
left: padding
|
||
};
|
||
}
|
||
function rectToClientRect(rect) {
|
||
return {
|
||
...rect,
|
||
top: rect.y,
|
||
left: rect.x,
|
||
right: rect.x + rect.width,
|
||
bottom: rect.y + rect.height
|
||
};
|
||
}
|
||
|
||
function computeCoordsFromPlacement(_ref, placement, rtl) {
|
||
let {
|
||
reference,
|
||
floating
|
||
} = _ref;
|
||
const sideAxis = getSideAxis(placement);
|
||
const alignmentAxis = getAlignmentAxis(placement);
|
||
const alignLength = getAxisLength(alignmentAxis);
|
||
const side = getSide(placement);
|
||
const isVertical = sideAxis === 'y';
|
||
const commonX = reference.x + reference.width / 2 - floating.width / 2;
|
||
const commonY = reference.y + reference.height / 2 - floating.height / 2;
|
||
const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
|
||
let coords;
|
||
switch (side) {
|
||
case 'top':
|
||
coords = {
|
||
x: commonX,
|
||
y: reference.y - floating.height
|
||
};
|
||
break;
|
||
case 'bottom':
|
||
coords = {
|
||
x: commonX,
|
||
y: reference.y + reference.height
|
||
};
|
||
break;
|
||
case 'right':
|
||
coords = {
|
||
x: reference.x + reference.width,
|
||
y: commonY
|
||
};
|
||
break;
|
||
case 'left':
|
||
coords = {
|
||
x: reference.x - floating.width,
|
||
y: commonY
|
||
};
|
||
break;
|
||
default:
|
||
coords = {
|
||
x: reference.x,
|
||
y: reference.y
|
||
};
|
||
}
|
||
switch (getAlignment(placement)) {
|
||
case 'start':
|
||
coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
|
||
break;
|
||
case 'end':
|
||
coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
|
||
break;
|
||
}
|
||
return coords;
|
||
}
|
||
|
||
/**
|
||
* Computes the `x` and `y` coordinates that will place the floating element
|
||
* next to a given reference element.
|
||
*
|
||
* This export does not have any `platform` interface logic. You will need to
|
||
* write one for the platform you are using Floating UI with.
|
||
*/
|
||
const computePosition$1 = async (reference, floating, config) => {
|
||
const {
|
||
placement = 'bottom',
|
||
strategy = 'absolute',
|
||
middleware = [],
|
||
platform
|
||
} = config;
|
||
const validMiddleware = middleware.filter(Boolean);
|
||
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
|
||
let rects = await platform.getElementRects({
|
||
reference,
|
||
floating,
|
||
strategy
|
||
});
|
||
let {
|
||
x,
|
||
y
|
||
} = computeCoordsFromPlacement(rects, placement, rtl);
|
||
let statefulPlacement = placement;
|
||
let middlewareData = {};
|
||
let resetCount = 0;
|
||
for (let i = 0; i < validMiddleware.length; i++) {
|
||
const {
|
||
name,
|
||
fn
|
||
} = validMiddleware[i];
|
||
const {
|
||
x: nextX,
|
||
y: nextY,
|
||
data,
|
||
reset
|
||
} = await fn({
|
||
x,
|
||
y,
|
||
initialPlacement: placement,
|
||
placement: statefulPlacement,
|
||
strategy,
|
||
middlewareData,
|
||
rects,
|
||
platform,
|
||
elements: {
|
||
reference,
|
||
floating
|
||
}
|
||
});
|
||
x = nextX != null ? nextX : x;
|
||
y = nextY != null ? nextY : y;
|
||
middlewareData = {
|
||
...middlewareData,
|
||
[name]: {
|
||
...middlewareData[name],
|
||
...data
|
||
}
|
||
};
|
||
if (reset && resetCount <= 50) {
|
||
resetCount++;
|
||
if (typeof reset === 'object') {
|
||
if (reset.placement) {
|
||
statefulPlacement = reset.placement;
|
||
}
|
||
if (reset.rects) {
|
||
rects = reset.rects === true ? await platform.getElementRects({
|
||
reference,
|
||
floating,
|
||
strategy
|
||
}) : reset.rects;
|
||
}
|
||
({
|
||
x,
|
||
y
|
||
} = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
|
||
}
|
||
i = -1;
|
||
}
|
||
}
|
||
return {
|
||
x,
|
||
y,
|
||
placement: statefulPlacement,
|
||
strategy,
|
||
middlewareData
|
||
};
|
||
};
|
||
|
||
/**
|
||
* Resolves with an object of overflow side offsets that determine how much the
|
||
* element is overflowing a given clipping boundary on each side.
|
||
* - positive = overflowing the boundary by that number of pixels
|
||
* - negative = how many pixels left before it will overflow
|
||
* - 0 = lies flush with the boundary
|
||
* @see https://floating-ui.com/docs/detectOverflow
|
||
*/
|
||
async function detectOverflow(state, options) {
|
||
var _await$platform$isEle;
|
||
if (options === void 0) {
|
||
options = {};
|
||
}
|
||
const {
|
||
x,
|
||
y,
|
||
platform,
|
||
rects,
|
||
elements,
|
||
strategy
|
||
} = state;
|
||
const {
|
||
boundary = 'clippingAncestors',
|
||
rootBoundary = 'viewport',
|
||
elementContext = 'floating',
|
||
altBoundary = false,
|
||
padding = 0
|
||
} = evaluate(options, state);
|
||
const paddingObject = getPaddingObject(padding);
|
||
const altContext = elementContext === 'floating' ? 'reference' : 'floating';
|
||
const element = elements[altBoundary ? altContext : elementContext];
|
||
const clippingClientRect = rectToClientRect(await platform.getClippingRect({
|
||
element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
|
||
boundary,
|
||
rootBoundary,
|
||
strategy
|
||
}));
|
||
const rect = elementContext === 'floating' ? {
|
||
...rects.floating,
|
||
x,
|
||
y
|
||
} : rects.reference;
|
||
const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
|
||
const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
|
||
x: 1,
|
||
y: 1
|
||
} : {
|
||
x: 1,
|
||
y: 1
|
||
};
|
||
const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
|
||
elements,
|
||
rect,
|
||
offsetParent,
|
||
strategy
|
||
}) : rect);
|
||
return {
|
||
top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
|
||
bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
|
||
left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
|
||
right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Provides data to position an inner element of the floating element so that it
|
||
* appears centered to the reference element.
|
||
* @see https://floating-ui.com/docs/arrow
|
||
*/
|
||
const arrow$1 = options => ({
|
||
name: 'arrow',
|
||
options,
|
||
async fn(state) {
|
||
const {
|
||
x,
|
||
y,
|
||
placement,
|
||
rects,
|
||
platform,
|
||
elements,
|
||
middlewareData
|
||
} = state;
|
||
// Since `element` is required, we don't Partial<> the type.
|
||
const {
|
||
element,
|
||
padding = 0
|
||
} = evaluate(options, state) || {};
|
||
if (element == null) {
|
||
return {};
|
||
}
|
||
const paddingObject = getPaddingObject(padding);
|
||
const coords = {
|
||
x,
|
||
y
|
||
};
|
||
const axis = getAlignmentAxis(placement);
|
||
const length = getAxisLength(axis);
|
||
const arrowDimensions = await platform.getDimensions(element);
|
||
const isYAxis = axis === 'y';
|
||
const minProp = isYAxis ? 'top' : 'left';
|
||
const maxProp = isYAxis ? 'bottom' : 'right';
|
||
const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
|
||
const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
|
||
const startDiff = coords[axis] - rects.reference[axis];
|
||
const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));
|
||
let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
|
||
|
||
// DOM platform can return `window` as the `offsetParent`.
|
||
if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {
|
||
clientSize = elements.floating[clientProp] || rects.floating[length];
|
||
}
|
||
const centerToReference = endDiff / 2 - startDiff / 2;
|
||
|
||
// If the padding is large enough that it causes the arrow to no longer be
|
||
// centered, modify the padding so that it is centered.
|
||
const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
|
||
const minPadding = min(paddingObject[minProp], largestPossiblePadding);
|
||
const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);
|
||
|
||
// Make sure the arrow doesn't overflow the floating element if the center
|
||
// point is outside the floating element's bounds.
|
||
const min$1 = minPadding;
|
||
const max = clientSize - arrowDimensions[length] - maxPadding;
|
||
const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
|
||
const offset = clamp(min$1, center, max);
|
||
|
||
// If the reference is small enough that the arrow's padding causes it to
|
||
// to point to nothing for an aligned placement, adjust the offset of the
|
||
// floating element itself. To ensure `shift()` continues to take action,
|
||
// a single reset is performed when this is true.
|
||
const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
|
||
const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
|
||
return {
|
||
[axis]: coords[axis] + alignmentOffset,
|
||
data: {
|
||
[axis]: offset,
|
||
centerOffset: center - offset - alignmentOffset,
|
||
...(shouldAddOffset && {
|
||
alignmentOffset
|
||
})
|
||
},
|
||
reset: shouldAddOffset
|
||
};
|
||
}
|
||
});
|
||
|
||
/**
|
||
* Optimizes the visibility of the floating element by flipping the `placement`
|
||
* in order to keep it in view when the preferred placement(s) will overflow the
|
||
* clipping boundary. Alternative to `autoPlacement`.
|
||
* @see https://floating-ui.com/docs/flip
|
||
*/
|
||
const flip$1 = function (options) {
|
||
if (options === void 0) {
|
||
options = {};
|
||
}
|
||
return {
|
||
name: 'flip',
|
||
options,
|
||
async fn(state) {
|
||
var _middlewareData$arrow, _middlewareData$flip;
|
||
const {
|
||
placement,
|
||
middlewareData,
|
||
rects,
|
||
initialPlacement,
|
||
platform,
|
||
elements
|
||
} = state;
|
||
const {
|
||
mainAxis: checkMainAxis = true,
|
||
crossAxis: checkCrossAxis = true,
|
||
fallbackPlacements: specifiedFallbackPlacements,
|
||
fallbackStrategy = 'bestFit',
|
||
fallbackAxisSideDirection = 'none',
|
||
flipAlignment = true,
|
||
...detectOverflowOptions
|
||
} = evaluate(options, state);
|
||
|
||
// If a reset by the arrow was caused due to an alignment offset being
|
||
// added, we should skip any logic now since `flip()` has already done its
|
||
// work.
|
||
// https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643
|
||
if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
|
||
return {};
|
||
}
|
||
const side = getSide(placement);
|
||
const isBasePlacement = getSide(initialPlacement) === initialPlacement;
|
||
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
|
||
const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
|
||
if (!specifiedFallbackPlacements && fallbackAxisSideDirection !== 'none') {
|
||
fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
|
||
}
|
||
const placements = [initialPlacement, ...fallbackPlacements];
|
||
const overflow = await detectOverflow(state, detectOverflowOptions);
|
||
const overflows = [];
|
||
let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
|
||
if (checkMainAxis) {
|
||
overflows.push(overflow[side]);
|
||
}
|
||
if (checkCrossAxis) {
|
||
const sides = getAlignmentSides(placement, rects, rtl);
|
||
overflows.push(overflow[sides[0]], overflow[sides[1]]);
|
||
}
|
||
overflowsData = [...overflowsData, {
|
||
placement,
|
||
overflows
|
||
}];
|
||
|
||
// One or more sides is overflowing.
|
||
if (!overflows.every(side => side <= 0)) {
|
||
var _middlewareData$flip2, _overflowsData$filter;
|
||
const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
|
||
const nextPlacement = placements[nextIndex];
|
||
if (nextPlacement) {
|
||
// Try next placement and re-run the lifecycle.
|
||
return {
|
||
data: {
|
||
index: nextIndex,
|
||
overflows: overflowsData
|
||
},
|
||
reset: {
|
||
placement: nextPlacement
|
||
}
|
||
};
|
||
}
|
||
|
||
// First, find the candidates that fit on the mainAxis side of overflow,
|
||
// then find the placement that fits the best on the main crossAxis side.
|
||
let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
|
||
|
||
// Otherwise fallback.
|
||
if (!resetPlacement) {
|
||
switch (fallbackStrategy) {
|
||
case 'bestFit':
|
||
{
|
||
var _overflowsData$map$so;
|
||
const placement = (_overflowsData$map$so = overflowsData.map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$map$so[0];
|
||
if (placement) {
|
||
resetPlacement = placement;
|
||
}
|
||
break;
|
||
}
|
||
case 'initialPlacement':
|
||
resetPlacement = initialPlacement;
|
||
break;
|
||
}
|
||
}
|
||
if (placement !== resetPlacement) {
|
||
return {
|
||
reset: {
|
||
placement: resetPlacement
|
||
}
|
||
};
|
||
}
|
||
}
|
||
return {};
|
||
}
|
||
};
|
||
};
|
||
|
||
// For type backwards-compatibility, the `OffsetOptions` type was also
|
||
// Derivable.
|
||
|
||
async function convertValueToCoords(state, options) {
|
||
const {
|
||
placement,
|
||
platform,
|
||
elements
|
||
} = state;
|
||
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
|
||
const side = getSide(placement);
|
||
const alignment = getAlignment(placement);
|
||
const isVertical = getSideAxis(placement) === 'y';
|
||
const mainAxisMulti = ['left', 'top'].includes(side) ? -1 : 1;
|
||
const crossAxisMulti = rtl && isVertical ? -1 : 1;
|
||
const rawValue = evaluate(options, state);
|
||
let {
|
||
mainAxis,
|
||
crossAxis,
|
||
alignmentAxis
|
||
} = typeof rawValue === 'number' ? {
|
||
mainAxis: rawValue,
|
||
crossAxis: 0,
|
||
alignmentAxis: null
|
||
} : {
|
||
mainAxis: 0,
|
||
crossAxis: 0,
|
||
alignmentAxis: null,
|
||
...rawValue
|
||
};
|
||
if (alignment && typeof alignmentAxis === 'number') {
|
||
crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
|
||
}
|
||
return isVertical ? {
|
||
x: crossAxis * crossAxisMulti,
|
||
y: mainAxis * mainAxisMulti
|
||
} : {
|
||
x: mainAxis * mainAxisMulti,
|
||
y: crossAxis * crossAxisMulti
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Modifies the placement by translating the floating element along the
|
||
* specified axes.
|
||
* A number (shorthand for `mainAxis` or distance), or an axes configuration
|
||
* object may be passed.
|
||
* @see https://floating-ui.com/docs/offset
|
||
*/
|
||
const offset = function (options) {
|
||
if (options === void 0) {
|
||
options = 0;
|
||
}
|
||
return {
|
||
name: 'offset',
|
||
options,
|
||
async fn(state) {
|
||
var _middlewareData$offse, _middlewareData$arrow;
|
||
const {
|
||
x,
|
||
y,
|
||
placement,
|
||
middlewareData
|
||
} = state;
|
||
const diffCoords = await convertValueToCoords(state, options);
|
||
|
||
// If the placement is the same and the arrow caused an alignment offset
|
||
// then we don't need to change the positioning coordinates.
|
||
if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
|
||
return {};
|
||
}
|
||
return {
|
||
x: x + diffCoords.x,
|
||
y: y + diffCoords.y,
|
||
data: {
|
||
...diffCoords,
|
||
placement
|
||
}
|
||
};
|
||
}
|
||
};
|
||
};
|
||
|
||
/**
|
||
* Optimizes the visibility of the floating element by shifting it in order to
|
||
* keep it in view when it will overflow the clipping boundary.
|
||
* @see https://floating-ui.com/docs/shift
|
||
*/
|
||
const shift$1 = function (options) {
|
||
if (options === void 0) {
|
||
options = {};
|
||
}
|
||
return {
|
||
name: 'shift',
|
||
options,
|
||
async fn(state) {
|
||
const {
|
||
x,
|
||
y,
|
||
placement
|
||
} = state;
|
||
const {
|
||
mainAxis: checkMainAxis = true,
|
||
crossAxis: checkCrossAxis = false,
|
||
limiter = {
|
||
fn: _ref => {
|
||
let {
|
||
x,
|
||
y
|
||
} = _ref;
|
||
return {
|
||
x,
|
||
y
|
||
};
|
||
}
|
||
},
|
||
...detectOverflowOptions
|
||
} = evaluate(options, state);
|
||
const coords = {
|
||
x,
|
||
y
|
||
};
|
||
const overflow = await detectOverflow(state, detectOverflowOptions);
|
||
const crossAxis = getSideAxis(getSide(placement));
|
||
const mainAxis = getOppositeAxis(crossAxis);
|
||
let mainAxisCoord = coords[mainAxis];
|
||
let crossAxisCoord = coords[crossAxis];
|
||
if (checkMainAxis) {
|
||
const minSide = mainAxis === 'y' ? 'top' : 'left';
|
||
const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
|
||
const min = mainAxisCoord + overflow[minSide];
|
||
const max = mainAxisCoord - overflow[maxSide];
|
||
mainAxisCoord = clamp(min, mainAxisCoord, max);
|
||
}
|
||
if (checkCrossAxis) {
|
||
const minSide = crossAxis === 'y' ? 'top' : 'left';
|
||
const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
|
||
const min = crossAxisCoord + overflow[minSide];
|
||
const max = crossAxisCoord - overflow[maxSide];
|
||
crossAxisCoord = clamp(min, crossAxisCoord, max);
|
||
}
|
||
const limitedCoords = limiter.fn({
|
||
...state,
|
||
[mainAxis]: mainAxisCoord,
|
||
[crossAxis]: crossAxisCoord
|
||
});
|
||
return {
|
||
...limitedCoords,
|
||
data: {
|
||
x: limitedCoords.x - x,
|
||
y: limitedCoords.y - y
|
||
}
|
||
};
|
||
}
|
||
};
|
||
};
|
||
|
||
function getNodeName(node) {
|
||
if (isNode(node)) {
|
||
return (node.nodeName || '').toLowerCase();
|
||
}
|
||
// Mocked nodes in testing environments may not be instances of Node. By
|
||
// returning `#document` an infinite loop won't occur.
|
||
// https://github.com/floating-ui/floating-ui/issues/2317
|
||
return '#document';
|
||
}
|
||
function getWindow(node) {
|
||
var _node$ownerDocument;
|
||
return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
|
||
}
|
||
function getDocumentElement(node) {
|
||
var _ref;
|
||
return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
|
||
}
|
||
function isNode(value) {
|
||
return value instanceof Node || value instanceof getWindow(value).Node;
|
||
}
|
||
function isElement(value) {
|
||
return value instanceof Element || value instanceof getWindow(value).Element;
|
||
}
|
||
function isHTMLElement(value) {
|
||
return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
|
||
}
|
||
function isShadowRoot(value) {
|
||
// Browsers without `ShadowRoot` support.
|
||
if (typeof ShadowRoot === 'undefined') {
|
||
return false;
|
||
}
|
||
return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
|
||
}
|
||
function isOverflowElement(element) {
|
||
const {
|
||
overflow,
|
||
overflowX,
|
||
overflowY,
|
||
display
|
||
} = getComputedStyle$1(element);
|
||
return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display);
|
||
}
|
||
function isTableElement(element) {
|
||
return ['table', 'td', 'th'].includes(getNodeName(element));
|
||
}
|
||
function isContainingBlock(element) {
|
||
const webkit = isWebKit();
|
||
const css = getComputedStyle$1(element);
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
|
||
return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
|
||
}
|
||
function getContainingBlock(element) {
|
||
let currentNode = getParentNode(element);
|
||
while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
|
||
if (isContainingBlock(currentNode)) {
|
||
return currentNode;
|
||
} else {
|
||
currentNode = getParentNode(currentNode);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
function isWebKit() {
|
||
if (typeof CSS === 'undefined' || !CSS.supports) return false;
|
||
return CSS.supports('-webkit-backdrop-filter', 'none');
|
||
}
|
||
function isLastTraversableNode(node) {
|
||
return ['html', 'body', '#document'].includes(getNodeName(node));
|
||
}
|
||
function getComputedStyle$1(element) {
|
||
return getWindow(element).getComputedStyle(element);
|
||
}
|
||
function getNodeScroll(element) {
|
||
if (isElement(element)) {
|
||
return {
|
||
scrollLeft: element.scrollLeft,
|
||
scrollTop: element.scrollTop
|
||
};
|
||
}
|
||
return {
|
||
scrollLeft: element.pageXOffset,
|
||
scrollTop: element.pageYOffset
|
||
};
|
||
}
|
||
function getParentNode(node) {
|
||
if (getNodeName(node) === 'html') {
|
||
return node;
|
||
}
|
||
const result =
|
||
// Step into the shadow DOM of the parent of a slotted node.
|
||
node.assignedSlot ||
|
||
// DOM Element detected.
|
||
node.parentNode ||
|
||
// ShadowRoot detected.
|
||
isShadowRoot(node) && node.host ||
|
||
// Fallback.
|
||
getDocumentElement(node);
|
||
return isShadowRoot(result) ? result.host : result;
|
||
}
|
||
function getNearestOverflowAncestor(node) {
|
||
const parentNode = getParentNode(node);
|
||
if (isLastTraversableNode(parentNode)) {
|
||
return node.ownerDocument ? node.ownerDocument.body : node.body;
|
||
}
|
||
if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
|
||
return parentNode;
|
||
}
|
||
return getNearestOverflowAncestor(parentNode);
|
||
}
|
||
function getOverflowAncestors(node, list, traverseIframes) {
|
||
var _node$ownerDocument2;
|
||
if (list === void 0) {
|
||
list = [];
|
||
}
|
||
if (traverseIframes === void 0) {
|
||
traverseIframes = true;
|
||
}
|
||
const scrollableAncestor = getNearestOverflowAncestor(node);
|
||
const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
|
||
const win = getWindow(scrollableAncestor);
|
||
if (isBody) {
|
||
return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], win.frameElement && traverseIframes ? getOverflowAncestors(win.frameElement) : []);
|
||
}
|
||
return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
|
||
}
|
||
|
||
function getCssDimensions(element) {
|
||
const css = getComputedStyle$1(element);
|
||
// In testing environments, the `width` and `height` properties are empty
|
||
// strings for SVG elements, returning NaN. Fallback to `0` in this case.
|
||
let width = parseFloat(css.width) || 0;
|
||
let height = parseFloat(css.height) || 0;
|
||
const hasOffset = isHTMLElement(element);
|
||
const offsetWidth = hasOffset ? element.offsetWidth : width;
|
||
const offsetHeight = hasOffset ? element.offsetHeight : height;
|
||
const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
|
||
if (shouldFallback) {
|
||
width = offsetWidth;
|
||
height = offsetHeight;
|
||
}
|
||
return {
|
||
width,
|
||
height,
|
||
$: shouldFallback
|
||
};
|
||
}
|
||
|
||
function unwrapElement(element) {
|
||
return !isElement(element) ? element.contextElement : element;
|
||
}
|
||
|
||
function getScale(element) {
|
||
const domElement = unwrapElement(element);
|
||
if (!isHTMLElement(domElement)) {
|
||
return createCoords(1);
|
||
}
|
||
const rect = domElement.getBoundingClientRect();
|
||
const {
|
||
width,
|
||
height,
|
||
$
|
||
} = getCssDimensions(domElement);
|
||
let x = ($ ? round(rect.width) : rect.width) / width;
|
||
let y = ($ ? round(rect.height) : rect.height) / height;
|
||
|
||
// 0, NaN, or Infinity should always fallback to 1.
|
||
|
||
if (!x || !Number.isFinite(x)) {
|
||
x = 1;
|
||
}
|
||
if (!y || !Number.isFinite(y)) {
|
||
y = 1;
|
||
}
|
||
return {
|
||
x,
|
||
y
|
||
};
|
||
}
|
||
|
||
const noOffsets = /*#__PURE__*/createCoords(0);
|
||
function getVisualOffsets(element) {
|
||
const win = getWindow(element);
|
||
if (!isWebKit() || !win.visualViewport) {
|
||
return noOffsets;
|
||
}
|
||
return {
|
||
x: win.visualViewport.offsetLeft,
|
||
y: win.visualViewport.offsetTop
|
||
};
|
||
}
|
||
function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
|
||
if (isFixed === void 0) {
|
||
isFixed = false;
|
||
}
|
||
if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
|
||
return false;
|
||
}
|
||
return isFixed;
|
||
}
|
||
|
||
function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
|
||
if (includeScale === void 0) {
|
||
includeScale = false;
|
||
}
|
||
if (isFixedStrategy === void 0) {
|
||
isFixedStrategy = false;
|
||
}
|
||
const clientRect = element.getBoundingClientRect();
|
||
const domElement = unwrapElement(element);
|
||
let scale = createCoords(1);
|
||
if (includeScale) {
|
||
if (offsetParent) {
|
||
if (isElement(offsetParent)) {
|
||
scale = getScale(offsetParent);
|
||
}
|
||
} else {
|
||
scale = getScale(element);
|
||
}
|
||
}
|
||
const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
|
||
let x = (clientRect.left + visualOffsets.x) / scale.x;
|
||
let y = (clientRect.top + visualOffsets.y) / scale.y;
|
||
let width = clientRect.width / scale.x;
|
||
let height = clientRect.height / scale.y;
|
||
if (domElement) {
|
||
const win = getWindow(domElement);
|
||
const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
|
||
let currentWin = win;
|
||
let currentIFrame = currentWin.frameElement;
|
||
while (currentIFrame && offsetParent && offsetWin !== currentWin) {
|
||
const iframeScale = getScale(currentIFrame);
|
||
const iframeRect = currentIFrame.getBoundingClientRect();
|
||
const css = getComputedStyle$1(currentIFrame);
|
||
const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
|
||
const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
|
||
x *= iframeScale.x;
|
||
y *= iframeScale.y;
|
||
width *= iframeScale.x;
|
||
height *= iframeScale.y;
|
||
x += left;
|
||
y += top;
|
||
currentWin = getWindow(currentIFrame);
|
||
currentIFrame = currentWin.frameElement;
|
||
}
|
||
}
|
||
return rectToClientRect({
|
||
width,
|
||
height,
|
||
x,
|
||
y
|
||
});
|
||
}
|
||
|
||
const topLayerSelectors = [':popover-open', ':modal'];
|
||
function isTopLayer(floating) {
|
||
return topLayerSelectors.some(selector => {
|
||
try {
|
||
return floating.matches(selector);
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
});
|
||
}
|
||
|
||
function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
|
||
let {
|
||
elements,
|
||
rect,
|
||
offsetParent,
|
||
strategy
|
||
} = _ref;
|
||
const isFixed = strategy === 'fixed';
|
||
const documentElement = getDocumentElement(offsetParent);
|
||
const topLayer = elements ? isTopLayer(elements.floating) : false;
|
||
if (offsetParent === documentElement || topLayer && isFixed) {
|
||
return rect;
|
||
}
|
||
let scroll = {
|
||
scrollLeft: 0,
|
||
scrollTop: 0
|
||
};
|
||
let scale = createCoords(1);
|
||
const offsets = createCoords(0);
|
||
const isOffsetParentAnElement = isHTMLElement(offsetParent);
|
||
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
|
||
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
|
||
scroll = getNodeScroll(offsetParent);
|
||
}
|
||
if (isHTMLElement(offsetParent)) {
|
||
const offsetRect = getBoundingClientRect(offsetParent);
|
||
scale = getScale(offsetParent);
|
||
offsets.x = offsetRect.x + offsetParent.clientLeft;
|
||
offsets.y = offsetRect.y + offsetParent.clientTop;
|
||
}
|
||
}
|
||
return {
|
||
width: rect.width * scale.x,
|
||
height: rect.height * scale.y,
|
||
x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x,
|
||
y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y
|
||
};
|
||
}
|
||
|
||
function getClientRects(element) {
|
||
return Array.from(element.getClientRects());
|
||
}
|
||
|
||
function getWindowScrollBarX(element) {
|
||
// If <html> has a CSS width greater than the viewport, then this will be
|
||
// incorrect for RTL.
|
||
return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;
|
||
}
|
||
|
||
// Gets the entire size of the scrollable document area, even extending outside
|
||
// of the `<html>` and `<body>` rect bounds if horizontally scrollable.
|
||
function getDocumentRect(element) {
|
||
const html = getDocumentElement(element);
|
||
const scroll = getNodeScroll(element);
|
||
const body = element.ownerDocument.body;
|
||
const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
|
||
const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
|
||
let x = -scroll.scrollLeft + getWindowScrollBarX(element);
|
||
const y = -scroll.scrollTop;
|
||
if (getComputedStyle$1(body).direction === 'rtl') {
|
||
x += max(html.clientWidth, body.clientWidth) - width;
|
||
}
|
||
return {
|
||
width,
|
||
height,
|
||
x,
|
||
y
|
||
};
|
||
}
|
||
|
||
function getViewportRect(element, strategy) {
|
||
const win = getWindow(element);
|
||
const html = getDocumentElement(element);
|
||
const visualViewport = win.visualViewport;
|
||
let width = html.clientWidth;
|
||
let height = html.clientHeight;
|
||
let x = 0;
|
||
let y = 0;
|
||
if (visualViewport) {
|
||
width = visualViewport.width;
|
||
height = visualViewport.height;
|
||
const visualViewportBased = isWebKit();
|
||
if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
|
||
x = visualViewport.offsetLeft;
|
||
y = visualViewport.offsetTop;
|
||
}
|
||
}
|
||
return {
|
||
width,
|
||
height,
|
||
x,
|
||
y
|
||
};
|
||
}
|
||
|
||
// Returns the inner client rect, subtracting scrollbars if present.
|
||
function getInnerBoundingClientRect(element, strategy) {
|
||
const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
|
||
const top = clientRect.top + element.clientTop;
|
||
const left = clientRect.left + element.clientLeft;
|
||
const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
|
||
const width = element.clientWidth * scale.x;
|
||
const height = element.clientHeight * scale.y;
|
||
const x = left * scale.x;
|
||
const y = top * scale.y;
|
||
return {
|
||
width,
|
||
height,
|
||
x,
|
||
y
|
||
};
|
||
}
|
||
function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
|
||
let rect;
|
||
if (clippingAncestor === 'viewport') {
|
||
rect = getViewportRect(element, strategy);
|
||
} else if (clippingAncestor === 'document') {
|
||
rect = getDocumentRect(getDocumentElement(element));
|
||
} else if (isElement(clippingAncestor)) {
|
||
rect = getInnerBoundingClientRect(clippingAncestor, strategy);
|
||
} else {
|
||
const visualOffsets = getVisualOffsets(element);
|
||
rect = {
|
||
...clippingAncestor,
|
||
x: clippingAncestor.x - visualOffsets.x,
|
||
y: clippingAncestor.y - visualOffsets.y
|
||
};
|
||
}
|
||
return rectToClientRect(rect);
|
||
}
|
||
function hasFixedPositionAncestor(element, stopNode) {
|
||
const parentNode = getParentNode(element);
|
||
if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
|
||
return false;
|
||
}
|
||
return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
|
||
}
|
||
|
||
// A "clipping ancestor" is an `overflow` element with the characteristic of
|
||
// clipping (or hiding) child elements. This returns all clipping ancestors
|
||
// of the given element up the tree.
|
||
function getClippingElementAncestors(element, cache) {
|
||
const cachedResult = cache.get(element);
|
||
if (cachedResult) {
|
||
return cachedResult;
|
||
}
|
||
let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
|
||
let currentContainingBlockComputedStyle = null;
|
||
const elementIsFixed = getComputedStyle$1(element).position === 'fixed';
|
||
let currentNode = elementIsFixed ? getParentNode(element) : element;
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
|
||
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
|
||
const computedStyle = getComputedStyle$1(currentNode);
|
||
const currentNodeIsContaining = isContainingBlock(currentNode);
|
||
if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
|
||
currentContainingBlockComputedStyle = null;
|
||
}
|
||
const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
|
||
if (shouldDropCurrentNode) {
|
||
// Drop non-containing blocks.
|
||
result = result.filter(ancestor => ancestor !== currentNode);
|
||
} else {
|
||
// Record last containing block for next iteration.
|
||
currentContainingBlockComputedStyle = computedStyle;
|
||
}
|
||
currentNode = getParentNode(currentNode);
|
||
}
|
||
cache.set(element, result);
|
||
return result;
|
||
}
|
||
|
||
// Gets the maximum area that the element is visible in due to any number of
|
||
// clipping ancestors.
|
||
function getClippingRect(_ref) {
|
||
let {
|
||
element,
|
||
boundary,
|
||
rootBoundary,
|
||
strategy
|
||
} = _ref;
|
||
const elementClippingAncestors = boundary === 'clippingAncestors' ? getClippingElementAncestors(element, this._c) : [].concat(boundary);
|
||
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
|
||
const firstClippingAncestor = clippingAncestors[0];
|
||
const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
|
||
const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
|
||
accRect.top = max(rect.top, accRect.top);
|
||
accRect.right = min(rect.right, accRect.right);
|
||
accRect.bottom = min(rect.bottom, accRect.bottom);
|
||
accRect.left = max(rect.left, accRect.left);
|
||
return accRect;
|
||
}, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
|
||
return {
|
||
width: clippingRect.right - clippingRect.left,
|
||
height: clippingRect.bottom - clippingRect.top,
|
||
x: clippingRect.left,
|
||
y: clippingRect.top
|
||
};
|
||
}
|
||
|
||
function getDimensions(element) {
|
||
const {
|
||
width,
|
||
height
|
||
} = getCssDimensions(element);
|
||
return {
|
||
width,
|
||
height
|
||
};
|
||
}
|
||
|
||
function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
|
||
const isOffsetParentAnElement = isHTMLElement(offsetParent);
|
||
const documentElement = getDocumentElement(offsetParent);
|
||
const isFixed = strategy === 'fixed';
|
||
const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
|
||
let scroll = {
|
||
scrollLeft: 0,
|
||
scrollTop: 0
|
||
};
|
||
const offsets = createCoords(0);
|
||
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
|
||
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
|
||
scroll = getNodeScroll(offsetParent);
|
||
}
|
||
if (isOffsetParentAnElement) {
|
||
const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
|
||
offsets.x = offsetRect.x + offsetParent.clientLeft;
|
||
offsets.y = offsetRect.y + offsetParent.clientTop;
|
||
} else if (documentElement) {
|
||
offsets.x = getWindowScrollBarX(documentElement);
|
||
}
|
||
}
|
||
const x = rect.left + scroll.scrollLeft - offsets.x;
|
||
const y = rect.top + scroll.scrollTop - offsets.y;
|
||
return {
|
||
x,
|
||
y,
|
||
width: rect.width,
|
||
height: rect.height
|
||
};
|
||
}
|
||
|
||
function getTrueOffsetParent(element, polyfill) {
|
||
if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') {
|
||
return null;
|
||
}
|
||
if (polyfill) {
|
||
return polyfill(element);
|
||
}
|
||
return element.offsetParent;
|
||
}
|
||
|
||
// Gets the closest ancestor positioned element. Handles some edge cases,
|
||
// such as table ancestors and cross browser bugs.
|
||
function getOffsetParent(element, polyfill) {
|
||
const window = getWindow(element);
|
||
if (!isHTMLElement(element) || isTopLayer(element)) {
|
||
return window;
|
||
}
|
||
let offsetParent = getTrueOffsetParent(element, polyfill);
|
||
while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') {
|
||
offsetParent = getTrueOffsetParent(offsetParent, polyfill);
|
||
}
|
||
if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static' && !isContainingBlock(offsetParent))) {
|
||
return window;
|
||
}
|
||
return offsetParent || getContainingBlock(element) || window;
|
||
}
|
||
|
||
const getElementRects = async function (data) {
|
||
const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
|
||
const getDimensionsFn = this.getDimensions;
|
||
return {
|
||
reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
|
||
floating: {
|
||
x: 0,
|
||
y: 0,
|
||
...(await getDimensionsFn(data.floating))
|
||
}
|
||
};
|
||
};
|
||
|
||
function isRTL(element) {
|
||
return getComputedStyle$1(element).direction === 'rtl';
|
||
}
|
||
|
||
const platform = {
|
||
convertOffsetParentRelativeRectToViewportRelativeRect,
|
||
getDocumentElement,
|
||
getClippingRect,
|
||
getOffsetParent,
|
||
getElementRects,
|
||
getClientRects,
|
||
getDimensions,
|
||
getScale,
|
||
isElement,
|
||
isRTL
|
||
};
|
||
|
||
// https://samthor.au/2021/observing-dom/
|
||
function observeMove(element, onMove) {
|
||
let io = null;
|
||
let timeoutId;
|
||
const root = getDocumentElement(element);
|
||
function cleanup() {
|
||
var _io;
|
||
clearTimeout(timeoutId);
|
||
(_io = io) == null || _io.disconnect();
|
||
io = null;
|
||
}
|
||
function refresh(skip, threshold) {
|
||
if (skip === void 0) {
|
||
skip = false;
|
||
}
|
||
if (threshold === void 0) {
|
||
threshold = 1;
|
||
}
|
||
cleanup();
|
||
const {
|
||
left,
|
||
top,
|
||
width,
|
||
height
|
||
} = element.getBoundingClientRect();
|
||
if (!skip) {
|
||
onMove();
|
||
}
|
||
if (!width || !height) {
|
||
return;
|
||
}
|
||
const insetTop = floor(top);
|
||
const insetRight = floor(root.clientWidth - (left + width));
|
||
const insetBottom = floor(root.clientHeight - (top + height));
|
||
const insetLeft = floor(left);
|
||
const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
|
||
const options = {
|
||
rootMargin,
|
||
threshold: max(0, min(1, threshold)) || 1
|
||
};
|
||
let isFirstUpdate = true;
|
||
function handleObserve(entries) {
|
||
const ratio = entries[0].intersectionRatio;
|
||
if (ratio !== threshold) {
|
||
if (!isFirstUpdate) {
|
||
return refresh();
|
||
}
|
||
if (!ratio) {
|
||
timeoutId = setTimeout(() => {
|
||
refresh(false, 1e-7);
|
||
}, 100);
|
||
} else {
|
||
refresh(false, ratio);
|
||
}
|
||
}
|
||
isFirstUpdate = false;
|
||
}
|
||
|
||
// Older browsers don't support a `document` as the root and will throw an
|
||
// error.
|
||
try {
|
||
io = new IntersectionObserver(handleObserve, {
|
||
...options,
|
||
// Handle <iframe>s
|
||
root: root.ownerDocument
|
||
});
|
||
} catch (e) {
|
||
io = new IntersectionObserver(handleObserve, options);
|
||
}
|
||
io.observe(element);
|
||
}
|
||
refresh(true);
|
||
return cleanup;
|
||
}
|
||
|
||
/**
|
||
* Automatically updates the position of the floating element when necessary.
|
||
* Should only be called when the floating element is mounted on the DOM or
|
||
* visible on the screen.
|
||
* @returns cleanup function that should be invoked when the floating element is
|
||
* removed from the DOM or hidden from the screen.
|
||
* @see https://floating-ui.com/docs/autoUpdate
|
||
*/
|
||
function autoUpdate(reference, floating, update, options) {
|
||
if (options === void 0) {
|
||
options = {};
|
||
}
|
||
const {
|
||
ancestorScroll = true,
|
||
ancestorResize = true,
|
||
elementResize = typeof ResizeObserver === 'function',
|
||
layoutShift = typeof IntersectionObserver === 'function',
|
||
animationFrame = false
|
||
} = options;
|
||
const referenceEl = unwrapElement(reference);
|
||
const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : [];
|
||
ancestors.forEach(ancestor => {
|
||
ancestorScroll && ancestor.addEventListener('scroll', update, {
|
||
passive: true
|
||
});
|
||
ancestorResize && ancestor.addEventListener('resize', update);
|
||
});
|
||
const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
|
||
let reobserveFrame = -1;
|
||
let resizeObserver = null;
|
||
if (elementResize) {
|
||
resizeObserver = new ResizeObserver(_ref => {
|
||
let [firstEntry] = _ref;
|
||
if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
|
||
// Prevent update loops when using the `size` middleware.
|
||
// https://github.com/floating-ui/floating-ui/issues/1740
|
||
resizeObserver.unobserve(floating);
|
||
cancelAnimationFrame(reobserveFrame);
|
||
reobserveFrame = requestAnimationFrame(() => {
|
||
var _resizeObserver;
|
||
(_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
|
||
});
|
||
}
|
||
update();
|
||
});
|
||
if (referenceEl && !animationFrame) {
|
||
resizeObserver.observe(referenceEl);
|
||
}
|
||
resizeObserver.observe(floating);
|
||
}
|
||
let frameId;
|
||
let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
|
||
if (animationFrame) {
|
||
frameLoop();
|
||
}
|
||
function frameLoop() {
|
||
const nextRefRect = getBoundingClientRect(reference);
|
||
if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
|
||
update();
|
||
}
|
||
prevRefRect = nextRefRect;
|
||
frameId = requestAnimationFrame(frameLoop);
|
||
}
|
||
update();
|
||
return () => {
|
||
var _resizeObserver2;
|
||
ancestors.forEach(ancestor => {
|
||
ancestorScroll && ancestor.removeEventListener('scroll', update);
|
||
ancestorResize && ancestor.removeEventListener('resize', update);
|
||
});
|
||
cleanupIo == null || cleanupIo();
|
||
(_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
|
||
resizeObserver = null;
|
||
if (animationFrame) {
|
||
cancelAnimationFrame(frameId);
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Optimizes the visibility of the floating element by shifting it in order to
|
||
* keep it in view when it will overflow the clipping boundary.
|
||
* @see https://floating-ui.com/docs/shift
|
||
*/
|
||
const shift = shift$1;
|
||
|
||
/**
|
||
* Optimizes the visibility of the floating element by flipping the `placement`
|
||
* in order to keep it in view when the preferred placement(s) will overflow the
|
||
* clipping boundary. Alternative to `autoPlacement`.
|
||
* @see https://floating-ui.com/docs/flip
|
||
*/
|
||
const flip = flip$1;
|
||
|
||
/**
|
||
* Provides data to position an inner element of the floating element so that it
|
||
* appears centered to the reference element.
|
||
* @see https://floating-ui.com/docs/arrow
|
||
*/
|
||
const arrow = arrow$1;
|
||
|
||
/**
|
||
* Computes the `x` and `y` coordinates that will place the floating element
|
||
* next to a given reference element.
|
||
*/
|
||
const computePosition = (reference, floating, options) => {
|
||
// This caches the expensive `getClippingElementAncestors` function so that
|
||
// multiple lifecycle resets re-use the same result. It only lives for a
|
||
// single call. If other functions become expensive, we can add them as well.
|
||
const cache = new Map();
|
||
const mergedOptions = {
|
||
platform,
|
||
...options
|
||
};
|
||
const platformWithCache = {
|
||
...mergedOptions.platform,
|
||
_c: cache
|
||
};
|
||
return computePosition$1(reference, floating, {
|
||
...mergedOptions,
|
||
platform: platformWithCache
|
||
});
|
||
};
|
||
|
||
/* eslint-disable no-multi-assign */
|
||
|
||
var core;
|
||
var hasRequiredCore;
|
||
|
||
function requireCore () {
|
||
if (hasRequiredCore) return core;
|
||
hasRequiredCore = 1;
|
||
function deepFreeze(obj) {
|
||
if (obj instanceof Map) {
|
||
obj.clear =
|
||
obj.delete =
|
||
obj.set =
|
||
function () {
|
||
throw new Error('map is read-only');
|
||
};
|
||
} else if (obj instanceof Set) {
|
||
obj.add =
|
||
obj.clear =
|
||
obj.delete =
|
||
function () {
|
||
throw new Error('set is read-only');
|
||
};
|
||
}
|
||
|
||
// Freeze self
|
||
Object.freeze(obj);
|
||
|
||
Object.getOwnPropertyNames(obj).forEach((name) => {
|
||
const prop = obj[name];
|
||
const type = typeof prop;
|
||
|
||
// Freeze prop if it is an object or function and also not already frozen
|
||
if ((type === 'object' || type === 'function') && !Object.isFrozen(prop)) {
|
||
deepFreeze(prop);
|
||
}
|
||
});
|
||
|
||
return obj;
|
||
}
|
||
|
||
/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */
|
||
/** @typedef {import('highlight.js').CompiledMode} CompiledMode */
|
||
/** @implements CallbackResponse */
|
||
|
||
class Response {
|
||
/**
|
||
* @param {CompiledMode} mode
|
||
*/
|
||
constructor(mode) {
|
||
// eslint-disable-next-line no-undefined
|
||
if (mode.data === undefined) mode.data = {};
|
||
|
||
this.data = mode.data;
|
||
this.isMatchIgnored = false;
|
||
}
|
||
|
||
ignoreMatch() {
|
||
this.isMatchIgnored = true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param {string} value
|
||
* @returns {string}
|
||
*/
|
||
function escapeHTML(value) {
|
||
return value
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"')
|
||
.replace(/'/g, ''');
|
||
}
|
||
|
||
/**
|
||
* performs a shallow merge of multiple objects into one
|
||
*
|
||
* @template T
|
||
* @param {T} original
|
||
* @param {Record<string,any>[]} objects
|
||
* @returns {T} a single new object
|
||
*/
|
||
function inherit$1(original, ...objects) {
|
||
/** @type Record<string,any> */
|
||
const result = Object.create(null);
|
||
|
||
for (const key in original) {
|
||
result[key] = original[key];
|
||
}
|
||
objects.forEach(function(obj) {
|
||
for (const key in obj) {
|
||
result[key] = obj[key];
|
||
}
|
||
});
|
||
return /** @type {T} */ (result);
|
||
}
|
||
|
||
/**
|
||
* @typedef {object} Renderer
|
||
* @property {(text: string) => void} addText
|
||
* @property {(node: Node) => void} openNode
|
||
* @property {(node: Node) => void} closeNode
|
||
* @property {() => string} value
|
||
*/
|
||
|
||
/** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */
|
||
/** @typedef {{walk: (r: Renderer) => void}} Tree */
|
||
/** */
|
||
|
||
const SPAN_CLOSE = '</span>';
|
||
|
||
/**
|
||
* Determines if a node needs to be wrapped in <span>
|
||
*
|
||
* @param {Node} node */
|
||
const emitsWrappingTags = (node) => {
|
||
// rarely we can have a sublanguage where language is undefined
|
||
// TODO: track down why
|
||
return !!node.scope;
|
||
};
|
||
|
||
/**
|
||
*
|
||
* @param {string} name
|
||
* @param {{prefix:string}} options
|
||
*/
|
||
const scopeToCSSClass = (name, { prefix }) => {
|
||
// sub-language
|
||
if (name.startsWith("language:")) {
|
||
return name.replace("language:", "language-");
|
||
}
|
||
// tiered scope: comment.line
|
||
if (name.includes(".")) {
|
||
const pieces = name.split(".");
|
||
return [
|
||
`${prefix}${pieces.shift()}`,
|
||
...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`))
|
||
].join(" ");
|
||
}
|
||
// simple scope
|
||
return `${prefix}${name}`;
|
||
};
|
||
|
||
/** @type {Renderer} */
|
||
class HTMLRenderer {
|
||
/**
|
||
* Creates a new HTMLRenderer
|
||
*
|
||
* @param {Tree} parseTree - the parse tree (must support `walk` API)
|
||
* @param {{classPrefix: string}} options
|
||
*/
|
||
constructor(parseTree, options) {
|
||
this.buffer = "";
|
||
this.classPrefix = options.classPrefix;
|
||
parseTree.walk(this);
|
||
}
|
||
|
||
/**
|
||
* Adds texts to the output stream
|
||
*
|
||
* @param {string} text */
|
||
addText(text) {
|
||
this.buffer += escapeHTML(text);
|
||
}
|
||
|
||
/**
|
||
* Adds a node open to the output stream (if needed)
|
||
*
|
||
* @param {Node} node */
|
||
openNode(node) {
|
||
if (!emitsWrappingTags(node)) return;
|
||
|
||
const className = scopeToCSSClass(node.scope,
|
||
{ prefix: this.classPrefix });
|
||
this.span(className);
|
||
}
|
||
|
||
/**
|
||
* Adds a node close to the output stream (if needed)
|
||
*
|
||
* @param {Node} node */
|
||
closeNode(node) {
|
||
if (!emitsWrappingTags(node)) return;
|
||
|
||
this.buffer += SPAN_CLOSE;
|
||
}
|
||
|
||
/**
|
||
* returns the accumulated buffer
|
||
*/
|
||
value() {
|
||
return this.buffer;
|
||
}
|
||
|
||
// helpers
|
||
|
||
/**
|
||
* Builds a span element
|
||
*
|
||
* @param {string} className */
|
||
span(className) {
|
||
this.buffer += `<span class="${className}">`;
|
||
}
|
||
}
|
||
|
||
/** @typedef {{scope?: string, language?: string, children: Node[]} | string} Node */
|
||
/** @typedef {{scope?: string, language?: string, children: Node[]} } DataNode */
|
||
/** @typedef {import('highlight.js').Emitter} Emitter */
|
||
/** */
|
||
|
||
/** @returns {DataNode} */
|
||
const newNode = (opts = {}) => {
|
||
/** @type DataNode */
|
||
const result = { children: [] };
|
||
Object.assign(result, opts);
|
||
return result;
|
||
};
|
||
|
||
class TokenTree {
|
||
constructor() {
|
||
/** @type DataNode */
|
||
this.rootNode = newNode();
|
||
this.stack = [this.rootNode];
|
||
}
|
||
|
||
get top() {
|
||
return this.stack[this.stack.length - 1];
|
||
}
|
||
|
||
get root() { return this.rootNode; }
|
||
|
||
/** @param {Node} node */
|
||
add(node) {
|
||
this.top.children.push(node);
|
||
}
|
||
|
||
/** @param {string} scope */
|
||
openNode(scope) {
|
||
/** @type Node */
|
||
const node = newNode({ scope });
|
||
this.add(node);
|
||
this.stack.push(node);
|
||
}
|
||
|
||
closeNode() {
|
||
if (this.stack.length > 1) {
|
||
return this.stack.pop();
|
||
}
|
||
// eslint-disable-next-line no-undefined
|
||
return undefined;
|
||
}
|
||
|
||
closeAllNodes() {
|
||
while (this.closeNode());
|
||
}
|
||
|
||
toJSON() {
|
||
return JSON.stringify(this.rootNode, null, 4);
|
||
}
|
||
|
||
/**
|
||
* @typedef { import("./html_renderer").Renderer } Renderer
|
||
* @param {Renderer} builder
|
||
*/
|
||
walk(builder) {
|
||
// this does not
|
||
return this.constructor._walk(builder, this.rootNode);
|
||
// this works
|
||
// return TokenTree._walk(builder, this.rootNode);
|
||
}
|
||
|
||
/**
|
||
* @param {Renderer} builder
|
||
* @param {Node} node
|
||
*/
|
||
static _walk(builder, node) {
|
||
if (typeof node === "string") {
|
||
builder.addText(node);
|
||
} else if (node.children) {
|
||
builder.openNode(node);
|
||
node.children.forEach((child) => this._walk(builder, child));
|
||
builder.closeNode(node);
|
||
}
|
||
return builder;
|
||
}
|
||
|
||
/**
|
||
* @param {Node} node
|
||
*/
|
||
static _collapse(node) {
|
||
if (typeof node === "string") return;
|
||
if (!node.children) return;
|
||
|
||
if (node.children.every(el => typeof el === "string")) {
|
||
// node.text = node.children.join("");
|
||
// delete node.children;
|
||
node.children = [node.children.join("")];
|
||
} else {
|
||
node.children.forEach((child) => {
|
||
TokenTree._collapse(child);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
Currently this is all private API, but this is the minimal API necessary
|
||
that an Emitter must implement to fully support the parser.
|
||
|
||
Minimal interface:
|
||
|
||
- addText(text)
|
||
- __addSublanguage(emitter, subLanguageName)
|
||
- startScope(scope)
|
||
- endScope()
|
||
- finalize()
|
||
- toHTML()
|
||
|
||
*/
|
||
|
||
/**
|
||
* @implements {Emitter}
|
||
*/
|
||
class TokenTreeEmitter extends TokenTree {
|
||
/**
|
||
* @param {*} options
|
||
*/
|
||
constructor(options) {
|
||
super();
|
||
this.options = options;
|
||
}
|
||
|
||
/**
|
||
* @param {string} text
|
||
*/
|
||
addText(text) {
|
||
if (text === "") { return; }
|
||
|
||
this.add(text);
|
||
}
|
||
|
||
/** @param {string} scope */
|
||
startScope(scope) {
|
||
this.openNode(scope);
|
||
}
|
||
|
||
endScope() {
|
||
this.closeNode();
|
||
}
|
||
|
||
/**
|
||
* @param {Emitter & {root: DataNode}} emitter
|
||
* @param {string} name
|
||
*/
|
||
__addSublanguage(emitter, name) {
|
||
/** @type DataNode */
|
||
const node = emitter.root;
|
||
if (name) node.scope = `language:${name}`;
|
||
|
||
this.add(node);
|
||
}
|
||
|
||
toHTML() {
|
||
const renderer = new HTMLRenderer(this, this.options);
|
||
return renderer.value();
|
||
}
|
||
|
||
finalize() {
|
||
this.closeAllNodes();
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param {string} value
|
||
* @returns {RegExp}
|
||
* */
|
||
|
||
/**
|
||
* @param {RegExp | string } re
|
||
* @returns {string}
|
||
*/
|
||
function source(re) {
|
||
if (!re) return null;
|
||
if (typeof re === "string") return re;
|
||
|
||
return re.source;
|
||
}
|
||
|
||
/**
|
||
* @param {RegExp | string } re
|
||
* @returns {string}
|
||
*/
|
||
function lookahead(re) {
|
||
return concat('(?=', re, ')');
|
||
}
|
||
|
||
/**
|
||
* @param {RegExp | string } re
|
||
* @returns {string}
|
||
*/
|
||
function anyNumberOfTimes(re) {
|
||
return concat('(?:', re, ')*');
|
||
}
|
||
|
||
/**
|
||
* @param {RegExp | string } re
|
||
* @returns {string}
|
||
*/
|
||
function optional(re) {
|
||
return concat('(?:', re, ')?');
|
||
}
|
||
|
||
/**
|
||
* @param {...(RegExp | string) } args
|
||
* @returns {string}
|
||
*/
|
||
function concat(...args) {
|
||
const joined = args.map((x) => source(x)).join("");
|
||
return joined;
|
||
}
|
||
|
||
/**
|
||
* @param { Array<string | RegExp | Object> } args
|
||
* @returns {object}
|
||
*/
|
||
function stripOptionsFromArgs(args) {
|
||
const opts = args[args.length - 1];
|
||
|
||
if (typeof opts === 'object' && opts.constructor === Object) {
|
||
args.splice(args.length - 1, 1);
|
||
return opts;
|
||
} else {
|
||
return {};
|
||
}
|
||
}
|
||
|
||
/** @typedef { {capture?: boolean} } RegexEitherOptions */
|
||
|
||
/**
|
||
* Any of the passed expresssions may match
|
||
*
|
||
* Creates a huge this | this | that | that match
|
||
* @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
|
||
* @returns {string}
|
||
*/
|
||
function either(...args) {
|
||
/** @type { object & {capture?: boolean} } */
|
||
const opts = stripOptionsFromArgs(args);
|
||
const joined = '('
|
||
+ (opts.capture ? "" : "?:")
|
||
+ args.map((x) => source(x)).join("|") + ")";
|
||
return joined;
|
||
}
|
||
|
||
/**
|
||
* @param {RegExp | string} re
|
||
* @returns {number}
|
||
*/
|
||
function countMatchGroups(re) {
|
||
return (new RegExp(re.toString() + '|')).exec('').length - 1;
|
||
}
|
||
|
||
/**
|
||
* Does lexeme start with a regular expression match at the beginning
|
||
* @param {RegExp} re
|
||
* @param {string} lexeme
|
||
*/
|
||
function startsWith(re, lexeme) {
|
||
const match = re && re.exec(lexeme);
|
||
return match && match.index === 0;
|
||
}
|
||
|
||
// BACKREF_RE matches an open parenthesis or backreference. To avoid
|
||
// an incorrect parse, it additionally matches the following:
|
||
// - [...] elements, where the meaning of parentheses and escapes change
|
||
// - other escape sequences, so we do not misparse escape sequences as
|
||
// interesting elements
|
||
// - non-matching or lookahead parentheses, which do not capture. These
|
||
// follow the '(' with a '?'.
|
||
const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
||
|
||
// **INTERNAL** Not intended for outside usage
|
||
// join logically computes regexps.join(separator), but fixes the
|
||
// backreferences so they continue to match.
|
||
// it also places each individual regular expression into it's own
|
||
// match group, keeping track of the sequencing of those match groups
|
||
// is currently an exercise for the caller. :-)
|
||
/**
|
||
* @param {(string | RegExp)[]} regexps
|
||
* @param {{joinWith: string}} opts
|
||
* @returns {string}
|
||
*/
|
||
function _rewriteBackreferences(regexps, { joinWith }) {
|
||
let numCaptures = 0;
|
||
|
||
return regexps.map((regex) => {
|
||
numCaptures += 1;
|
||
const offset = numCaptures;
|
||
let re = source(regex);
|
||
let out = '';
|
||
|
||
while (re.length > 0) {
|
||
const match = BACKREF_RE.exec(re);
|
||
if (!match) {
|
||
out += re;
|
||
break;
|
||
}
|
||
out += re.substring(0, match.index);
|
||
re = re.substring(match.index + match[0].length);
|
||
if (match[0][0] === '\\' && match[1]) {
|
||
// Adjust the backreference.
|
||
out += '\\' + String(Number(match[1]) + offset);
|
||
} else {
|
||
out += match[0];
|
||
if (match[0] === '(') {
|
||
numCaptures++;
|
||
}
|
||
}
|
||
}
|
||
return out;
|
||
}).map(re => `(${re})`).join(joinWith);
|
||
}
|
||
|
||
/** @typedef {import('highlight.js').Mode} Mode */
|
||
/** @typedef {import('highlight.js').ModeCallback} ModeCallback */
|
||
|
||
// Common regexps
|
||
const MATCH_NOTHING_RE = /\b\B/;
|
||
const IDENT_RE = '[a-zA-Z]\\w*';
|
||
const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*';
|
||
const NUMBER_RE = '\\b\\d+(\\.\\d+)?';
|
||
const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
|
||
const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
|
||
const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
|
||
|
||
/**
|
||
* @param { Partial<Mode> & {binary?: string | RegExp} } opts
|
||
*/
|
||
const SHEBANG = (opts = {}) => {
|
||
const beginShebang = /^#![ ]*\//;
|
||
if (opts.binary) {
|
||
opts.begin = concat(
|
||
beginShebang,
|
||
/.*\b/,
|
||
opts.binary,
|
||
/\b.*/);
|
||
}
|
||
return inherit$1({
|
||
scope: 'meta',
|
||
begin: beginShebang,
|
||
end: /$/,
|
||
relevance: 0,
|
||
/** @type {ModeCallback} */
|
||
"on:begin": (m, resp) => {
|
||
if (m.index !== 0) resp.ignoreMatch();
|
||
}
|
||
}, opts);
|
||
};
|
||
|
||
// Common modes
|
||
const BACKSLASH_ESCAPE = {
|
||
begin: '\\\\[\\s\\S]', relevance: 0
|
||
};
|
||
const APOS_STRING_MODE = {
|
||
scope: 'string',
|
||
begin: '\'',
|
||
end: '\'',
|
||
illegal: '\\n',
|
||
contains: [BACKSLASH_ESCAPE]
|
||
};
|
||
const QUOTE_STRING_MODE = {
|
||
scope: 'string',
|
||
begin: '"',
|
||
end: '"',
|
||
illegal: '\\n',
|
||
contains: [BACKSLASH_ESCAPE]
|
||
};
|
||
const PHRASAL_WORDS_MODE = {
|
||
begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/
|
||
};
|
||
/**
|
||
* Creates a comment mode
|
||
*
|
||
* @param {string | RegExp} begin
|
||
* @param {string | RegExp} end
|
||
* @param {Mode | {}} [modeOptions]
|
||
* @returns {Partial<Mode>}
|
||
*/
|
||
const COMMENT = function(begin, end, modeOptions = {}) {
|
||
const mode = inherit$1(
|
||
{
|
||
scope: 'comment',
|
||
begin,
|
||
end,
|
||
contains: []
|
||
},
|
||
modeOptions
|
||
);
|
||
mode.contains.push({
|
||
scope: 'doctag',
|
||
// hack to avoid the space from being included. the space is necessary to
|
||
// match here to prevent the plain text rule below from gobbling up doctags
|
||
begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)',
|
||
end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,
|
||
excludeBegin: true,
|
||
relevance: 0
|
||
});
|
||
const ENGLISH_WORD = either(
|
||
// list of common 1 and 2 letter words in English
|
||
"I",
|
||
"a",
|
||
"is",
|
||
"so",
|
||
"us",
|
||
"to",
|
||
"at",
|
||
"if",
|
||
"in",
|
||
"it",
|
||
"on",
|
||
// note: this is not an exhaustive list of contractions, just popular ones
|
||
/[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc
|
||
/[A-Za-z]+[-][a-z]+/, // `no-way`, etc.
|
||
/[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences
|
||
);
|
||
// looking like plain text, more likely to be a comment
|
||
mode.contains.push(
|
||
{
|
||
// TODO: how to include ", (, ) without breaking grammars that use these for
|
||
// comment delimiters?
|
||
// begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/
|
||
// ---
|
||
|
||
// this tries to find sequences of 3 english words in a row (without any
|
||
// "programming" type syntax) this gives us a strong signal that we've
|
||
// TRULY found a comment - vs perhaps scanning with the wrong language.
|
||
// It's possible to find something that LOOKS like the start of the
|
||
// comment - but then if there is no readable text - good chance it is a
|
||
// false match and not a comment.
|
||
//
|
||
// for a visual example please see:
|
||
// https://github.com/highlightjs/highlight.js/issues/2827
|
||
|
||
begin: concat(
|
||
/[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */
|
||
'(',
|
||
ENGLISH_WORD,
|
||
/[.]?[:]?([.][ ]|[ ])/,
|
||
'){3}') // look for 3 words in a row
|
||
}
|
||
);
|
||
return mode;
|
||
};
|
||
const C_LINE_COMMENT_MODE = COMMENT('//', '$');
|
||
const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/');
|
||
const HASH_COMMENT_MODE = COMMENT('#', '$');
|
||
const NUMBER_MODE = {
|
||
scope: 'number',
|
||
begin: NUMBER_RE,
|
||
relevance: 0
|
||
};
|
||
const C_NUMBER_MODE = {
|
||
scope: 'number',
|
||
begin: C_NUMBER_RE,
|
||
relevance: 0
|
||
};
|
||
const BINARY_NUMBER_MODE = {
|
||
scope: 'number',
|
||
begin: BINARY_NUMBER_RE,
|
||
relevance: 0
|
||
};
|
||
const REGEXP_MODE = {
|
||
scope: "regexp",
|
||
begin: /\/(?=[^/\n]*\/)/,
|
||
end: /\/[gimuy]*/,
|
||
contains: [
|
||
BACKSLASH_ESCAPE,
|
||
{
|
||
begin: /\[/,
|
||
end: /\]/,
|
||
relevance: 0,
|
||
contains: [BACKSLASH_ESCAPE]
|
||
}
|
||
]
|
||
};
|
||
const TITLE_MODE = {
|
||
scope: 'title',
|
||
begin: IDENT_RE,
|
||
relevance: 0
|
||
};
|
||
const UNDERSCORE_TITLE_MODE = {
|
||
scope: 'title',
|
||
begin: UNDERSCORE_IDENT_RE,
|
||
relevance: 0
|
||
};
|
||
const METHOD_GUARD = {
|
||
// excludes method names from keyword processing
|
||
begin: '\\.\\s*' + UNDERSCORE_IDENT_RE,
|
||
relevance: 0
|
||
};
|
||
|
||
/**
|
||
* Adds end same as begin mechanics to a mode
|
||
*
|
||
* Your mode must include at least a single () match group as that first match
|
||
* group is what is used for comparison
|
||
* @param {Partial<Mode>} mode
|
||
*/
|
||
const END_SAME_AS_BEGIN = function(mode) {
|
||
return Object.assign(mode,
|
||
{
|
||
/** @type {ModeCallback} */
|
||
'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; },
|
||
/** @type {ModeCallback} */
|
||
'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); }
|
||
});
|
||
};
|
||
|
||
var MODES = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
APOS_STRING_MODE: APOS_STRING_MODE,
|
||
BACKSLASH_ESCAPE: BACKSLASH_ESCAPE,
|
||
BINARY_NUMBER_MODE: BINARY_NUMBER_MODE,
|
||
BINARY_NUMBER_RE: BINARY_NUMBER_RE,
|
||
COMMENT: COMMENT,
|
||
C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE,
|
||
C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE,
|
||
C_NUMBER_MODE: C_NUMBER_MODE,
|
||
C_NUMBER_RE: C_NUMBER_RE,
|
||
END_SAME_AS_BEGIN: END_SAME_AS_BEGIN,
|
||
HASH_COMMENT_MODE: HASH_COMMENT_MODE,
|
||
IDENT_RE: IDENT_RE,
|
||
MATCH_NOTHING_RE: MATCH_NOTHING_RE,
|
||
METHOD_GUARD: METHOD_GUARD,
|
||
NUMBER_MODE: NUMBER_MODE,
|
||
NUMBER_RE: NUMBER_RE,
|
||
PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE,
|
||
QUOTE_STRING_MODE: QUOTE_STRING_MODE,
|
||
REGEXP_MODE: REGEXP_MODE,
|
||
RE_STARTERS_RE: RE_STARTERS_RE,
|
||
SHEBANG: SHEBANG,
|
||
TITLE_MODE: TITLE_MODE,
|
||
UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE,
|
||
UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE
|
||
});
|
||
|
||
/**
|
||
@typedef {import('highlight.js').CallbackResponse} CallbackResponse
|
||
@typedef {import('highlight.js').CompilerExt} CompilerExt
|
||
*/
|
||
|
||
// Grammar extensions / plugins
|
||
// See: https://github.com/highlightjs/highlight.js/issues/2833
|
||
|
||
// Grammar extensions allow "syntactic sugar" to be added to the grammar modes
|
||
// without requiring any underlying changes to the compiler internals.
|
||
|
||
// `compileMatch` being the perfect small example of now allowing a grammar
|
||
// author to write `match` when they desire to match a single expression rather
|
||
// than being forced to use `begin`. The extension then just moves `match` into
|
||
// `begin` when it runs. Ie, no features have been added, but we've just made
|
||
// the experience of writing (and reading grammars) a little bit nicer.
|
||
|
||
// ------
|
||
|
||
// TODO: We need negative look-behind support to do this properly
|
||
/**
|
||
* Skip a match if it has a preceding dot
|
||
*
|
||
* This is used for `beginKeywords` to prevent matching expressions such as
|
||
* `bob.keyword.do()`. The mode compiler automatically wires this up as a
|
||
* special _internal_ 'on:begin' callback for modes with `beginKeywords`
|
||
* @param {RegExpMatchArray} match
|
||
* @param {CallbackResponse} response
|
||
*/
|
||
function skipIfHasPrecedingDot(match, response) {
|
||
const before = match.input[match.index - 1];
|
||
if (before === ".") {
|
||
response.ignoreMatch();
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @type {CompilerExt}
|
||
*/
|
||
function scopeClassName(mode, _parent) {
|
||
// eslint-disable-next-line no-undefined
|
||
if (mode.className !== undefined) {
|
||
mode.scope = mode.className;
|
||
delete mode.className;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* `beginKeywords` syntactic sugar
|
||
* @type {CompilerExt}
|
||
*/
|
||
function beginKeywords(mode, parent) {
|
||
if (!parent) return;
|
||
if (!mode.beginKeywords) return;
|
||
|
||
// for languages with keywords that include non-word characters checking for
|
||
// a word boundary is not sufficient, so instead we check for a word boundary
|
||
// or whitespace - this does no harm in any case since our keyword engine
|
||
// doesn't allow spaces in keywords anyways and we still check for the boundary
|
||
// first
|
||
mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)';
|
||
mode.__beforeBegin = skipIfHasPrecedingDot;
|
||
mode.keywords = mode.keywords || mode.beginKeywords;
|
||
delete mode.beginKeywords;
|
||
|
||
// prevents double relevance, the keywords themselves provide
|
||
// relevance, the mode doesn't need to double it
|
||
// eslint-disable-next-line no-undefined
|
||
if (mode.relevance === undefined) mode.relevance = 0;
|
||
}
|
||
|
||
/**
|
||
* Allow `illegal` to contain an array of illegal values
|
||
* @type {CompilerExt}
|
||
*/
|
||
function compileIllegal(mode, _parent) {
|
||
if (!Array.isArray(mode.illegal)) return;
|
||
|
||
mode.illegal = either(...mode.illegal);
|
||
}
|
||
|
||
/**
|
||
* `match` to match a single expression for readability
|
||
* @type {CompilerExt}
|
||
*/
|
||
function compileMatch(mode, _parent) {
|
||
if (!mode.match) return;
|
||
if (mode.begin || mode.end) throw new Error("begin & end are not supported with match");
|
||
|
||
mode.begin = mode.match;
|
||
delete mode.match;
|
||
}
|
||
|
||
/**
|
||
* provides the default 1 relevance to all modes
|
||
* @type {CompilerExt}
|
||
*/
|
||
function compileRelevance(mode, _parent) {
|
||
// eslint-disable-next-line no-undefined
|
||
if (mode.relevance === undefined) mode.relevance = 1;
|
||
}
|
||
|
||
// allow beforeMatch to act as a "qualifier" for the match
|
||
// the full match begin must be [beforeMatch][begin]
|
||
const beforeMatchExt = (mode, parent) => {
|
||
if (!mode.beforeMatch) return;
|
||
// starts conflicts with endsParent which we need to make sure the child
|
||
// rule is not matched multiple times
|
||
if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
|
||
|
||
const originalMode = Object.assign({}, mode);
|
||
Object.keys(mode).forEach((key) => { delete mode[key]; });
|
||
|
||
mode.keywords = originalMode.keywords;
|
||
mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));
|
||
mode.starts = {
|
||
relevance: 0,
|
||
contains: [
|
||
Object.assign(originalMode, { endsParent: true })
|
||
]
|
||
};
|
||
mode.relevance = 0;
|
||
|
||
delete originalMode.beforeMatch;
|
||
};
|
||
|
||
// keywords that should have no default relevance value
|
||
const COMMON_KEYWORDS = [
|
||
'of',
|
||
'and',
|
||
'for',
|
||
'in',
|
||
'not',
|
||
'or',
|
||
'if',
|
||
'then',
|
||
'parent', // common variable name
|
||
'list', // common variable name
|
||
'value' // common variable name
|
||
];
|
||
|
||
const DEFAULT_KEYWORD_SCOPE = "keyword";
|
||
|
||
/**
|
||
* Given raw keywords from a language definition, compile them.
|
||
*
|
||
* @param {string | Record<string,string|string[]> | Array<string>} rawKeywords
|
||
* @param {boolean} caseInsensitive
|
||
*/
|
||
function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) {
|
||
/** @type {import("highlight.js/private").KeywordDict} */
|
||
const compiledKeywords = Object.create(null);
|
||
|
||
// input can be a string of keywords, an array of keywords, or a object with
|
||
// named keys representing scopeName (which can then point to a string or array)
|
||
if (typeof rawKeywords === 'string') {
|
||
compileList(scopeName, rawKeywords.split(" "));
|
||
} else if (Array.isArray(rawKeywords)) {
|
||
compileList(scopeName, rawKeywords);
|
||
} else {
|
||
Object.keys(rawKeywords).forEach(function(scopeName) {
|
||
// collapse all our objects back into the parent object
|
||
Object.assign(
|
||
compiledKeywords,
|
||
compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName)
|
||
);
|
||
});
|
||
}
|
||
return compiledKeywords;
|
||
|
||
// ---
|
||
|
||
/**
|
||
* Compiles an individual list of keywords
|
||
*
|
||
* Ex: "for if when while|5"
|
||
*
|
||
* @param {string} scopeName
|
||
* @param {Array<string>} keywordList
|
||
*/
|
||
function compileList(scopeName, keywordList) {
|
||
if (caseInsensitive) {
|
||
keywordList = keywordList.map(x => x.toLowerCase());
|
||
}
|
||
keywordList.forEach(function(keyword) {
|
||
const pair = keyword.split('|');
|
||
compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])];
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Returns the proper score for a given keyword
|
||
*
|
||
* Also takes into account comment keywords, which will be scored 0 UNLESS
|
||
* another score has been manually assigned.
|
||
* @param {string} keyword
|
||
* @param {string} [providedScore]
|
||
*/
|
||
function scoreForKeyword(keyword, providedScore) {
|
||
// manual scores always win over common keywords
|
||
// so you can force a score of 1 if you really insist
|
||
if (providedScore) {
|
||
return Number(providedScore);
|
||
}
|
||
|
||
return commonKeyword(keyword) ? 0 : 1;
|
||
}
|
||
|
||
/**
|
||
* Determines if a given keyword is common or not
|
||
*
|
||
* @param {string} keyword */
|
||
function commonKeyword(keyword) {
|
||
return COMMON_KEYWORDS.includes(keyword.toLowerCase());
|
||
}
|
||
|
||
/*
|
||
|
||
For the reasoning behind this please see:
|
||
https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419
|
||
|
||
*/
|
||
|
||
/**
|
||
* @type {Record<string, boolean>}
|
||
*/
|
||
const seenDeprecations = {};
|
||
|
||
/**
|
||
* @param {string} message
|
||
*/
|
||
const error = (message) => {
|
||
console.error(message);
|
||
};
|
||
|
||
/**
|
||
* @param {string} message
|
||
* @param {any} args
|
||
*/
|
||
const warn = (message, ...args) => {
|
||
console.log(`WARN: ${message}`, ...args);
|
||
};
|
||
|
||
/**
|
||
* @param {string} version
|
||
* @param {string} message
|
||
*/
|
||
const deprecated = (version, message) => {
|
||
if (seenDeprecations[`${version}/${message}`]) return;
|
||
|
||
console.log(`Deprecated as of ${version}. ${message}`);
|
||
seenDeprecations[`${version}/${message}`] = true;
|
||
};
|
||
|
||
/* eslint-disable no-throw-literal */
|
||
|
||
/**
|
||
@typedef {import('highlight.js').CompiledMode} CompiledMode
|
||
*/
|
||
|
||
const MultiClassError = new Error();
|
||
|
||
/**
|
||
* Renumbers labeled scope names to account for additional inner match
|
||
* groups that otherwise would break everything.
|
||
*
|
||
* Lets say we 3 match scopes:
|
||
*
|
||
* { 1 => ..., 2 => ..., 3 => ... }
|
||
*
|
||
* So what we need is a clean match like this:
|
||
*
|
||
* (a)(b)(c) => [ "a", "b", "c" ]
|
||
*
|
||
* But this falls apart with inner match groups:
|
||
*
|
||
* (a)(((b)))(c) => ["a", "b", "b", "b", "c" ]
|
||
*
|
||
* Our scopes are now "out of alignment" and we're repeating `b` 3 times.
|
||
* What needs to happen is the numbers are remapped:
|
||
*
|
||
* { 1 => ..., 2 => ..., 5 => ... }
|
||
*
|
||
* We also need to know that the ONLY groups that should be output
|
||
* are 1, 2, and 5. This function handles this behavior.
|
||
*
|
||
* @param {CompiledMode} mode
|
||
* @param {Array<RegExp | string>} regexes
|
||
* @param {{key: "beginScope"|"endScope"}} opts
|
||
*/
|
||
function remapScopeNames(mode, regexes, { key }) {
|
||
let offset = 0;
|
||
const scopeNames = mode[key];
|
||
/** @type Record<number,boolean> */
|
||
const emit = {};
|
||
/** @type Record<number,string> */
|
||
const positions = {};
|
||
|
||
for (let i = 1; i <= regexes.length; i++) {
|
||
positions[i + offset] = scopeNames[i];
|
||
emit[i + offset] = true;
|
||
offset += countMatchGroups(regexes[i - 1]);
|
||
}
|
||
// we use _emit to keep track of which match groups are "top-level" to avoid double
|
||
// output from inside match groups
|
||
mode[key] = positions;
|
||
mode[key]._emit = emit;
|
||
mode[key]._multi = true;
|
||
}
|
||
|
||
/**
|
||
* @param {CompiledMode} mode
|
||
*/
|
||
function beginMultiClass(mode) {
|
||
if (!Array.isArray(mode.begin)) return;
|
||
|
||
if (mode.skip || mode.excludeBegin || mode.returnBegin) {
|
||
error("skip, excludeBegin, returnBegin not compatible with beginScope: {}");
|
||
throw MultiClassError;
|
||
}
|
||
|
||
if (typeof mode.beginScope !== "object" || mode.beginScope === null) {
|
||
error("beginScope must be object");
|
||
throw MultiClassError;
|
||
}
|
||
|
||
remapScopeNames(mode, mode.begin, { key: "beginScope" });
|
||
mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" });
|
||
}
|
||
|
||
/**
|
||
* @param {CompiledMode} mode
|
||
*/
|
||
function endMultiClass(mode) {
|
||
if (!Array.isArray(mode.end)) return;
|
||
|
||
if (mode.skip || mode.excludeEnd || mode.returnEnd) {
|
||
error("skip, excludeEnd, returnEnd not compatible with endScope: {}");
|
||
throw MultiClassError;
|
||
}
|
||
|
||
if (typeof mode.endScope !== "object" || mode.endScope === null) {
|
||
error("endScope must be object");
|
||
throw MultiClassError;
|
||
}
|
||
|
||
remapScopeNames(mode, mode.end, { key: "endScope" });
|
||
mode.end = _rewriteBackreferences(mode.end, { joinWith: "" });
|
||
}
|
||
|
||
/**
|
||
* this exists only to allow `scope: {}` to be used beside `match:`
|
||
* Otherwise `beginScope` would necessary and that would look weird
|
||
|
||
{
|
||
match: [ /def/, /\w+/ ]
|
||
scope: { 1: "keyword" , 2: "title" }
|
||
}
|
||
|
||
* @param {CompiledMode} mode
|
||
*/
|
||
function scopeSugar(mode) {
|
||
if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) {
|
||
mode.beginScope = mode.scope;
|
||
delete mode.scope;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param {CompiledMode} mode
|
||
*/
|
||
function MultiClass(mode) {
|
||
scopeSugar(mode);
|
||
|
||
if (typeof mode.beginScope === "string") {
|
||
mode.beginScope = { _wrap: mode.beginScope };
|
||
}
|
||
if (typeof mode.endScope === "string") {
|
||
mode.endScope = { _wrap: mode.endScope };
|
||
}
|
||
|
||
beginMultiClass(mode);
|
||
endMultiClass(mode);
|
||
}
|
||
|
||
/**
|
||
@typedef {import('highlight.js').Mode} Mode
|
||
@typedef {import('highlight.js').CompiledMode} CompiledMode
|
||
@typedef {import('highlight.js').Language} Language
|
||
@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
|
||
@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage
|
||
*/
|
||
|
||
// compilation
|
||
|
||
/**
|
||
* Compiles a language definition result
|
||
*
|
||
* Given the raw result of a language definition (Language), compiles this so
|
||
* that it is ready for highlighting code.
|
||
* @param {Language} language
|
||
* @returns {CompiledLanguage}
|
||
*/
|
||
function compileLanguage(language) {
|
||
/**
|
||
* Builds a regex with the case sensitivity of the current language
|
||
*
|
||
* @param {RegExp | string} value
|
||
* @param {boolean} [global]
|
||
*/
|
||
function langRe(value, global) {
|
||
return new RegExp(
|
||
source(value),
|
||
'm'
|
||
+ (language.case_insensitive ? 'i' : '')
|
||
+ (language.unicodeRegex ? 'u' : '')
|
||
+ (global ? 'g' : '')
|
||
);
|
||
}
|
||
|
||
/**
|
||
Stores multiple regular expressions and allows you to quickly search for
|
||
them all in a string simultaneously - returning the first match. It does
|
||
this by creating a huge (a|b|c) regex - each individual item wrapped with ()
|
||
and joined by `|` - using match groups to track position. When a match is
|
||
found checking which position in the array has content allows us to figure
|
||
out which of the original regexes / match groups triggered the match.
|
||
|
||
The match object itself (the result of `Regex.exec`) is returned but also
|
||
enhanced by merging in any meta-data that was registered with the regex.
|
||
This is how we keep track of which mode matched, and what type of rule
|
||
(`illegal`, `begin`, end, etc).
|
||
*/
|
||
class MultiRegex {
|
||
constructor() {
|
||
this.matchIndexes = {};
|
||
// @ts-ignore
|
||
this.regexes = [];
|
||
this.matchAt = 1;
|
||
this.position = 0;
|
||
}
|
||
|
||
// @ts-ignore
|
||
addRule(re, opts) {
|
||
opts.position = this.position++;
|
||
// @ts-ignore
|
||
this.matchIndexes[this.matchAt] = opts;
|
||
this.regexes.push([opts, re]);
|
||
this.matchAt += countMatchGroups(re) + 1;
|
||
}
|
||
|
||
compile() {
|
||
if (this.regexes.length === 0) {
|
||
// avoids the need to check length every time exec is called
|
||
// @ts-ignore
|
||
this.exec = () => null;
|
||
}
|
||
const terminators = this.regexes.map(el => el[1]);
|
||
this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true);
|
||
this.lastIndex = 0;
|
||
}
|
||
|
||
/** @param {string} s */
|
||
exec(s) {
|
||
this.matcherRe.lastIndex = this.lastIndex;
|
||
const match = this.matcherRe.exec(s);
|
||
if (!match) { return null; }
|
||
|
||
// eslint-disable-next-line no-undefined
|
||
const i = match.findIndex((el, i) => i > 0 && el !== undefined);
|
||
// @ts-ignore
|
||
const matchData = this.matchIndexes[i];
|
||
// trim off any earlier non-relevant match groups (ie, the other regex
|
||
// match groups that make up the multi-matcher)
|
||
match.splice(0, i);
|
||
|
||
return Object.assign(match, matchData);
|
||
}
|
||
}
|
||
|
||
/*
|
||
Created to solve the key deficiently with MultiRegex - there is no way to
|
||
test for multiple matches at a single location. Why would we need to do
|
||
that? In the future a more dynamic engine will allow certain matches to be
|
||
ignored. An example: if we matched say the 3rd regex in a large group but
|
||
decided to ignore it - we'd need to started testing again at the 4th
|
||
regex... but MultiRegex itself gives us no real way to do that.
|
||
|
||
So what this class creates MultiRegexs on the fly for whatever search
|
||
position they are needed.
|
||
|
||
NOTE: These additional MultiRegex objects are created dynamically. For most
|
||
grammars most of the time we will never actually need anything more than the
|
||
first MultiRegex - so this shouldn't have too much overhead.
|
||
|
||
Say this is our search group, and we match regex3, but wish to ignore it.
|
||
|
||
regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0
|
||
|
||
What we need is a new MultiRegex that only includes the remaining
|
||
possibilities:
|
||
|
||
regex4 | regex5 ' ie, startAt = 3
|
||
|
||
This class wraps all that complexity up in a simple API... `startAt` decides
|
||
where in the array of expressions to start doing the matching. It
|
||
auto-increments, so if a match is found at position 2, then startAt will be
|
||
set to 3. If the end is reached startAt will return to 0.
|
||
|
||
MOST of the time the parser will be setting startAt manually to 0.
|
||
*/
|
||
class ResumableMultiRegex {
|
||
constructor() {
|
||
// @ts-ignore
|
||
this.rules = [];
|
||
// @ts-ignore
|
||
this.multiRegexes = [];
|
||
this.count = 0;
|
||
|
||
this.lastIndex = 0;
|
||
this.regexIndex = 0;
|
||
}
|
||
|
||
// @ts-ignore
|
||
getMatcher(index) {
|
||
if (this.multiRegexes[index]) return this.multiRegexes[index];
|
||
|
||
const matcher = new MultiRegex();
|
||
this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts));
|
||
matcher.compile();
|
||
this.multiRegexes[index] = matcher;
|
||
return matcher;
|
||
}
|
||
|
||
resumingScanAtSamePosition() {
|
||
return this.regexIndex !== 0;
|
||
}
|
||
|
||
considerAll() {
|
||
this.regexIndex = 0;
|
||
}
|
||
|
||
// @ts-ignore
|
||
addRule(re, opts) {
|
||
this.rules.push([re, opts]);
|
||
if (opts.type === "begin") this.count++;
|
||
}
|
||
|
||
/** @param {string} s */
|
||
exec(s) {
|
||
const m = this.getMatcher(this.regexIndex);
|
||
m.lastIndex = this.lastIndex;
|
||
let result = m.exec(s);
|
||
|
||
// The following is because we have no easy way to say "resume scanning at the
|
||
// existing position but also skip the current rule ONLY". What happens is
|
||
// all prior rules are also skipped which can result in matching the wrong
|
||
// thing. Example of matching "booger":
|
||
|
||
// our matcher is [string, "booger", number]
|
||
//
|
||
// ....booger....
|
||
|
||
// if "booger" is ignored then we'd really need a regex to scan from the
|
||
// SAME position for only: [string, number] but ignoring "booger" (if it
|
||
// was the first match), a simple resume would scan ahead who knows how
|
||
// far looking only for "number", ignoring potential string matches (or
|
||
// future "booger" matches that might be valid.)
|
||
|
||
// So what we do: We execute two matchers, one resuming at the same
|
||
// position, but the second full matcher starting at the position after:
|
||
|
||
// /--- resume first regex match here (for [number])
|
||
// |/---- full match here for [string, "booger", number]
|
||
// vv
|
||
// ....booger....
|
||
|
||
// Which ever results in a match first is then used. So this 3-4 step
|
||
// process essentially allows us to say "match at this position, excluding
|
||
// a prior rule that was ignored".
|
||
//
|
||
// 1. Match "booger" first, ignore. Also proves that [string] does non match.
|
||
// 2. Resume matching for [number]
|
||
// 3. Match at index + 1 for [string, "booger", number]
|
||
// 4. If #2 and #3 result in matches, which came first?
|
||
if (this.resumingScanAtSamePosition()) {
|
||
if (result && result.index === this.lastIndex) ; else { // use the second matcher result
|
||
const m2 = this.getMatcher(0);
|
||
m2.lastIndex = this.lastIndex + 1;
|
||
result = m2.exec(s);
|
||
}
|
||
}
|
||
|
||
if (result) {
|
||
this.regexIndex += result.position + 1;
|
||
if (this.regexIndex === this.count) {
|
||
// wrap-around to considering all matches again
|
||
this.considerAll();
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Given a mode, builds a huge ResumableMultiRegex that can be used to walk
|
||
* the content and find matches.
|
||
*
|
||
* @param {CompiledMode} mode
|
||
* @returns {ResumableMultiRegex}
|
||
*/
|
||
function buildModeRegex(mode) {
|
||
const mm = new ResumableMultiRegex();
|
||
|
||
mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: "begin" }));
|
||
|
||
if (mode.terminatorEnd) {
|
||
mm.addRule(mode.terminatorEnd, { type: "end" });
|
||
}
|
||
if (mode.illegal) {
|
||
mm.addRule(mode.illegal, { type: "illegal" });
|
||
}
|
||
|
||
return mm;
|
||
}
|
||
|
||
/** skip vs abort vs ignore
|
||
*
|
||
* @skip - The mode is still entered and exited normally (and contains rules apply),
|
||
* but all content is held and added to the parent buffer rather than being
|
||
* output when the mode ends. Mostly used with `sublanguage` to build up
|
||
* a single large buffer than can be parsed by sublanguage.
|
||
*
|
||
* - The mode begin ands ends normally.
|
||
* - Content matched is added to the parent mode buffer.
|
||
* - The parser cursor is moved forward normally.
|
||
*
|
||
* @abort - A hack placeholder until we have ignore. Aborts the mode (as if it
|
||
* never matched) but DOES NOT continue to match subsequent `contains`
|
||
* modes. Abort is bad/suboptimal because it can result in modes
|
||
* farther down not getting applied because an earlier rule eats the
|
||
* content but then aborts.
|
||
*
|
||
* - The mode does not begin.
|
||
* - Content matched by `begin` is added to the mode buffer.
|
||
* - The parser cursor is moved forward accordingly.
|
||
*
|
||
* @ignore - Ignores the mode (as if it never matched) and continues to match any
|
||
* subsequent `contains` modes. Ignore isn't technically possible with
|
||
* the current parser implementation.
|
||
*
|
||
* - The mode does not begin.
|
||
* - Content matched by `begin` is ignored.
|
||
* - The parser cursor is not moved forward.
|
||
*/
|
||
|
||
/**
|
||
* Compiles an individual mode
|
||
*
|
||
* This can raise an error if the mode contains certain detectable known logic
|
||
* issues.
|
||
* @param {Mode} mode
|
||
* @param {CompiledMode | null} [parent]
|
||
* @returns {CompiledMode | never}
|
||
*/
|
||
function compileMode(mode, parent) {
|
||
const cmode = /** @type CompiledMode */ (mode);
|
||
if (mode.isCompiled) return cmode;
|
||
|
||
[
|
||
scopeClassName,
|
||
// do this early so compiler extensions generally don't have to worry about
|
||
// the distinction between match/begin
|
||
compileMatch,
|
||
MultiClass,
|
||
beforeMatchExt
|
||
].forEach(ext => ext(mode, parent));
|
||
|
||
language.compilerExtensions.forEach(ext => ext(mode, parent));
|
||
|
||
// __beforeBegin is considered private API, internal use only
|
||
mode.__beforeBegin = null;
|
||
|
||
[
|
||
beginKeywords,
|
||
// do this later so compiler extensions that come earlier have access to the
|
||
// raw array if they wanted to perhaps manipulate it, etc.
|
||
compileIllegal,
|
||
// default to 1 relevance if not specified
|
||
compileRelevance
|
||
].forEach(ext => ext(mode, parent));
|
||
|
||
mode.isCompiled = true;
|
||
|
||
let keywordPattern = null;
|
||
if (typeof mode.keywords === "object" && mode.keywords.$pattern) {
|
||
// we need a copy because keywords might be compiled multiple times
|
||
// so we can't go deleting $pattern from the original on the first
|
||
// pass
|
||
mode.keywords = Object.assign({}, mode.keywords);
|
||
keywordPattern = mode.keywords.$pattern;
|
||
delete mode.keywords.$pattern;
|
||
}
|
||
keywordPattern = keywordPattern || /\w+/;
|
||
|
||
if (mode.keywords) {
|
||
mode.keywords = compileKeywords(mode.keywords, language.case_insensitive);
|
||
}
|
||
|
||
cmode.keywordPatternRe = langRe(keywordPattern, true);
|
||
|
||
if (parent) {
|
||
if (!mode.begin) mode.begin = /\B|\b/;
|
||
cmode.beginRe = langRe(cmode.begin);
|
||
if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/;
|
||
if (mode.end) cmode.endRe = langRe(cmode.end);
|
||
cmode.terminatorEnd = source(cmode.end) || '';
|
||
if (mode.endsWithParent && parent.terminatorEnd) {
|
||
cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd;
|
||
}
|
||
}
|
||
if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal));
|
||
if (!mode.contains) mode.contains = [];
|
||
|
||
mode.contains = [].concat(...mode.contains.map(function(c) {
|
||
return expandOrCloneMode(c === 'self' ? mode : c);
|
||
}));
|
||
mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); });
|
||
|
||
if (mode.starts) {
|
||
compileMode(mode.starts, parent);
|
||
}
|
||
|
||
cmode.matcher = buildModeRegex(cmode);
|
||
return cmode;
|
||
}
|
||
|
||
if (!language.compilerExtensions) language.compilerExtensions = [];
|
||
|
||
// self is not valid at the top-level
|
||
if (language.contains && language.contains.includes('self')) {
|
||
throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");
|
||
}
|
||
|
||
// we need a null object, which inherit will guarantee
|
||
language.classNameAliases = inherit$1(language.classNameAliases || {});
|
||
|
||
return compileMode(/** @type Mode */ (language));
|
||
}
|
||
|
||
/**
|
||
* Determines if a mode has a dependency on it's parent or not
|
||
*
|
||
* If a mode does have a parent dependency then often we need to clone it if
|
||
* it's used in multiple places so that each copy points to the correct parent,
|
||
* where-as modes without a parent can often safely be re-used at the bottom of
|
||
* a mode chain.
|
||
*
|
||
* @param {Mode | null} mode
|
||
* @returns {boolean} - is there a dependency on the parent?
|
||
* */
|
||
function dependencyOnParent(mode) {
|
||
if (!mode) return false;
|
||
|
||
return mode.endsWithParent || dependencyOnParent(mode.starts);
|
||
}
|
||
|
||
/**
|
||
* Expands a mode or clones it if necessary
|
||
*
|
||
* This is necessary for modes with parental dependenceis (see notes on
|
||
* `dependencyOnParent`) and for nodes that have `variants` - which must then be
|
||
* exploded into their own individual modes at compile time.
|
||
*
|
||
* @param {Mode} mode
|
||
* @returns {Mode | Mode[]}
|
||
* */
|
||
function expandOrCloneMode(mode) {
|
||
if (mode.variants && !mode.cachedVariants) {
|
||
mode.cachedVariants = mode.variants.map(function(variant) {
|
||
return inherit$1(mode, { variants: null }, variant);
|
||
});
|
||
}
|
||
|
||
// EXPAND
|
||
// if we have variants then essentially "replace" the mode with the variants
|
||
// this happens in compileMode, where this function is called from
|
||
if (mode.cachedVariants) {
|
||
return mode.cachedVariants;
|
||
}
|
||
|
||
// CLONE
|
||
// if we have dependencies on parents then we need a unique
|
||
// instance of ourselves, so we can be reused with many
|
||
// different parents without issue
|
||
if (dependencyOnParent(mode)) {
|
||
return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null });
|
||
}
|
||
|
||
if (Object.isFrozen(mode)) {
|
||
return inherit$1(mode);
|
||
}
|
||
|
||
// no special dependency issues, just return ourselves
|
||
return mode;
|
||
}
|
||
|
||
var version = "11.9.0";
|
||
|
||
class HTMLInjectionError extends Error {
|
||
constructor(reason, html) {
|
||
super(reason);
|
||
this.name = "HTMLInjectionError";
|
||
this.html = html;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Syntax highlighting with language autodetection.
|
||
https://highlightjs.org/
|
||
*/
|
||
|
||
|
||
|
||
/**
|
||
@typedef {import('highlight.js').Mode} Mode
|
||
@typedef {import('highlight.js').CompiledMode} CompiledMode
|
||
@typedef {import('highlight.js').CompiledScope} CompiledScope
|
||
@typedef {import('highlight.js').Language} Language
|
||
@typedef {import('highlight.js').HLJSApi} HLJSApi
|
||
@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
|
||
@typedef {import('highlight.js').PluginEvent} PluginEvent
|
||
@typedef {import('highlight.js').HLJSOptions} HLJSOptions
|
||
@typedef {import('highlight.js').LanguageFn} LanguageFn
|
||
@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement
|
||
@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext
|
||
@typedef {import('highlight.js/private').MatchType} MatchType
|
||
@typedef {import('highlight.js/private').KeywordData} KeywordData
|
||
@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch
|
||
@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError
|
||
@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult
|
||
@typedef {import('highlight.js').HighlightOptions} HighlightOptions
|
||
@typedef {import('highlight.js').HighlightResult} HighlightResult
|
||
*/
|
||
|
||
|
||
const escape = escapeHTML;
|
||
const inherit = inherit$1;
|
||
const NO_MATCH = Symbol("nomatch");
|
||
const MAX_KEYWORD_HITS = 7;
|
||
|
||
/**
|
||
* @param {any} hljs - object that is extended (legacy)
|
||
* @returns {HLJSApi}
|
||
*/
|
||
const HLJS = function(hljs) {
|
||
// Global internal variables used within the highlight.js library.
|
||
/** @type {Record<string, Language>} */
|
||
const languages = Object.create(null);
|
||
/** @type {Record<string, string>} */
|
||
const aliases = Object.create(null);
|
||
/** @type {HLJSPlugin[]} */
|
||
const plugins = [];
|
||
|
||
// safe/production mode - swallows more errors, tries to keep running
|
||
// even if a single syntax or parse hits a fatal error
|
||
let SAFE_MODE = true;
|
||
const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?";
|
||
/** @type {Language} */
|
||
const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] };
|
||
|
||
// Global options used when within external APIs. This is modified when
|
||
// calling the `hljs.configure` function.
|
||
/** @type HLJSOptions */
|
||
let options = {
|
||
ignoreUnescapedHTML: false,
|
||
throwUnescapedHTML: false,
|
||
noHighlightRe: /^(no-?highlight)$/i,
|
||
languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i,
|
||
classPrefix: 'hljs-',
|
||
cssSelector: 'pre code',
|
||
languages: null,
|
||
// beta configuration options, subject to change, welcome to discuss
|
||
// https://github.com/highlightjs/highlight.js/issues/1086
|
||
__emitter: TokenTreeEmitter
|
||
};
|
||
|
||
/* Utility functions */
|
||
|
||
/**
|
||
* Tests a language name to see if highlighting should be skipped
|
||
* @param {string} languageName
|
||
*/
|
||
function shouldNotHighlight(languageName) {
|
||
return options.noHighlightRe.test(languageName);
|
||
}
|
||
|
||
/**
|
||
* @param {HighlightedHTMLElement} block - the HTML element to determine language for
|
||
*/
|
||
function blockLanguage(block) {
|
||
let classes = block.className + ' ';
|
||
|
||
classes += block.parentNode ? block.parentNode.className : '';
|
||
|
||
// language-* takes precedence over non-prefixed class names.
|
||
const match = options.languageDetectRe.exec(classes);
|
||
if (match) {
|
||
const language = getLanguage(match[1]);
|
||
if (!language) {
|
||
warn(LANGUAGE_NOT_FOUND.replace("{}", match[1]));
|
||
warn("Falling back to no-highlight mode for this block.", block);
|
||
}
|
||
return language ? match[1] : 'no-highlight';
|
||
}
|
||
|
||
return classes
|
||
.split(/\s+/)
|
||
.find((_class) => shouldNotHighlight(_class) || getLanguage(_class));
|
||
}
|
||
|
||
/**
|
||
* Core highlighting function.
|
||
*
|
||
* OLD API
|
||
* highlight(lang, code, ignoreIllegals, continuation)
|
||
*
|
||
* NEW API
|
||
* highlight(code, {lang, ignoreIllegals})
|
||
*
|
||
* @param {string} codeOrLanguageName - the language to use for highlighting
|
||
* @param {string | HighlightOptions} optionsOrCode - the code to highlight
|
||
* @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
|
||
*
|
||
* @returns {HighlightResult} Result - an object that represents the result
|
||
* @property {string} language - the language name
|
||
* @property {number} relevance - the relevance score
|
||
* @property {string} value - the highlighted HTML code
|
||
* @property {string} code - the original raw code
|
||
* @property {CompiledMode} top - top of the current mode stack
|
||
* @property {boolean} illegal - indicates whether any illegal matches were found
|
||
*/
|
||
function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) {
|
||
let code = "";
|
||
let languageName = "";
|
||
if (typeof optionsOrCode === "object") {
|
||
code = codeOrLanguageName;
|
||
ignoreIllegals = optionsOrCode.ignoreIllegals;
|
||
languageName = optionsOrCode.language;
|
||
} else {
|
||
// old API
|
||
deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated.");
|
||
deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277");
|
||
languageName = codeOrLanguageName;
|
||
code = optionsOrCode;
|
||
}
|
||
|
||
// https://github.com/highlightjs/highlight.js/issues/3149
|
||
// eslint-disable-next-line no-undefined
|
||
if (ignoreIllegals === undefined) { ignoreIllegals = true; }
|
||
|
||
/** @type {BeforeHighlightContext} */
|
||
const context = {
|
||
code,
|
||
language: languageName
|
||
};
|
||
// the plugin can change the desired language or the code to be highlighted
|
||
// just be changing the object it was passed
|
||
fire("before:highlight", context);
|
||
|
||
// a before plugin can usurp the result completely by providing it's own
|
||
// in which case we don't even need to call highlight
|
||
const result = context.result
|
||
? context.result
|
||
: _highlight(context.language, context.code, ignoreIllegals);
|
||
|
||
result.code = context.code;
|
||
// the plugin can change anything in result to suite it
|
||
fire("after:highlight", result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* private highlight that's used internally and does not fire callbacks
|
||
*
|
||
* @param {string} languageName - the language to use for highlighting
|
||
* @param {string} codeToHighlight - the code to highlight
|
||
* @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
|
||
* @param {CompiledMode?} [continuation] - current continuation mode, if any
|
||
* @returns {HighlightResult} - result of the highlight operation
|
||
*/
|
||
function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {
|
||
const keywordHits = Object.create(null);
|
||
|
||
/**
|
||
* Return keyword data if a match is a keyword
|
||
* @param {CompiledMode} mode - current mode
|
||
* @param {string} matchText - the textual match
|
||
* @returns {KeywordData | false}
|
||
*/
|
||
function keywordData(mode, matchText) {
|
||
return mode.keywords[matchText];
|
||
}
|
||
|
||
function processKeywords() {
|
||
if (!top.keywords) {
|
||
emitter.addText(modeBuffer);
|
||
return;
|
||
}
|
||
|
||
let lastIndex = 0;
|
||
top.keywordPatternRe.lastIndex = 0;
|
||
let match = top.keywordPatternRe.exec(modeBuffer);
|
||
let buf = "";
|
||
|
||
while (match) {
|
||
buf += modeBuffer.substring(lastIndex, match.index);
|
||
const word = language.case_insensitive ? match[0].toLowerCase() : match[0];
|
||
const data = keywordData(top, word);
|
||
if (data) {
|
||
const [kind, keywordRelevance] = data;
|
||
emitter.addText(buf);
|
||
buf = "";
|
||
|
||
keywordHits[word] = (keywordHits[word] || 0) + 1;
|
||
if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance;
|
||
if (kind.startsWith("_")) {
|
||
// _ implied for relevance only, do not highlight
|
||
// by applying a class name
|
||
buf += match[0];
|
||
} else {
|
||
const cssClass = language.classNameAliases[kind] || kind;
|
||
emitKeyword(match[0], cssClass);
|
||
}
|
||
} else {
|
||
buf += match[0];
|
||
}
|
||
lastIndex = top.keywordPatternRe.lastIndex;
|
||
match = top.keywordPatternRe.exec(modeBuffer);
|
||
}
|
||
buf += modeBuffer.substring(lastIndex);
|
||
emitter.addText(buf);
|
||
}
|
||
|
||
function processSubLanguage() {
|
||
if (modeBuffer === "") return;
|
||
/** @type HighlightResult */
|
||
let result = null;
|
||
|
||
if (typeof top.subLanguage === 'string') {
|
||
if (!languages[top.subLanguage]) {
|
||
emitter.addText(modeBuffer);
|
||
return;
|
||
}
|
||
result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]);
|
||
continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top);
|
||
} else {
|
||
result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null);
|
||
}
|
||
|
||
// Counting embedded language score towards the host language may be disabled
|
||
// with zeroing the containing mode relevance. Use case in point is Markdown that
|
||
// allows XML everywhere and makes every XML snippet to have a much larger Markdown
|
||
// score.
|
||
if (top.relevance > 0) {
|
||
relevance += result.relevance;
|
||
}
|
||
emitter.__addSublanguage(result._emitter, result.language);
|
||
}
|
||
|
||
function processBuffer() {
|
||
if (top.subLanguage != null) {
|
||
processSubLanguage();
|
||
} else {
|
||
processKeywords();
|
||
}
|
||
modeBuffer = '';
|
||
}
|
||
|
||
/**
|
||
* @param {string} text
|
||
* @param {string} scope
|
||
*/
|
||
function emitKeyword(keyword, scope) {
|
||
if (keyword === "") return;
|
||
|
||
emitter.startScope(scope);
|
||
emitter.addText(keyword);
|
||
emitter.endScope();
|
||
}
|
||
|
||
/**
|
||
* @param {CompiledScope} scope
|
||
* @param {RegExpMatchArray} match
|
||
*/
|
||
function emitMultiClass(scope, match) {
|
||
let i = 1;
|
||
const max = match.length - 1;
|
||
while (i <= max) {
|
||
if (!scope._emit[i]) { i++; continue; }
|
||
const klass = language.classNameAliases[scope[i]] || scope[i];
|
||
const text = match[i];
|
||
if (klass) {
|
||
emitKeyword(text, klass);
|
||
} else {
|
||
modeBuffer = text;
|
||
processKeywords();
|
||
modeBuffer = "";
|
||
}
|
||
i++;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param {CompiledMode} mode - new mode to start
|
||
* @param {RegExpMatchArray} match
|
||
*/
|
||
function startNewMode(mode, match) {
|
||
if (mode.scope && typeof mode.scope === "string") {
|
||
emitter.openNode(language.classNameAliases[mode.scope] || mode.scope);
|
||
}
|
||
if (mode.beginScope) {
|
||
// beginScope just wraps the begin match itself in a scope
|
||
if (mode.beginScope._wrap) {
|
||
emitKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap);
|
||
modeBuffer = "";
|
||
} else if (mode.beginScope._multi) {
|
||
// at this point modeBuffer should just be the match
|
||
emitMultiClass(mode.beginScope, match);
|
||
modeBuffer = "";
|
||
}
|
||
}
|
||
|
||
top = Object.create(mode, { parent: { value: top } });
|
||
return top;
|
||
}
|
||
|
||
/**
|
||
* @param {CompiledMode } mode - the mode to potentially end
|
||
* @param {RegExpMatchArray} match - the latest match
|
||
* @param {string} matchPlusRemainder - match plus remainder of content
|
||
* @returns {CompiledMode | void} - the next mode, or if void continue on in current mode
|
||
*/
|
||
function endOfMode(mode, match, matchPlusRemainder) {
|
||
let matched = startsWith(mode.endRe, matchPlusRemainder);
|
||
|
||
if (matched) {
|
||
if (mode["on:end"]) {
|
||
const resp = new Response(mode);
|
||
mode["on:end"](match, resp);
|
||
if (resp.isMatchIgnored) matched = false;
|
||
}
|
||
|
||
if (matched) {
|
||
while (mode.endsParent && mode.parent) {
|
||
mode = mode.parent;
|
||
}
|
||
return mode;
|
||
}
|
||
}
|
||
// even if on:end fires an `ignore` it's still possible
|
||
// that we might trigger the end node because of a parent mode
|
||
if (mode.endsWithParent) {
|
||
return endOfMode(mode.parent, match, matchPlusRemainder);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Handle matching but then ignoring a sequence of text
|
||
*
|
||
* @param {string} lexeme - string containing full match text
|
||
*/
|
||
function doIgnore(lexeme) {
|
||
if (top.matcher.regexIndex === 0) {
|
||
// no more regexes to potentially match here, so we move the cursor forward one
|
||
// space
|
||
modeBuffer += lexeme[0];
|
||
return 1;
|
||
} else {
|
||
// no need to move the cursor, we still have additional regexes to try and
|
||
// match at this very spot
|
||
resumeScanAtSamePosition = true;
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Handle the start of a new potential mode match
|
||
*
|
||
* @param {EnhancedMatch} match - the current match
|
||
* @returns {number} how far to advance the parse cursor
|
||
*/
|
||
function doBeginMatch(match) {
|
||
const lexeme = match[0];
|
||
const newMode = match.rule;
|
||
|
||
const resp = new Response(newMode);
|
||
// first internal before callbacks, then the public ones
|
||
const beforeCallbacks = [newMode.__beforeBegin, newMode["on:begin"]];
|
||
for (const cb of beforeCallbacks) {
|
||
if (!cb) continue;
|
||
cb(match, resp);
|
||
if (resp.isMatchIgnored) return doIgnore(lexeme);
|
||
}
|
||
|
||
if (newMode.skip) {
|
||
modeBuffer += lexeme;
|
||
} else {
|
||
if (newMode.excludeBegin) {
|
||
modeBuffer += lexeme;
|
||
}
|
||
processBuffer();
|
||
if (!newMode.returnBegin && !newMode.excludeBegin) {
|
||
modeBuffer = lexeme;
|
||
}
|
||
}
|
||
startNewMode(newMode, match);
|
||
return newMode.returnBegin ? 0 : lexeme.length;
|
||
}
|
||
|
||
/**
|
||
* Handle the potential end of mode
|
||
*
|
||
* @param {RegExpMatchArray} match - the current match
|
||
*/
|
||
function doEndMatch(match) {
|
||
const lexeme = match[0];
|
||
const matchPlusRemainder = codeToHighlight.substring(match.index);
|
||
|
||
const endMode = endOfMode(top, match, matchPlusRemainder);
|
||
if (!endMode) { return NO_MATCH; }
|
||
|
||
const origin = top;
|
||
if (top.endScope && top.endScope._wrap) {
|
||
processBuffer();
|
||
emitKeyword(lexeme, top.endScope._wrap);
|
||
} else if (top.endScope && top.endScope._multi) {
|
||
processBuffer();
|
||
emitMultiClass(top.endScope, match);
|
||
} else if (origin.skip) {
|
||
modeBuffer += lexeme;
|
||
} else {
|
||
if (!(origin.returnEnd || origin.excludeEnd)) {
|
||
modeBuffer += lexeme;
|
||
}
|
||
processBuffer();
|
||
if (origin.excludeEnd) {
|
||
modeBuffer = lexeme;
|
||
}
|
||
}
|
||
do {
|
||
if (top.scope) {
|
||
emitter.closeNode();
|
||
}
|
||
if (!top.skip && !top.subLanguage) {
|
||
relevance += top.relevance;
|
||
}
|
||
top = top.parent;
|
||
} while (top !== endMode.parent);
|
||
if (endMode.starts) {
|
||
startNewMode(endMode.starts, match);
|
||
}
|
||
return origin.returnEnd ? 0 : lexeme.length;
|
||
}
|
||
|
||
function processContinuations() {
|
||
const list = [];
|
||
for (let current = top; current !== language; current = current.parent) {
|
||
if (current.scope) {
|
||
list.unshift(current.scope);
|
||
}
|
||
}
|
||
list.forEach(item => emitter.openNode(item));
|
||
}
|
||
|
||
/** @type {{type?: MatchType, index?: number, rule?: Mode}}} */
|
||
let lastMatch = {};
|
||
|
||
/**
|
||
* Process an individual match
|
||
*
|
||
* @param {string} textBeforeMatch - text preceding the match (since the last match)
|
||
* @param {EnhancedMatch} [match] - the match itself
|
||
*/
|
||
function processLexeme(textBeforeMatch, match) {
|
||
const lexeme = match && match[0];
|
||
|
||
// add non-matched text to the current mode buffer
|
||
modeBuffer += textBeforeMatch;
|
||
|
||
if (lexeme == null) {
|
||
processBuffer();
|
||
return 0;
|
||
}
|
||
|
||
// we've found a 0 width match and we're stuck, so we need to advance
|
||
// this happens when we have badly behaved rules that have optional matchers to the degree that
|
||
// sometimes they can end up matching nothing at all
|
||
// Ref: https://github.com/highlightjs/highlight.js/issues/2140
|
||
if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") {
|
||
// spit the "skipped" character that our regex choked on back into the output sequence
|
||
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
|
||
if (!SAFE_MODE) {
|
||
/** @type {AnnotatedError} */
|
||
const err = new Error(`0 width match regex (${languageName})`);
|
||
err.languageName = languageName;
|
||
err.badRule = lastMatch.rule;
|
||
throw err;
|
||
}
|
||
return 1;
|
||
}
|
||
lastMatch = match;
|
||
|
||
if (match.type === "begin") {
|
||
return doBeginMatch(match);
|
||
} else if (match.type === "illegal" && !ignoreIllegals) {
|
||
// illegal match, we do not continue processing
|
||
/** @type {AnnotatedError} */
|
||
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '<unnamed>') + '"');
|
||
err.mode = top;
|
||
throw err;
|
||
} else if (match.type === "end") {
|
||
const processed = doEndMatch(match);
|
||
if (processed !== NO_MATCH) {
|
||
return processed;
|
||
}
|
||
}
|
||
|
||
// edge case for when illegal matches $ (end of line) which is technically
|
||
// a 0 width match but not a begin/end match so it's not caught by the
|
||
// first handler (when ignoreIllegals is true)
|
||
if (match.type === "illegal" && lexeme === "") {
|
||
// advance so we aren't stuck in an infinite loop
|
||
return 1;
|
||
}
|
||
|
||
// infinite loops are BAD, this is a last ditch catch all. if we have a
|
||
// decent number of iterations yet our index (cursor position in our
|
||
// parsing) still 3x behind our index then something is very wrong
|
||
// so we bail
|
||
if (iterations > 100000 && iterations > match.index * 3) {
|
||
const err = new Error('potential infinite loop, way more iterations than matches');
|
||
throw err;
|
||
}
|
||
|
||
/*
|
||
Why might be find ourselves here? An potential end match that was
|
||
triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH.
|
||
(this could be because a callback requests the match be ignored, etc)
|
||
|
||
This causes no real harm other than stopping a few times too many.
|
||
*/
|
||
|
||
modeBuffer += lexeme;
|
||
return lexeme.length;
|
||
}
|
||
|
||
const language = getLanguage(languageName);
|
||
if (!language) {
|
||
error(LANGUAGE_NOT_FOUND.replace("{}", languageName));
|
||
throw new Error('Unknown language: "' + languageName + '"');
|
||
}
|
||
|
||
const md = compileLanguage(language);
|
||
let result = '';
|
||
/** @type {CompiledMode} */
|
||
let top = continuation || md;
|
||
/** @type Record<string,CompiledMode> */
|
||
const continuations = {}; // keep continuations for sub-languages
|
||
const emitter = new options.__emitter(options);
|
||
processContinuations();
|
||
let modeBuffer = '';
|
||
let relevance = 0;
|
||
let index = 0;
|
||
let iterations = 0;
|
||
let resumeScanAtSamePosition = false;
|
||
|
||
try {
|
||
if (!language.__emitTokens) {
|
||
top.matcher.considerAll();
|
||
|
||
for (;;) {
|
||
iterations++;
|
||
if (resumeScanAtSamePosition) {
|
||
// only regexes not matched previously will now be
|
||
// considered for a potential match
|
||
resumeScanAtSamePosition = false;
|
||
} else {
|
||
top.matcher.considerAll();
|
||
}
|
||
top.matcher.lastIndex = index;
|
||
|
||
const match = top.matcher.exec(codeToHighlight);
|
||
// console.log("match", match[0], match.rule && match.rule.begin)
|
||
|
||
if (!match) break;
|
||
|
||
const beforeMatch = codeToHighlight.substring(index, match.index);
|
||
const processedCount = processLexeme(beforeMatch, match);
|
||
index = match.index + processedCount;
|
||
}
|
||
processLexeme(codeToHighlight.substring(index));
|
||
} else {
|
||
language.__emitTokens(codeToHighlight, emitter);
|
||
}
|
||
|
||
emitter.finalize();
|
||
result = emitter.toHTML();
|
||
|
||
return {
|
||
language: languageName,
|
||
value: result,
|
||
relevance,
|
||
illegal: false,
|
||
_emitter: emitter,
|
||
_top: top
|
||
};
|
||
} catch (err) {
|
||
if (err.message && err.message.includes('Illegal')) {
|
||
return {
|
||
language: languageName,
|
||
value: escape(codeToHighlight),
|
||
illegal: true,
|
||
relevance: 0,
|
||
_illegalBy: {
|
||
message: err.message,
|
||
index,
|
||
context: codeToHighlight.slice(index - 100, index + 100),
|
||
mode: err.mode,
|
||
resultSoFar: result
|
||
},
|
||
_emitter: emitter
|
||
};
|
||
} else if (SAFE_MODE) {
|
||
return {
|
||
language: languageName,
|
||
value: escape(codeToHighlight),
|
||
illegal: false,
|
||
relevance: 0,
|
||
errorRaised: err,
|
||
_emitter: emitter,
|
||
_top: top
|
||
};
|
||
} else {
|
||
throw err;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* returns a valid highlight result, without actually doing any actual work,
|
||
* auto highlight starts with this and it's possible for small snippets that
|
||
* auto-detection may not find a better match
|
||
* @param {string} code
|
||
* @returns {HighlightResult}
|
||
*/
|
||
function justTextHighlightResult(code) {
|
||
const result = {
|
||
value: escape(code),
|
||
illegal: false,
|
||
relevance: 0,
|
||
_top: PLAINTEXT_LANGUAGE,
|
||
_emitter: new options.__emitter(options)
|
||
};
|
||
result._emitter.addText(code);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
Highlighting with language detection. Accepts a string with the code to
|
||
highlight. Returns an object with the following properties:
|
||
|
||
- language (detected language)
|
||
- relevance (int)
|
||
- value (an HTML string with highlighting markup)
|
||
- secondBest (object with the same structure for second-best heuristically
|
||
detected language, may be absent)
|
||
|
||
@param {string} code
|
||
@param {Array<string>} [languageSubset]
|
||
@returns {AutoHighlightResult}
|
||
*/
|
||
function highlightAuto(code, languageSubset) {
|
||
languageSubset = languageSubset || options.languages || Object.keys(languages);
|
||
const plaintext = justTextHighlightResult(code);
|
||
|
||
const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name =>
|
||
_highlight(name, code, false)
|
||
);
|
||
results.unshift(plaintext); // plaintext is always an option
|
||
|
||
const sorted = results.sort((a, b) => {
|
||
// sort base on relevance
|
||
if (a.relevance !== b.relevance) return b.relevance - a.relevance;
|
||
|
||
// always award the tie to the base language
|
||
// ie if C++ and Arduino are tied, it's more likely to be C++
|
||
if (a.language && b.language) {
|
||
if (getLanguage(a.language).supersetOf === b.language) {
|
||
return 1;
|
||
} else if (getLanguage(b.language).supersetOf === a.language) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// otherwise say they are equal, which has the effect of sorting on
|
||
// relevance while preserving the original ordering - which is how ties
|
||
// have historically been settled, ie the language that comes first always
|
||
// wins in the case of a tie
|
||
return 0;
|
||
});
|
||
|
||
const [best, secondBest] = sorted;
|
||
|
||
/** @type {AutoHighlightResult} */
|
||
const result = best;
|
||
result.secondBest = secondBest;
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Builds new class name for block given the language name
|
||
*
|
||
* @param {HTMLElement} element
|
||
* @param {string} [currentLang]
|
||
* @param {string} [resultLang]
|
||
*/
|
||
function updateClassName(element, currentLang, resultLang) {
|
||
const language = (currentLang && aliases[currentLang]) || resultLang;
|
||
|
||
element.classList.add("hljs");
|
||
element.classList.add(`language-${language}`);
|
||
}
|
||
|
||
/**
|
||
* Applies highlighting to a DOM node containing code.
|
||
*
|
||
* @param {HighlightedHTMLElement} element - the HTML element to highlight
|
||
*/
|
||
function highlightElement(element) {
|
||
/** @type HTMLElement */
|
||
let node = null;
|
||
const language = blockLanguage(element);
|
||
|
||
if (shouldNotHighlight(language)) return;
|
||
|
||
fire("before:highlightElement",
|
||
{ el: element, language });
|
||
|
||
if (element.dataset.highlighted) {
|
||
console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.", element);
|
||
return;
|
||
}
|
||
|
||
// we should be all text, no child nodes (unescaped HTML) - this is possibly
|
||
// an HTML injection attack - it's likely too late if this is already in
|
||
// production (the code has likely already done its damage by the time
|
||
// we're seeing it)... but we yell loudly about this so that hopefully it's
|
||
// more likely to be caught in development before making it to production
|
||
if (element.children.length > 0) {
|
||
if (!options.ignoreUnescapedHTML) {
|
||
console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk.");
|
||
console.warn("https://github.com/highlightjs/highlight.js/wiki/security");
|
||
console.warn("The element with unescaped HTML:");
|
||
console.warn(element);
|
||
}
|
||
if (options.throwUnescapedHTML) {
|
||
const err = new HTMLInjectionError(
|
||
"One of your code blocks includes unescaped HTML.",
|
||
element.innerHTML
|
||
);
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
node = element;
|
||
const text = node.textContent;
|
||
const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);
|
||
|
||
element.innerHTML = result.value;
|
||
element.dataset.highlighted = "yes";
|
||
updateClassName(element, language, result.language);
|
||
element.result = {
|
||
language: result.language,
|
||
// TODO: remove with version 11.0
|
||
re: result.relevance,
|
||
relevance: result.relevance
|
||
};
|
||
if (result.secondBest) {
|
||
element.secondBest = {
|
||
language: result.secondBest.language,
|
||
relevance: result.secondBest.relevance
|
||
};
|
||
}
|
||
|
||
fire("after:highlightElement", { el: element, result, text });
|
||
}
|
||
|
||
/**
|
||
* Updates highlight.js global options with the passed options
|
||
*
|
||
* @param {Partial<HLJSOptions>} userOptions
|
||
*/
|
||
function configure(userOptions) {
|
||
options = inherit(options, userOptions);
|
||
}
|
||
|
||
// TODO: remove v12, deprecated
|
||
const initHighlighting = () => {
|
||
highlightAll();
|
||
deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now.");
|
||
};
|
||
|
||
// TODO: remove v12, deprecated
|
||
function initHighlightingOnLoad() {
|
||
highlightAll();
|
||
deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now.");
|
||
}
|
||
|
||
let wantsHighlight = false;
|
||
|
||
/**
|
||
* auto-highlights all pre>code elements on the page
|
||
*/
|
||
function highlightAll() {
|
||
// if we are called too early in the loading process
|
||
if (document.readyState === "loading") {
|
||
wantsHighlight = true;
|
||
return;
|
||
}
|
||
|
||
const blocks = document.querySelectorAll(options.cssSelector);
|
||
blocks.forEach(highlightElement);
|
||
}
|
||
|
||
function boot() {
|
||
// if a highlight was requested before DOM was loaded, do now
|
||
if (wantsHighlight) highlightAll();
|
||
}
|
||
|
||
// make sure we are in the browser environment
|
||
if (typeof window !== 'undefined' && window.addEventListener) {
|
||
window.addEventListener('DOMContentLoaded', boot, false);
|
||
}
|
||
|
||
/**
|
||
* Register a language grammar module
|
||
*
|
||
* @param {string} languageName
|
||
* @param {LanguageFn} languageDefinition
|
||
*/
|
||
function registerLanguage(languageName, languageDefinition) {
|
||
let lang = null;
|
||
try {
|
||
lang = languageDefinition(hljs);
|
||
} catch (error$1) {
|
||
error("Language definition for '{}' could not be registered.".replace("{}", languageName));
|
||
// hard or soft error
|
||
if (!SAFE_MODE) { throw error$1; } else { error(error$1); }
|
||
// languages that have serious errors are replaced with essentially a
|
||
// "plaintext" stand-in so that the code blocks will still get normal
|
||
// css classes applied to them - and one bad language won't break the
|
||
// entire highlighter
|
||
lang = PLAINTEXT_LANGUAGE;
|
||
}
|
||
// give it a temporary name if it doesn't have one in the meta-data
|
||
if (!lang.name) lang.name = languageName;
|
||
languages[languageName] = lang;
|
||
lang.rawDefinition = languageDefinition.bind(null, hljs);
|
||
|
||
if (lang.aliases) {
|
||
registerAliases(lang.aliases, { languageName });
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Remove a language grammar module
|
||
*
|
||
* @param {string} languageName
|
||
*/
|
||
function unregisterLanguage(languageName) {
|
||
delete languages[languageName];
|
||
for (const alias of Object.keys(aliases)) {
|
||
if (aliases[alias] === languageName) {
|
||
delete aliases[alias];
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @returns {string[]} List of language internal names
|
||
*/
|
||
function listLanguages() {
|
||
return Object.keys(languages);
|
||
}
|
||
|
||
/**
|
||
* @param {string} name - name of the language to retrieve
|
||
* @returns {Language | undefined}
|
||
*/
|
||
function getLanguage(name) {
|
||
name = (name || '').toLowerCase();
|
||
return languages[name] || languages[aliases[name]];
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param {string|string[]} aliasList - single alias or list of aliases
|
||
* @param {{languageName: string}} opts
|
||
*/
|
||
function registerAliases(aliasList, { languageName }) {
|
||
if (typeof aliasList === 'string') {
|
||
aliasList = [aliasList];
|
||
}
|
||
aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; });
|
||
}
|
||
|
||
/**
|
||
* Determines if a given language has auto-detection enabled
|
||
* @param {string} name - name of the language
|
||
*/
|
||
function autoDetection(name) {
|
||
const lang = getLanguage(name);
|
||
return lang && !lang.disableAutodetect;
|
||
}
|
||
|
||
/**
|
||
* Upgrades the old highlightBlock plugins to the new
|
||
* highlightElement API
|
||
* @param {HLJSPlugin} plugin
|
||
*/
|
||
function upgradePluginAPI(plugin) {
|
||
// TODO: remove with v12
|
||
if (plugin["before:highlightBlock"] && !plugin["before:highlightElement"]) {
|
||
plugin["before:highlightElement"] = (data) => {
|
||
plugin["before:highlightBlock"](
|
||
Object.assign({ block: data.el }, data)
|
||
);
|
||
};
|
||
}
|
||
if (plugin["after:highlightBlock"] && !plugin["after:highlightElement"]) {
|
||
plugin["after:highlightElement"] = (data) => {
|
||
plugin["after:highlightBlock"](
|
||
Object.assign({ block: data.el }, data)
|
||
);
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param {HLJSPlugin} plugin
|
||
*/
|
||
function addPlugin(plugin) {
|
||
upgradePluginAPI(plugin);
|
||
plugins.push(plugin);
|
||
}
|
||
|
||
/**
|
||
* @param {HLJSPlugin} plugin
|
||
*/
|
||
function removePlugin(plugin) {
|
||
const index = plugins.indexOf(plugin);
|
||
if (index !== -1) {
|
||
plugins.splice(index, 1);
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param {PluginEvent} event
|
||
* @param {any} args
|
||
*/
|
||
function fire(event, args) {
|
||
const cb = event;
|
||
plugins.forEach(function(plugin) {
|
||
if (plugin[cb]) {
|
||
plugin[cb](args);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* DEPRECATED
|
||
* @param {HighlightedHTMLElement} el
|
||
*/
|
||
function deprecateHighlightBlock(el) {
|
||
deprecated("10.7.0", "highlightBlock will be removed entirely in v12.0");
|
||
deprecated("10.7.0", "Please use highlightElement now.");
|
||
|
||
return highlightElement(el);
|
||
}
|
||
|
||
/* Interface definition */
|
||
Object.assign(hljs, {
|
||
highlight,
|
||
highlightAuto,
|
||
highlightAll,
|
||
highlightElement,
|
||
// TODO: Remove with v12 API
|
||
highlightBlock: deprecateHighlightBlock,
|
||
configure,
|
||
initHighlighting,
|
||
initHighlightingOnLoad,
|
||
registerLanguage,
|
||
unregisterLanguage,
|
||
listLanguages,
|
||
getLanguage,
|
||
registerAliases,
|
||
autoDetection,
|
||
inherit,
|
||
addPlugin,
|
||
removePlugin
|
||
});
|
||
|
||
hljs.debugMode = function() { SAFE_MODE = false; };
|
||
hljs.safeMode = function() { SAFE_MODE = true; };
|
||
hljs.versionString = version;
|
||
|
||
hljs.regex = {
|
||
concat: concat,
|
||
lookahead: lookahead,
|
||
either: either,
|
||
optional: optional,
|
||
anyNumberOfTimes: anyNumberOfTimes
|
||
};
|
||
|
||
for (const key in MODES) {
|
||
// @ts-ignore
|
||
if (typeof MODES[key] === "object") {
|
||
// @ts-ignore
|
||
deepFreeze(MODES[key]);
|
||
}
|
||
}
|
||
|
||
// merge all the modes/regexes into our main object
|
||
Object.assign(hljs, MODES);
|
||
|
||
return hljs;
|
||
};
|
||
|
||
// Other names for the variable may break build script
|
||
const highlight = HLJS({});
|
||
|
||
// returns a new instance of the highlighter to be used for extensions
|
||
// check https://github.com/wooorm/lowlight/issues/47
|
||
highlight.newInstance = () => HLJS({});
|
||
|
||
core = highlight;
|
||
highlight.HighlightJS = highlight;
|
||
highlight.default = highlight;
|
||
return core;
|
||
}
|
||
|
||
var coreExports = requireCore();
|
||
var HighlightJS = /*@__PURE__*/getDefaultExportFromCjs(coreExports);
|
||
|
||
/*
|
||
Language: HTML, XML
|
||
Website: https://www.w3.org/XML/
|
||
Category: common, web
|
||
Audit: 2020
|
||
*/
|
||
|
||
/** @type LanguageFn */
|
||
function xml(hljs) {
|
||
const regex = hljs.regex;
|
||
// XML names can have the following additional letters: https://www.w3.org/TR/xml/#NT-NameChar
|
||
// OTHER_NAME_CHARS = /[:\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]/;
|
||
// Element names start with NAME_START_CHAR followed by optional other Unicode letters, ASCII digits, hyphens, underscores, and periods
|
||
// const TAG_NAME_RE = regex.concat(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/, regex.optional(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*:/), /[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*/);;
|
||
// const XML_IDENT_RE = /[A-Z_a-z:\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]+/;
|
||
// const TAG_NAME_RE = regex.concat(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/, regex.optional(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*:/), /[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*/);
|
||
// however, to cater for performance and more Unicode support rely simply on the Unicode letter class
|
||
const TAG_NAME_RE = regex.concat(/[\p{L}_]/u, regex.optional(/[\p{L}0-9_.-]*:/u), /[\p{L}0-9_.-]*/u);
|
||
const XML_IDENT_RE = /[\p{L}0-9._:-]+/u;
|
||
const XML_ENTITIES = {
|
||
className: 'symbol',
|
||
begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/
|
||
};
|
||
const XML_META_KEYWORDS = {
|
||
begin: /\s/,
|
||
contains: [
|
||
{
|
||
className: 'keyword',
|
||
begin: /#?[a-z_][a-z1-9_-]+/,
|
||
illegal: /\n/
|
||
}
|
||
]
|
||
};
|
||
const XML_META_PAR_KEYWORDS = hljs.inherit(XML_META_KEYWORDS, {
|
||
begin: /\(/,
|
||
end: /\)/
|
||
});
|
||
const APOS_META_STRING_MODE = hljs.inherit(hljs.APOS_STRING_MODE, { className: 'string' });
|
||
const QUOTE_META_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, { className: 'string' });
|
||
const TAG_INTERNALS = {
|
||
endsWithParent: true,
|
||
illegal: /</,
|
||
relevance: 0,
|
||
contains: [
|
||
{
|
||
className: 'attr',
|
||
begin: XML_IDENT_RE,
|
||
relevance: 0
|
||
},
|
||
{
|
||
begin: /=\s*/,
|
||
relevance: 0,
|
||
contains: [
|
||
{
|
||
className: 'string',
|
||
endsParent: true,
|
||
variants: [
|
||
{
|
||
begin: /"/,
|
||
end: /"/,
|
||
contains: [ XML_ENTITIES ]
|
||
},
|
||
{
|
||
begin: /'/,
|
||
end: /'/,
|
||
contains: [ XML_ENTITIES ]
|
||
},
|
||
{ begin: /[^\s"'=<>`]+/ }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
};
|
||
return {
|
||
name: 'HTML, XML',
|
||
aliases: [
|
||
'html',
|
||
'xhtml',
|
||
'rss',
|
||
'atom',
|
||
'xjb',
|
||
'xsd',
|
||
'xsl',
|
||
'plist',
|
||
'wsf',
|
||
'svg'
|
||
],
|
||
case_insensitive: true,
|
||
unicodeRegex: true,
|
||
contains: [
|
||
{
|
||
className: 'meta',
|
||
begin: /<![a-z]/,
|
||
end: />/,
|
||
relevance: 10,
|
||
contains: [
|
||
XML_META_KEYWORDS,
|
||
QUOTE_META_STRING_MODE,
|
||
APOS_META_STRING_MODE,
|
||
XML_META_PAR_KEYWORDS,
|
||
{
|
||
begin: /\[/,
|
||
end: /\]/,
|
||
contains: [
|
||
{
|
||
className: 'meta',
|
||
begin: /<![a-z]/,
|
||
end: />/,
|
||
contains: [
|
||
XML_META_KEYWORDS,
|
||
XML_META_PAR_KEYWORDS,
|
||
QUOTE_META_STRING_MODE,
|
||
APOS_META_STRING_MODE
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
hljs.COMMENT(
|
||
/<!--/,
|
||
/-->/,
|
||
{ relevance: 10 }
|
||
),
|
||
{
|
||
begin: /<!\[CDATA\[/,
|
||
end: /\]\]>/,
|
||
relevance: 10
|
||
},
|
||
XML_ENTITIES,
|
||
// xml processing instructions
|
||
{
|
||
className: 'meta',
|
||
end: /\?>/,
|
||
variants: [
|
||
{
|
||
begin: /<\?xml/,
|
||
relevance: 10,
|
||
contains: [
|
||
QUOTE_META_STRING_MODE
|
||
]
|
||
},
|
||
{
|
||
begin: /<\?[a-z][a-z0-9]+/,
|
||
}
|
||
]
|
||
|
||
},
|
||
{
|
||
className: 'tag',
|
||
/*
|
||
The lookahead pattern (?=...) ensures that 'begin' only matches
|
||
'<style' as a single word, followed by a whitespace or an
|
||
ending bracket.
|
||
*/
|
||
begin: /<style(?=\s|>)/,
|
||
end: />/,
|
||
keywords: { name: 'style' },
|
||
contains: [ TAG_INTERNALS ],
|
||
starts: {
|
||
end: /<\/style>/,
|
||
returnEnd: true,
|
||
subLanguage: [
|
||
'css',
|
||
'xml'
|
||
]
|
||
}
|
||
},
|
||
{
|
||
className: 'tag',
|
||
// See the comment in the <style tag about the lookahead pattern
|
||
begin: /<script(?=\s|>)/,
|
||
end: />/,
|
||
keywords: { name: 'script' },
|
||
contains: [ TAG_INTERNALS ],
|
||
starts: {
|
||
end: /<\/script>/,
|
||
returnEnd: true,
|
||
subLanguage: [
|
||
'javascript',
|
||
'handlebars',
|
||
'xml'
|
||
]
|
||
}
|
||
},
|
||
// we need this for now for jSX
|
||
{
|
||
className: 'tag',
|
||
begin: /<>|<\/>/
|
||
},
|
||
// open tag
|
||
{
|
||
className: 'tag',
|
||
begin: regex.concat(
|
||
/</,
|
||
regex.lookahead(regex.concat(
|
||
TAG_NAME_RE,
|
||
// <tag/>
|
||
// <tag>
|
||
// <tag ...
|
||
regex.either(/\/>/, />/, /\s/)
|
||
))
|
||
),
|
||
end: /\/?>/,
|
||
contains: [
|
||
{
|
||
className: 'name',
|
||
begin: TAG_NAME_RE,
|
||
relevance: 0,
|
||
starts: TAG_INTERNALS
|
||
}
|
||
]
|
||
},
|
||
// close tag
|
||
{
|
||
className: 'tag',
|
||
begin: regex.concat(
|
||
/<\//,
|
||
regex.lookahead(regex.concat(
|
||
TAG_NAME_RE, />/
|
||
))
|
||
),
|
||
contains: [
|
||
{
|
||
className: 'name',
|
||
begin: TAG_NAME_RE,
|
||
relevance: 0
|
||
},
|
||
{
|
||
begin: />/,
|
||
relevance: 0,
|
||
endsParent: true
|
||
}
|
||
]
|
||
}
|
||
]
|
||
};
|
||
}
|
||
|
||
const MODES = (hljs) => {
|
||
return {
|
||
IMPORTANT: {
|
||
scope: 'meta',
|
||
begin: '!important'
|
||
},
|
||
BLOCK_COMMENT: hljs.C_BLOCK_COMMENT_MODE,
|
||
HEXCOLOR: {
|
||
scope: 'number',
|
||
begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/
|
||
},
|
||
FUNCTION_DISPATCH: {
|
||
className: "built_in",
|
||
begin: /[\w-]+(?=\()/
|
||
},
|
||
ATTRIBUTE_SELECTOR_MODE: {
|
||
scope: 'selector-attr',
|
||
begin: /\[/,
|
||
end: /\]/,
|
||
illegal: '$',
|
||
contains: [
|
||
hljs.APOS_STRING_MODE,
|
||
hljs.QUOTE_STRING_MODE
|
||
]
|
||
},
|
||
CSS_NUMBER_MODE: {
|
||
scope: 'number',
|
||
begin: hljs.NUMBER_RE + '(' +
|
||
'%|em|ex|ch|rem' +
|
||
'|vw|vh|vmin|vmax' +
|
||
'|cm|mm|in|pt|pc|px' +
|
||
'|deg|grad|rad|turn' +
|
||
'|s|ms' +
|
||
'|Hz|kHz' +
|
||
'|dpi|dpcm|dppx' +
|
||
')?',
|
||
relevance: 0
|
||
},
|
||
CSS_VARIABLE: {
|
||
className: "attr",
|
||
begin: /--[A-Za-z_][A-Za-z0-9_-]*/
|
||
}
|
||
};
|
||
};
|
||
|
||
const TAGS = [
|
||
'a',
|
||
'abbr',
|
||
'address',
|
||
'article',
|
||
'aside',
|
||
'audio',
|
||
'b',
|
||
'blockquote',
|
||
'body',
|
||
'button',
|
||
'canvas',
|
||
'caption',
|
||
'cite',
|
||
'code',
|
||
'dd',
|
||
'del',
|
||
'details',
|
||
'dfn',
|
||
'div',
|
||
'dl',
|
||
'dt',
|
||
'em',
|
||
'fieldset',
|
||
'figcaption',
|
||
'figure',
|
||
'footer',
|
||
'form',
|
||
'h1',
|
||
'h2',
|
||
'h3',
|
||
'h4',
|
||
'h5',
|
||
'h6',
|
||
'header',
|
||
'hgroup',
|
||
'html',
|
||
'i',
|
||
'iframe',
|
||
'img',
|
||
'input',
|
||
'ins',
|
||
'kbd',
|
||
'label',
|
||
'legend',
|
||
'li',
|
||
'main',
|
||
'mark',
|
||
'menu',
|
||
'nav',
|
||
'object',
|
||
'ol',
|
||
'p',
|
||
'q',
|
||
'quote',
|
||
'samp',
|
||
'section',
|
||
'span',
|
||
'strong',
|
||
'summary',
|
||
'sup',
|
||
'table',
|
||
'tbody',
|
||
'td',
|
||
'textarea',
|
||
'tfoot',
|
||
'th',
|
||
'thead',
|
||
'time',
|
||
'tr',
|
||
'ul',
|
||
'var',
|
||
'video'
|
||
];
|
||
|
||
const MEDIA_FEATURES = [
|
||
'any-hover',
|
||
'any-pointer',
|
||
'aspect-ratio',
|
||
'color',
|
||
'color-gamut',
|
||
'color-index',
|
||
'device-aspect-ratio',
|
||
'device-height',
|
||
'device-width',
|
||
'display-mode',
|
||
'forced-colors',
|
||
'grid',
|
||
'height',
|
||
'hover',
|
||
'inverted-colors',
|
||
'monochrome',
|
||
'orientation',
|
||
'overflow-block',
|
||
'overflow-inline',
|
||
'pointer',
|
||
'prefers-color-scheme',
|
||
'prefers-contrast',
|
||
'prefers-reduced-motion',
|
||
'prefers-reduced-transparency',
|
||
'resolution',
|
||
'scan',
|
||
'scripting',
|
||
'update',
|
||
'width',
|
||
// TODO: find a better solution?
|
||
'min-width',
|
||
'max-width',
|
||
'min-height',
|
||
'max-height'
|
||
];
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes
|
||
const PSEUDO_CLASSES = [
|
||
'active',
|
||
'any-link',
|
||
'blank',
|
||
'checked',
|
||
'current',
|
||
'default',
|
||
'defined',
|
||
'dir', // dir()
|
||
'disabled',
|
||
'drop',
|
||
'empty',
|
||
'enabled',
|
||
'first',
|
||
'first-child',
|
||
'first-of-type',
|
||
'fullscreen',
|
||
'future',
|
||
'focus',
|
||
'focus-visible',
|
||
'focus-within',
|
||
'has', // has()
|
||
'host', // host or host()
|
||
'host-context', // host-context()
|
||
'hover',
|
||
'indeterminate',
|
||
'in-range',
|
||
'invalid',
|
||
'is', // is()
|
||
'lang', // lang()
|
||
'last-child',
|
||
'last-of-type',
|
||
'left',
|
||
'link',
|
||
'local-link',
|
||
'not', // not()
|
||
'nth-child', // nth-child()
|
||
'nth-col', // nth-col()
|
||
'nth-last-child', // nth-last-child()
|
||
'nth-last-col', // nth-last-col()
|
||
'nth-last-of-type', //nth-last-of-type()
|
||
'nth-of-type', //nth-of-type()
|
||
'only-child',
|
||
'only-of-type',
|
||
'optional',
|
||
'out-of-range',
|
||
'past',
|
||
'placeholder-shown',
|
||
'read-only',
|
||
'read-write',
|
||
'required',
|
||
'right',
|
||
'root',
|
||
'scope',
|
||
'target',
|
||
'target-within',
|
||
'user-invalid',
|
||
'valid',
|
||
'visited',
|
||
'where' // where()
|
||
];
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
|
||
const PSEUDO_ELEMENTS = [
|
||
'after',
|
||
'backdrop',
|
||
'before',
|
||
'cue',
|
||
'cue-region',
|
||
'first-letter',
|
||
'first-line',
|
||
'grammar-error',
|
||
'marker',
|
||
'part',
|
||
'placeholder',
|
||
'selection',
|
||
'slotted',
|
||
'spelling-error'
|
||
];
|
||
|
||
const ATTRIBUTES = [
|
||
'align-content',
|
||
'align-items',
|
||
'align-self',
|
||
'all',
|
||
'animation',
|
||
'animation-delay',
|
||
'animation-direction',
|
||
'animation-duration',
|
||
'animation-fill-mode',
|
||
'animation-iteration-count',
|
||
'animation-name',
|
||
'animation-play-state',
|
||
'animation-timing-function',
|
||
'backface-visibility',
|
||
'background',
|
||
'background-attachment',
|
||
'background-blend-mode',
|
||
'background-clip',
|
||
'background-color',
|
||
'background-image',
|
||
'background-origin',
|
||
'background-position',
|
||
'background-repeat',
|
||
'background-size',
|
||
'block-size',
|
||
'border',
|
||
'border-block',
|
||
'border-block-color',
|
||
'border-block-end',
|
||
'border-block-end-color',
|
||
'border-block-end-style',
|
||
'border-block-end-width',
|
||
'border-block-start',
|
||
'border-block-start-color',
|
||
'border-block-start-style',
|
||
'border-block-start-width',
|
||
'border-block-style',
|
||
'border-block-width',
|
||
'border-bottom',
|
||
'border-bottom-color',
|
||
'border-bottom-left-radius',
|
||
'border-bottom-right-radius',
|
||
'border-bottom-style',
|
||
'border-bottom-width',
|
||
'border-collapse',
|
||
'border-color',
|
||
'border-image',
|
||
'border-image-outset',
|
||
'border-image-repeat',
|
||
'border-image-slice',
|
||
'border-image-source',
|
||
'border-image-width',
|
||
'border-inline',
|
||
'border-inline-color',
|
||
'border-inline-end',
|
||
'border-inline-end-color',
|
||
'border-inline-end-style',
|
||
'border-inline-end-width',
|
||
'border-inline-start',
|
||
'border-inline-start-color',
|
||
'border-inline-start-style',
|
||
'border-inline-start-width',
|
||
'border-inline-style',
|
||
'border-inline-width',
|
||
'border-left',
|
||
'border-left-color',
|
||
'border-left-style',
|
||
'border-left-width',
|
||
'border-radius',
|
||
'border-right',
|
||
'border-right-color',
|
||
'border-right-style',
|
||
'border-right-width',
|
||
'border-spacing',
|
||
'border-style',
|
||
'border-top',
|
||
'border-top-color',
|
||
'border-top-left-radius',
|
||
'border-top-right-radius',
|
||
'border-top-style',
|
||
'border-top-width',
|
||
'border-width',
|
||
'bottom',
|
||
'box-decoration-break',
|
||
'box-shadow',
|
||
'box-sizing',
|
||
'break-after',
|
||
'break-before',
|
||
'break-inside',
|
||
'caption-side',
|
||
'caret-color',
|
||
'clear',
|
||
'clip',
|
||
'clip-path',
|
||
'clip-rule',
|
||
'color',
|
||
'column-count',
|
||
'column-fill',
|
||
'column-gap',
|
||
'column-rule',
|
||
'column-rule-color',
|
||
'column-rule-style',
|
||
'column-rule-width',
|
||
'column-span',
|
||
'column-width',
|
||
'columns',
|
||
'contain',
|
||
'content',
|
||
'content-visibility',
|
||
'counter-increment',
|
||
'counter-reset',
|
||
'cue',
|
||
'cue-after',
|
||
'cue-before',
|
||
'cursor',
|
||
'direction',
|
||
'display',
|
||
'empty-cells',
|
||
'filter',
|
||
'flex',
|
||
'flex-basis',
|
||
'flex-direction',
|
||
'flex-flow',
|
||
'flex-grow',
|
||
'flex-shrink',
|
||
'flex-wrap',
|
||
'float',
|
||
'flow',
|
||
'font',
|
||
'font-display',
|
||
'font-family',
|
||
'font-feature-settings',
|
||
'font-kerning',
|
||
'font-language-override',
|
||
'font-size',
|
||
'font-size-adjust',
|
||
'font-smoothing',
|
||
'font-stretch',
|
||
'font-style',
|
||
'font-synthesis',
|
||
'font-variant',
|
||
'font-variant-caps',
|
||
'font-variant-east-asian',
|
||
'font-variant-ligatures',
|
||
'font-variant-numeric',
|
||
'font-variant-position',
|
||
'font-variation-settings',
|
||
'font-weight',
|
||
'gap',
|
||
'glyph-orientation-vertical',
|
||
'grid',
|
||
'grid-area',
|
||
'grid-auto-columns',
|
||
'grid-auto-flow',
|
||
'grid-auto-rows',
|
||
'grid-column',
|
||
'grid-column-end',
|
||
'grid-column-start',
|
||
'grid-gap',
|
||
'grid-row',
|
||
'grid-row-end',
|
||
'grid-row-start',
|
||
'grid-template',
|
||
'grid-template-areas',
|
||
'grid-template-columns',
|
||
'grid-template-rows',
|
||
'hanging-punctuation',
|
||
'height',
|
||
'hyphens',
|
||
'icon',
|
||
'image-orientation',
|
||
'image-rendering',
|
||
'image-resolution',
|
||
'ime-mode',
|
||
'inline-size',
|
||
'isolation',
|
||
'justify-content',
|
||
'left',
|
||
'letter-spacing',
|
||
'line-break',
|
||
'line-height',
|
||
'list-style',
|
||
'list-style-image',
|
||
'list-style-position',
|
||
'list-style-type',
|
||
'margin',
|
||
'margin-block',
|
||
'margin-block-end',
|
||
'margin-block-start',
|
||
'margin-bottom',
|
||
'margin-inline',
|
||
'margin-inline-end',
|
||
'margin-inline-start',
|
||
'margin-left',
|
||
'margin-right',
|
||
'margin-top',
|
||
'marks',
|
||
'mask',
|
||
'mask-border',
|
||
'mask-border-mode',
|
||
'mask-border-outset',
|
||
'mask-border-repeat',
|
||
'mask-border-slice',
|
||
'mask-border-source',
|
||
'mask-border-width',
|
||
'mask-clip',
|
||
'mask-composite',
|
||
'mask-image',
|
||
'mask-mode',
|
||
'mask-origin',
|
||
'mask-position',
|
||
'mask-repeat',
|
||
'mask-size',
|
||
'mask-type',
|
||
'max-block-size',
|
||
'max-height',
|
||
'max-inline-size',
|
||
'max-width',
|
||
'min-block-size',
|
||
'min-height',
|
||
'min-inline-size',
|
||
'min-width',
|
||
'mix-blend-mode',
|
||
'nav-down',
|
||
'nav-index',
|
||
'nav-left',
|
||
'nav-right',
|
||
'nav-up',
|
||
'none',
|
||
'normal',
|
||
'object-fit',
|
||
'object-position',
|
||
'opacity',
|
||
'order',
|
||
'orphans',
|
||
'outline',
|
||
'outline-color',
|
||
'outline-offset',
|
||
'outline-style',
|
||
'outline-width',
|
||
'overflow',
|
||
'overflow-wrap',
|
||
'overflow-x',
|
||
'overflow-y',
|
||
'padding',
|
||
'padding-block',
|
||
'padding-block-end',
|
||
'padding-block-start',
|
||
'padding-bottom',
|
||
'padding-inline',
|
||
'padding-inline-end',
|
||
'padding-inline-start',
|
||
'padding-left',
|
||
'padding-right',
|
||
'padding-top',
|
||
'page-break-after',
|
||
'page-break-before',
|
||
'page-break-inside',
|
||
'pause',
|
||
'pause-after',
|
||
'pause-before',
|
||
'perspective',
|
||
'perspective-origin',
|
||
'pointer-events',
|
||
'position',
|
||
'quotes',
|
||
'resize',
|
||
'rest',
|
||
'rest-after',
|
||
'rest-before',
|
||
'right',
|
||
'row-gap',
|
||
'scroll-margin',
|
||
'scroll-margin-block',
|
||
'scroll-margin-block-end',
|
||
'scroll-margin-block-start',
|
||
'scroll-margin-bottom',
|
||
'scroll-margin-inline',
|
||
'scroll-margin-inline-end',
|
||
'scroll-margin-inline-start',
|
||
'scroll-margin-left',
|
||
'scroll-margin-right',
|
||
'scroll-margin-top',
|
||
'scroll-padding',
|
||
'scroll-padding-block',
|
||
'scroll-padding-block-end',
|
||
'scroll-padding-block-start',
|
||
'scroll-padding-bottom',
|
||
'scroll-padding-inline',
|
||
'scroll-padding-inline-end',
|
||
'scroll-padding-inline-start',
|
||
'scroll-padding-left',
|
||
'scroll-padding-right',
|
||
'scroll-padding-top',
|
||
'scroll-snap-align',
|
||
'scroll-snap-stop',
|
||
'scroll-snap-type',
|
||
'scrollbar-color',
|
||
'scrollbar-gutter',
|
||
'scrollbar-width',
|
||
'shape-image-threshold',
|
||
'shape-margin',
|
||
'shape-outside',
|
||
'speak',
|
||
'speak-as',
|
||
'src', // @font-face
|
||
'tab-size',
|
||
'table-layout',
|
||
'text-align',
|
||
'text-align-all',
|
||
'text-align-last',
|
||
'text-combine-upright',
|
||
'text-decoration',
|
||
'text-decoration-color',
|
||
'text-decoration-line',
|
||
'text-decoration-style',
|
||
'text-emphasis',
|
||
'text-emphasis-color',
|
||
'text-emphasis-position',
|
||
'text-emphasis-style',
|
||
'text-indent',
|
||
'text-justify',
|
||
'text-orientation',
|
||
'text-overflow',
|
||
'text-rendering',
|
||
'text-shadow',
|
||
'text-transform',
|
||
'text-underline-position',
|
||
'top',
|
||
'transform',
|
||
'transform-box',
|
||
'transform-origin',
|
||
'transform-style',
|
||
'transition',
|
||
'transition-delay',
|
||
'transition-duration',
|
||
'transition-property',
|
||
'transition-timing-function',
|
||
'unicode-bidi',
|
||
'vertical-align',
|
||
'visibility',
|
||
'voice-balance',
|
||
'voice-duration',
|
||
'voice-family',
|
||
'voice-pitch',
|
||
'voice-range',
|
||
'voice-rate',
|
||
'voice-stress',
|
||
'voice-volume',
|
||
'white-space',
|
||
'widows',
|
||
'width',
|
||
'will-change',
|
||
'word-break',
|
||
'word-spacing',
|
||
'word-wrap',
|
||
'writing-mode',
|
||
'z-index'
|
||
// reverse makes sure longer attributes `font-weight` are matched fully
|
||
// instead of getting false positives on say `font`
|
||
].reverse();
|
||
|
||
/*
|
||
Language: CSS
|
||
Category: common, css, web
|
||
Website: https://developer.mozilla.org/en-US/docs/Web/CSS
|
||
*/
|
||
|
||
|
||
/** @type LanguageFn */
|
||
function css(hljs) {
|
||
const regex = hljs.regex;
|
||
const modes = MODES(hljs);
|
||
const VENDOR_PREFIX = { begin: /-(webkit|moz|ms|o)-(?=[a-z])/ };
|
||
const AT_MODIFIERS = "and or not only";
|
||
const AT_PROPERTY_RE = /@-?\w[\w]*(-\w+)*/; // @-webkit-keyframes
|
||
const IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*';
|
||
const STRINGS = [
|
||
hljs.APOS_STRING_MODE,
|
||
hljs.QUOTE_STRING_MODE
|
||
];
|
||
|
||
return {
|
||
name: 'CSS',
|
||
case_insensitive: true,
|
||
illegal: /[=|'\$]/,
|
||
keywords: { keyframePosition: "from to" },
|
||
classNameAliases: {
|
||
// for visual continuity with `tag {}` and because we
|
||
// don't have a great class for this?
|
||
keyframePosition: "selector-tag" },
|
||
contains: [
|
||
modes.BLOCK_COMMENT,
|
||
VENDOR_PREFIX,
|
||
// to recognize keyframe 40% etc which are outside the scope of our
|
||
// attribute value mode
|
||
modes.CSS_NUMBER_MODE,
|
||
{
|
||
className: 'selector-id',
|
||
begin: /#[A-Za-z0-9_-]+/,
|
||
relevance: 0
|
||
},
|
||
{
|
||
className: 'selector-class',
|
||
begin: '\\.' + IDENT_RE,
|
||
relevance: 0
|
||
},
|
||
modes.ATTRIBUTE_SELECTOR_MODE,
|
||
{
|
||
className: 'selector-pseudo',
|
||
variants: [
|
||
{ begin: ':(' + PSEUDO_CLASSES.join('|') + ')' },
|
||
{ begin: ':(:)?(' + PSEUDO_ELEMENTS.join('|') + ')' }
|
||
]
|
||
},
|
||
// we may actually need this (12/2020)
|
||
// { // pseudo-selector params
|
||
// begin: /\(/,
|
||
// end: /\)/,
|
||
// contains: [ hljs.CSS_NUMBER_MODE ]
|
||
// },
|
||
modes.CSS_VARIABLE,
|
||
{
|
||
className: 'attribute',
|
||
begin: '\\b(' + ATTRIBUTES.join('|') + ')\\b'
|
||
},
|
||
// attribute values
|
||
{
|
||
begin: /:/,
|
||
end: /[;}{]/,
|
||
contains: [
|
||
modes.BLOCK_COMMENT,
|
||
modes.HEXCOLOR,
|
||
modes.IMPORTANT,
|
||
modes.CSS_NUMBER_MODE,
|
||
...STRINGS,
|
||
// needed to highlight these as strings and to avoid issues with
|
||
// illegal characters that might be inside urls that would tigger the
|
||
// languages illegal stack
|
||
{
|
||
begin: /(url|data-uri)\(/,
|
||
end: /\)/,
|
||
relevance: 0, // from keywords
|
||
keywords: { built_in: "url data-uri" },
|
||
contains: [
|
||
...STRINGS,
|
||
{
|
||
className: "string",
|
||
// any character other than `)` as in `url()` will be the start
|
||
// of a string, which ends with `)` (from the parent mode)
|
||
begin: /[^)]/,
|
||
endsWithParent: true,
|
||
excludeEnd: true
|
||
}
|
||
]
|
||
},
|
||
modes.FUNCTION_DISPATCH
|
||
]
|
||
},
|
||
{
|
||
begin: regex.lookahead(/@/),
|
||
end: '[{;]',
|
||
relevance: 0,
|
||
illegal: /:/, // break on Less variables @var: ...
|
||
contains: [
|
||
{
|
||
className: 'keyword',
|
||
begin: AT_PROPERTY_RE
|
||
},
|
||
{
|
||
begin: /\s/,
|
||
endsWithParent: true,
|
||
excludeEnd: true,
|
||
relevance: 0,
|
||
keywords: {
|
||
$pattern: /[a-z-]+/,
|
||
keyword: AT_MODIFIERS,
|
||
attribute: MEDIA_FEATURES.join(" ")
|
||
},
|
||
contains: [
|
||
{
|
||
begin: /[a-z-]+(?=:)/,
|
||
className: "attribute"
|
||
},
|
||
...STRINGS,
|
||
modes.CSS_NUMBER_MODE
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
className: 'selector-tag',
|
||
begin: '\\b(' + TAGS.join('|') + ')\\b'
|
||
}
|
||
]
|
||
};
|
||
}
|
||
|
||
/*
|
||
Language: JSON
|
||
Description: JSON (JavaScript Object Notation) is a lightweight data-interchange format.
|
||
Author: Ivan Sagalaev <maniac@softwaremaniacs.org>
|
||
Website: http://www.json.org
|
||
Category: common, protocols, web
|
||
*/
|
||
|
||
function json(hljs) {
|
||
const ATTRIBUTE = {
|
||
className: 'attr',
|
||
begin: /"(\\.|[^\\"\r\n])*"(?=\s*:)/,
|
||
relevance: 1.01
|
||
};
|
||
const PUNCTUATION = {
|
||
match: /[{}[\],:]/,
|
||
className: "punctuation",
|
||
relevance: 0
|
||
};
|
||
const LITERALS = [
|
||
"true",
|
||
"false",
|
||
"null"
|
||
];
|
||
// NOTE: normally we would rely on `keywords` for this but using a mode here allows us
|
||
// - to use the very tight `illegal: \S` rule later to flag any other character
|
||
// - as illegal indicating that despite looking like JSON we do not truly have
|
||
// - JSON and thus improve false-positively greatly since JSON will try and claim
|
||
// - all sorts of JSON looking stuff
|
||
const LITERALS_MODE = {
|
||
scope: "literal",
|
||
beginKeywords: LITERALS.join(" "),
|
||
};
|
||
|
||
return {
|
||
name: 'JSON',
|
||
keywords:{
|
||
literal: LITERALS,
|
||
},
|
||
contains: [
|
||
ATTRIBUTE,
|
||
PUNCTUATION,
|
||
hljs.QUOTE_STRING_MODE,
|
||
LITERALS_MODE,
|
||
hljs.C_NUMBER_MODE,
|
||
hljs.C_LINE_COMMENT_MODE,
|
||
hljs.C_BLOCK_COMMENT_MODE
|
||
],
|
||
illegal: '\\S'
|
||
};
|
||
}
|
||
|
||
const IDENT_RE$1 = '[A-Za-z$_][0-9A-Za-z$_]*';
|
||
const KEYWORDS$1 = [
|
||
"as", // for exports
|
||
"in",
|
||
"of",
|
||
"if",
|
||
"for",
|
||
"while",
|
||
"finally",
|
||
"var",
|
||
"new",
|
||
"function",
|
||
"do",
|
||
"return",
|
||
"void",
|
||
"else",
|
||
"break",
|
||
"catch",
|
||
"instanceof",
|
||
"with",
|
||
"throw",
|
||
"case",
|
||
"default",
|
||
"try",
|
||
"switch",
|
||
"continue",
|
||
"typeof",
|
||
"delete",
|
||
"let",
|
||
"yield",
|
||
"const",
|
||
"class",
|
||
// JS handles these with a special rule
|
||
// "get",
|
||
// "set",
|
||
"debugger",
|
||
"async",
|
||
"await",
|
||
"static",
|
||
"import",
|
||
"from",
|
||
"export",
|
||
"extends"
|
||
];
|
||
const LITERALS$1 = [
|
||
"true",
|
||
"false",
|
||
"null",
|
||
"undefined",
|
||
"NaN",
|
||
"Infinity"
|
||
];
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
|
||
const TYPES$1 = [
|
||
// Fundamental objects
|
||
"Object",
|
||
"Function",
|
||
"Boolean",
|
||
"Symbol",
|
||
// numbers and dates
|
||
"Math",
|
||
"Date",
|
||
"Number",
|
||
"BigInt",
|
||
// text
|
||
"String",
|
||
"RegExp",
|
||
// Indexed collections
|
||
"Array",
|
||
"Float32Array",
|
||
"Float64Array",
|
||
"Int8Array",
|
||
"Uint8Array",
|
||
"Uint8ClampedArray",
|
||
"Int16Array",
|
||
"Int32Array",
|
||
"Uint16Array",
|
||
"Uint32Array",
|
||
"BigInt64Array",
|
||
"BigUint64Array",
|
||
// Keyed collections
|
||
"Set",
|
||
"Map",
|
||
"WeakSet",
|
||
"WeakMap",
|
||
// Structured data
|
||
"ArrayBuffer",
|
||
"SharedArrayBuffer",
|
||
"Atomics",
|
||
"DataView",
|
||
"JSON",
|
||
// Control abstraction objects
|
||
"Promise",
|
||
"Generator",
|
||
"GeneratorFunction",
|
||
"AsyncFunction",
|
||
// Reflection
|
||
"Reflect",
|
||
"Proxy",
|
||
// Internationalization
|
||
"Intl",
|
||
// WebAssembly
|
||
"WebAssembly"
|
||
];
|
||
|
||
const ERROR_TYPES$1 = [
|
||
"Error",
|
||
"EvalError",
|
||
"InternalError",
|
||
"RangeError",
|
||
"ReferenceError",
|
||
"SyntaxError",
|
||
"TypeError",
|
||
"URIError"
|
||
];
|
||
|
||
const BUILT_IN_GLOBALS$1 = [
|
||
"setInterval",
|
||
"setTimeout",
|
||
"clearInterval",
|
||
"clearTimeout",
|
||
|
||
"require",
|
||
"exports",
|
||
|
||
"eval",
|
||
"isFinite",
|
||
"isNaN",
|
||
"parseFloat",
|
||
"parseInt",
|
||
"decodeURI",
|
||
"decodeURIComponent",
|
||
"encodeURI",
|
||
"encodeURIComponent",
|
||
"escape",
|
||
"unescape"
|
||
];
|
||
|
||
const BUILT_IN_VARIABLES$1 = [
|
||
"arguments",
|
||
"this",
|
||
"super",
|
||
"console",
|
||
"window",
|
||
"document",
|
||
"localStorage",
|
||
"sessionStorage",
|
||
"module",
|
||
"global" // Node.js
|
||
];
|
||
|
||
const BUILT_INS$1 = [].concat(
|
||
BUILT_IN_GLOBALS$1,
|
||
TYPES$1,
|
||
ERROR_TYPES$1
|
||
);
|
||
|
||
/*
|
||
Language: JavaScript
|
||
Description: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.
|
||
Category: common, scripting, web
|
||
Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
|
||
*/
|
||
|
||
|
||
/** @type LanguageFn */
|
||
function javascript$1(hljs) {
|
||
const regex = hljs.regex;
|
||
/**
|
||
* Takes a string like "<Booger" and checks to see
|
||
* if we can find a matching "</Booger" later in the
|
||
* content.
|
||
* @param {RegExpMatchArray} match
|
||
* @param {{after:number}} param1
|
||
*/
|
||
const hasClosingTag = (match, { after }) => {
|
||
const tag = "</" + match[0].slice(1);
|
||
const pos = match.input.indexOf(tag, after);
|
||
return pos !== -1;
|
||
};
|
||
|
||
const IDENT_RE$1$1 = IDENT_RE$1;
|
||
const FRAGMENT = {
|
||
begin: '<>',
|
||
end: '</>'
|
||
};
|
||
// to avoid some special cases inside isTrulyOpeningTag
|
||
const XML_SELF_CLOSING = /<[A-Za-z0-9\\._:-]+\s*\/>/;
|
||
const XML_TAG = {
|
||
begin: /<[A-Za-z0-9\\._:-]+/,
|
||
end: /\/[A-Za-z0-9\\._:-]+>|\/>/,
|
||
/**
|
||
* @param {RegExpMatchArray} match
|
||
* @param {CallbackResponse} response
|
||
*/
|
||
isTrulyOpeningTag: (match, response) => {
|
||
const afterMatchIndex = match[0].length + match.index;
|
||
const nextChar = match.input[afterMatchIndex];
|
||
if (
|
||
// HTML should not include another raw `<` inside a tag
|
||
// nested type?
|
||
// `<Array<Array<number>>`, etc.
|
||
nextChar === "<" ||
|
||
// the , gives away that this is not HTML
|
||
// `<T, A extends keyof T, V>`
|
||
nextChar === ","
|
||
) {
|
||
response.ignoreMatch();
|
||
return;
|
||
}
|
||
|
||
// `<something>`
|
||
// Quite possibly a tag, lets look for a matching closing tag...
|
||
if (nextChar === ">") {
|
||
// if we cannot find a matching closing tag, then we
|
||
// will ignore it
|
||
if (!hasClosingTag(match, { after: afterMatchIndex })) {
|
||
response.ignoreMatch();
|
||
}
|
||
}
|
||
|
||
// `<blah />` (self-closing)
|
||
// handled by simpleSelfClosing rule
|
||
|
||
let m;
|
||
const afterMatch = match.input.substring(afterMatchIndex);
|
||
|
||
// some more template typing stuff
|
||
// <T = any>(key?: string) => Modify<
|
||
if ((m = afterMatch.match(/^\s*=/))) {
|
||
response.ignoreMatch();
|
||
return;
|
||
}
|
||
|
||
// `<From extends string>`
|
||
// technically this could be HTML, but it smells like a type
|
||
// NOTE: This is ugh, but added specifically for https://github.com/highlightjs/highlight.js/issues/3276
|
||
if ((m = afterMatch.match(/^\s+extends\s+/))) {
|
||
if (m.index === 0) {
|
||
response.ignoreMatch();
|
||
// eslint-disable-next-line no-useless-return
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
const KEYWORDS$1$1 = {
|
||
$pattern: IDENT_RE$1,
|
||
keyword: KEYWORDS$1,
|
||
literal: LITERALS$1,
|
||
built_in: BUILT_INS$1,
|
||
"variable.language": BUILT_IN_VARIABLES$1
|
||
};
|
||
|
||
// https://tc39.es/ecma262/#sec-literals-numeric-literals
|
||
const decimalDigits = '[0-9](_?[0-9])*';
|
||
const frac = `\\.(${decimalDigits})`;
|
||
// DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral
|
||
// https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
|
||
const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`;
|
||
const NUMBER = {
|
||
className: 'number',
|
||
variants: [
|
||
// DecimalLiteral
|
||
{ begin: `(\\b(${decimalInteger})((${frac})|\\.)?|(${frac}))` +
|
||
`[eE][+-]?(${decimalDigits})\\b` },
|
||
{ begin: `\\b(${decimalInteger})\\b((${frac})\\b|\\.)?|(${frac})\\b` },
|
||
|
||
// DecimalBigIntegerLiteral
|
||
{ begin: `\\b(0|[1-9](_?[0-9])*)n\\b` },
|
||
|
||
// NonDecimalIntegerLiteral
|
||
{ begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b" },
|
||
{ begin: "\\b0[bB][0-1](_?[0-1])*n?\\b" },
|
||
{ begin: "\\b0[oO][0-7](_?[0-7])*n?\\b" },
|
||
|
||
// LegacyOctalIntegerLiteral (does not include underscore separators)
|
||
// https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
|
||
{ begin: "\\b0[0-7]+n?\\b" },
|
||
],
|
||
relevance: 0
|
||
};
|
||
|
||
const SUBST = {
|
||
className: 'subst',
|
||
begin: '\\$\\{',
|
||
end: '\\}',
|
||
keywords: KEYWORDS$1$1,
|
||
contains: [] // defined later
|
||
};
|
||
const HTML_TEMPLATE = {
|
||
begin: 'html`',
|
||
end: '',
|
||
starts: {
|
||
end: '`',
|
||
returnEnd: false,
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
],
|
||
subLanguage: 'xml'
|
||
}
|
||
};
|
||
const CSS_TEMPLATE = {
|
||
begin: 'css`',
|
||
end: '',
|
||
starts: {
|
||
end: '`',
|
||
returnEnd: false,
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
],
|
||
subLanguage: 'css'
|
||
}
|
||
};
|
||
const GRAPHQL_TEMPLATE = {
|
||
begin: 'gql`',
|
||
end: '',
|
||
starts: {
|
||
end: '`',
|
||
returnEnd: false,
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
],
|
||
subLanguage: 'graphql'
|
||
}
|
||
};
|
||
const TEMPLATE_STRING = {
|
||
className: 'string',
|
||
begin: '`',
|
||
end: '`',
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
]
|
||
};
|
||
const JSDOC_COMMENT = hljs.COMMENT(
|
||
/\/\*\*(?!\/)/,
|
||
'\\*/',
|
||
{
|
||
relevance: 0,
|
||
contains: [
|
||
{
|
||
begin: '(?=@[A-Za-z]+)',
|
||
relevance: 0,
|
||
contains: [
|
||
{
|
||
className: 'doctag',
|
||
begin: '@[A-Za-z]+'
|
||
},
|
||
{
|
||
className: 'type',
|
||
begin: '\\{',
|
||
end: '\\}',
|
||
excludeEnd: true,
|
||
excludeBegin: true,
|
||
relevance: 0
|
||
},
|
||
{
|
||
className: 'variable',
|
||
begin: IDENT_RE$1$1 + '(?=\\s*(-)|$)',
|
||
endsParent: true,
|
||
relevance: 0
|
||
},
|
||
// eat spaces (not newlines) so we can find
|
||
// types or variables
|
||
{
|
||
begin: /(?=[^\n])\s/,
|
||
relevance: 0
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
);
|
||
const COMMENT = {
|
||
className: "comment",
|
||
variants: [
|
||
JSDOC_COMMENT,
|
||
hljs.C_BLOCK_COMMENT_MODE,
|
||
hljs.C_LINE_COMMENT_MODE
|
||
]
|
||
};
|
||
const SUBST_INTERNALS = [
|
||
hljs.APOS_STRING_MODE,
|
||
hljs.QUOTE_STRING_MODE,
|
||
HTML_TEMPLATE,
|
||
CSS_TEMPLATE,
|
||
GRAPHQL_TEMPLATE,
|
||
TEMPLATE_STRING,
|
||
// Skip numbers when they are part of a variable name
|
||
{ match: /\$\d+/ },
|
||
NUMBER,
|
||
// This is intentional:
|
||
// See https://github.com/highlightjs/highlight.js/issues/3288
|
||
// hljs.REGEXP_MODE
|
||
];
|
||
SUBST.contains = SUBST_INTERNALS
|
||
.concat({
|
||
// we need to pair up {} inside our subst to prevent
|
||
// it from ending too early by matching another }
|
||
begin: /\{/,
|
||
end: /\}/,
|
||
keywords: KEYWORDS$1$1,
|
||
contains: [
|
||
"self"
|
||
].concat(SUBST_INTERNALS)
|
||
});
|
||
const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains);
|
||
const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([
|
||
// eat recursive parens in sub expressions
|
||
{
|
||
begin: /\(/,
|
||
end: /\)/,
|
||
keywords: KEYWORDS$1$1,
|
||
contains: ["self"].concat(SUBST_AND_COMMENTS)
|
||
}
|
||
]);
|
||
const PARAMS = {
|
||
className: 'params',
|
||
begin: /\(/,
|
||
end: /\)/,
|
||
excludeBegin: true,
|
||
excludeEnd: true,
|
||
keywords: KEYWORDS$1$1,
|
||
contains: PARAMS_CONTAINS
|
||
};
|
||
|
||
// ES6 classes
|
||
const CLASS_OR_EXTENDS = {
|
||
variants: [
|
||
// class Car extends vehicle
|
||
{
|
||
match: [
|
||
/class/,
|
||
/\s+/,
|
||
IDENT_RE$1$1,
|
||
/\s+/,
|
||
/extends/,
|
||
/\s+/,
|
||
regex.concat(IDENT_RE$1$1, "(", regex.concat(/\./, IDENT_RE$1$1), ")*")
|
||
],
|
||
scope: {
|
||
1: "keyword",
|
||
3: "title.class",
|
||
5: "keyword",
|
||
7: "title.class.inherited"
|
||
}
|
||
},
|
||
// class Car
|
||
{
|
||
match: [
|
||
/class/,
|
||
/\s+/,
|
||
IDENT_RE$1$1
|
||
],
|
||
scope: {
|
||
1: "keyword",
|
||
3: "title.class"
|
||
}
|
||
},
|
||
|
||
]
|
||
};
|
||
|
||
const CLASS_REFERENCE = {
|
||
relevance: 0,
|
||
match:
|
||
regex.either(
|
||
// Hard coded exceptions
|
||
/\bJSON/,
|
||
// Float32Array, OutT
|
||
/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,
|
||
// CSSFactory, CSSFactoryT
|
||
/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,
|
||
// FPs, FPsT
|
||
/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/,
|
||
// P
|
||
// single letters are not highlighted
|
||
// BLAH
|
||
// this will be flagged as a UPPER_CASE_CONSTANT instead
|
||
),
|
||
className: "title.class",
|
||
keywords: {
|
||
_: [
|
||
// se we still get relevance credit for JS library classes
|
||
...TYPES$1,
|
||
...ERROR_TYPES$1
|
||
]
|
||
}
|
||
};
|
||
|
||
const USE_STRICT = {
|
||
label: "use_strict",
|
||
className: 'meta',
|
||
relevance: 10,
|
||
begin: /^\s*['"]use (strict|asm)['"]/
|
||
};
|
||
|
||
const FUNCTION_DEFINITION = {
|
||
variants: [
|
||
{
|
||
match: [
|
||
/function/,
|
||
/\s+/,
|
||
IDENT_RE$1$1,
|
||
/(?=\s*\()/
|
||
]
|
||
},
|
||
// anonymous function
|
||
{
|
||
match: [
|
||
/function/,
|
||
/\s*(?=\()/
|
||
]
|
||
}
|
||
],
|
||
className: {
|
||
1: "keyword",
|
||
3: "title.function"
|
||
},
|
||
label: "func.def",
|
||
contains: [ PARAMS ],
|
||
illegal: /%/
|
||
};
|
||
|
||
const UPPER_CASE_CONSTANT = {
|
||
relevance: 0,
|
||
match: /\b[A-Z][A-Z_0-9]+\b/,
|
||
className: "variable.constant"
|
||
};
|
||
|
||
function noneOf(list) {
|
||
return regex.concat("(?!", list.join("|"), ")");
|
||
}
|
||
|
||
const FUNCTION_CALL = {
|
||
match: regex.concat(
|
||
/\b/,
|
||
noneOf([
|
||
...BUILT_IN_GLOBALS$1,
|
||
"super",
|
||
"import"
|
||
]),
|
||
IDENT_RE$1$1, regex.lookahead(/\(/)),
|
||
className: "title.function",
|
||
relevance: 0
|
||
};
|
||
|
||
const PROPERTY_ACCESS = {
|
||
begin: regex.concat(/\./, regex.lookahead(
|
||
regex.concat(IDENT_RE$1$1, /(?![0-9A-Za-z$_(])/)
|
||
)),
|
||
end: IDENT_RE$1$1,
|
||
excludeBegin: true,
|
||
keywords: "prototype",
|
||
className: "property",
|
||
relevance: 0
|
||
};
|
||
|
||
const GETTER_OR_SETTER = {
|
||
match: [
|
||
/get|set/,
|
||
/\s+/,
|
||
IDENT_RE$1$1,
|
||
/(?=\()/
|
||
],
|
||
className: {
|
||
1: "keyword",
|
||
3: "title.function"
|
||
},
|
||
contains: [
|
||
{ // eat to avoid empty params
|
||
begin: /\(\)/
|
||
},
|
||
PARAMS
|
||
]
|
||
};
|
||
|
||
const FUNC_LEAD_IN_RE = '(\\(' +
|
||
'[^()]*(\\(' +
|
||
'[^()]*(\\(' +
|
||
'[^()]*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\s*=>';
|
||
|
||
const FUNCTION_VARIABLE = {
|
||
match: [
|
||
/const|var|let/, /\s+/,
|
||
IDENT_RE$1$1, /\s*/,
|
||
/=\s*/,
|
||
/(async\s*)?/, // async is optional
|
||
regex.lookahead(FUNC_LEAD_IN_RE)
|
||
],
|
||
keywords: "async",
|
||
className: {
|
||
1: "keyword",
|
||
3: "title.function"
|
||
},
|
||
contains: [
|
||
PARAMS
|
||
]
|
||
};
|
||
|
||
return {
|
||
name: 'JavaScript',
|
||
aliases: ['js', 'jsx', 'mjs', 'cjs'],
|
||
keywords: KEYWORDS$1$1,
|
||
// this will be extended by TypeScript
|
||
exports: { PARAMS_CONTAINS, CLASS_REFERENCE },
|
||
illegal: /#(?![$_A-z])/,
|
||
contains: [
|
||
hljs.SHEBANG({
|
||
label: "shebang",
|
||
binary: "node",
|
||
relevance: 5
|
||
}),
|
||
USE_STRICT,
|
||
hljs.APOS_STRING_MODE,
|
||
hljs.QUOTE_STRING_MODE,
|
||
HTML_TEMPLATE,
|
||
CSS_TEMPLATE,
|
||
GRAPHQL_TEMPLATE,
|
||
TEMPLATE_STRING,
|
||
COMMENT,
|
||
// Skip numbers when they are part of a variable name
|
||
{ match: /\$\d+/ },
|
||
NUMBER,
|
||
CLASS_REFERENCE,
|
||
{
|
||
className: 'attr',
|
||
begin: IDENT_RE$1$1 + regex.lookahead(':'),
|
||
relevance: 0
|
||
},
|
||
FUNCTION_VARIABLE,
|
||
{ // "value" container
|
||
begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*',
|
||
keywords: 'return throw case',
|
||
relevance: 0,
|
||
contains: [
|
||
COMMENT,
|
||
hljs.REGEXP_MODE,
|
||
{
|
||
className: 'function',
|
||
// we have to count the parens to make sure we actually have the
|
||
// correct bounding ( ) before the =>. There could be any number of
|
||
// sub-expressions inside also surrounded by parens.
|
||
begin: FUNC_LEAD_IN_RE,
|
||
returnBegin: true,
|
||
end: '\\s*=>',
|
||
contains: [
|
||
{
|
||
className: 'params',
|
||
variants: [
|
||
{
|
||
begin: hljs.UNDERSCORE_IDENT_RE,
|
||
relevance: 0
|
||
},
|
||
{
|
||
className: null,
|
||
begin: /\(\s*\)/,
|
||
skip: true
|
||
},
|
||
{
|
||
begin: /\(/,
|
||
end: /\)/,
|
||
excludeBegin: true,
|
||
excludeEnd: true,
|
||
keywords: KEYWORDS$1$1,
|
||
contains: PARAMS_CONTAINS
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{ // could be a comma delimited list of params to a function call
|
||
begin: /,/,
|
||
relevance: 0
|
||
},
|
||
{
|
||
match: /\s+/,
|
||
relevance: 0
|
||
},
|
||
{ // JSX
|
||
variants: [
|
||
{ begin: FRAGMENT.begin, end: FRAGMENT.end },
|
||
{ match: XML_SELF_CLOSING },
|
||
{
|
||
begin: XML_TAG.begin,
|
||
// we carefully check the opening tag to see if it truly
|
||
// is a tag and not a false positive
|
||
'on:begin': XML_TAG.isTrulyOpeningTag,
|
||
end: XML_TAG.end
|
||
}
|
||
],
|
||
subLanguage: 'xml',
|
||
contains: [
|
||
{
|
||
begin: XML_TAG.begin,
|
||
end: XML_TAG.end,
|
||
skip: true,
|
||
contains: ['self']
|
||
}
|
||
]
|
||
}
|
||
],
|
||
},
|
||
FUNCTION_DEFINITION,
|
||
{
|
||
// prevent this from getting swallowed up by function
|
||
// since they appear "function like"
|
||
beginKeywords: "while if switch catch for"
|
||
},
|
||
{
|
||
// we have to count the parens to make sure we actually have the correct
|
||
// bounding ( ). There could be any number of sub-expressions inside
|
||
// also surrounded by parens.
|
||
begin: '\\b(?!function)' + hljs.UNDERSCORE_IDENT_RE +
|
||
'\\(' + // first parens
|
||
'[^()]*(\\(' +
|
||
'[^()]*(\\(' +
|
||
'[^()]*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)\\s*\\{', // end parens
|
||
returnBegin:true,
|
||
label: "func.def",
|
||
contains: [
|
||
PARAMS,
|
||
hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1$1, className: "title.function" })
|
||
]
|
||
},
|
||
// catch ... so it won't trigger the property rule below
|
||
{
|
||
match: /\.\.\./,
|
||
relevance: 0
|
||
},
|
||
PROPERTY_ACCESS,
|
||
// hack: prevents detection of keywords in some circumstances
|
||
// .keyword()
|
||
// $keyword = x
|
||
{
|
||
match: '\\$' + IDENT_RE$1$1,
|
||
relevance: 0
|
||
},
|
||
{
|
||
match: [ /\bconstructor(?=\s*\()/ ],
|
||
className: { 1: "title.function" },
|
||
contains: [ PARAMS ]
|
||
},
|
||
FUNCTION_CALL,
|
||
UPPER_CASE_CONSTANT,
|
||
CLASS_OR_EXTENDS,
|
||
GETTER_OR_SETTER,
|
||
{
|
||
match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`
|
||
}
|
||
]
|
||
};
|
||
}
|
||
|
||
const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
|
||
const KEYWORDS = [
|
||
"as", // for exports
|
||
"in",
|
||
"of",
|
||
"if",
|
||
"for",
|
||
"while",
|
||
"finally",
|
||
"var",
|
||
"new",
|
||
"function",
|
||
"do",
|
||
"return",
|
||
"void",
|
||
"else",
|
||
"break",
|
||
"catch",
|
||
"instanceof",
|
||
"with",
|
||
"throw",
|
||
"case",
|
||
"default",
|
||
"try",
|
||
"switch",
|
||
"continue",
|
||
"typeof",
|
||
"delete",
|
||
"let",
|
||
"yield",
|
||
"const",
|
||
"class",
|
||
// JS handles these with a special rule
|
||
// "get",
|
||
// "set",
|
||
"debugger",
|
||
"async",
|
||
"await",
|
||
"static",
|
||
"import",
|
||
"from",
|
||
"export",
|
||
"extends"
|
||
];
|
||
const LITERALS = [
|
||
"true",
|
||
"false",
|
||
"null",
|
||
"undefined",
|
||
"NaN",
|
||
"Infinity"
|
||
];
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
|
||
const TYPES = [
|
||
// Fundamental objects
|
||
"Object",
|
||
"Function",
|
||
"Boolean",
|
||
"Symbol",
|
||
// numbers and dates
|
||
"Math",
|
||
"Date",
|
||
"Number",
|
||
"BigInt",
|
||
// text
|
||
"String",
|
||
"RegExp",
|
||
// Indexed collections
|
||
"Array",
|
||
"Float32Array",
|
||
"Float64Array",
|
||
"Int8Array",
|
||
"Uint8Array",
|
||
"Uint8ClampedArray",
|
||
"Int16Array",
|
||
"Int32Array",
|
||
"Uint16Array",
|
||
"Uint32Array",
|
||
"BigInt64Array",
|
||
"BigUint64Array",
|
||
// Keyed collections
|
||
"Set",
|
||
"Map",
|
||
"WeakSet",
|
||
"WeakMap",
|
||
// Structured data
|
||
"ArrayBuffer",
|
||
"SharedArrayBuffer",
|
||
"Atomics",
|
||
"DataView",
|
||
"JSON",
|
||
// Control abstraction objects
|
||
"Promise",
|
||
"Generator",
|
||
"GeneratorFunction",
|
||
"AsyncFunction",
|
||
// Reflection
|
||
"Reflect",
|
||
"Proxy",
|
||
// Internationalization
|
||
"Intl",
|
||
// WebAssembly
|
||
"WebAssembly"
|
||
];
|
||
|
||
const ERROR_TYPES = [
|
||
"Error",
|
||
"EvalError",
|
||
"InternalError",
|
||
"RangeError",
|
||
"ReferenceError",
|
||
"SyntaxError",
|
||
"TypeError",
|
||
"URIError"
|
||
];
|
||
|
||
const BUILT_IN_GLOBALS = [
|
||
"setInterval",
|
||
"setTimeout",
|
||
"clearInterval",
|
||
"clearTimeout",
|
||
|
||
"require",
|
||
"exports",
|
||
|
||
"eval",
|
||
"isFinite",
|
||
"isNaN",
|
||
"parseFloat",
|
||
"parseInt",
|
||
"decodeURI",
|
||
"decodeURIComponent",
|
||
"encodeURI",
|
||
"encodeURIComponent",
|
||
"escape",
|
||
"unescape"
|
||
];
|
||
|
||
const BUILT_IN_VARIABLES = [
|
||
"arguments",
|
||
"this",
|
||
"super",
|
||
"console",
|
||
"window",
|
||
"document",
|
||
"localStorage",
|
||
"sessionStorage",
|
||
"module",
|
||
"global" // Node.js
|
||
];
|
||
|
||
const BUILT_INS = [].concat(
|
||
BUILT_IN_GLOBALS,
|
||
TYPES,
|
||
ERROR_TYPES
|
||
);
|
||
|
||
/*
|
||
Language: JavaScript
|
||
Description: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.
|
||
Category: common, scripting, web
|
||
Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
|
||
*/
|
||
|
||
|
||
/** @type LanguageFn */
|
||
function javascript(hljs) {
|
||
const regex = hljs.regex;
|
||
/**
|
||
* Takes a string like "<Booger" and checks to see
|
||
* if we can find a matching "</Booger" later in the
|
||
* content.
|
||
* @param {RegExpMatchArray} match
|
||
* @param {{after:number}} param1
|
||
*/
|
||
const hasClosingTag = (match, { after }) => {
|
||
const tag = "</" + match[0].slice(1);
|
||
const pos = match.input.indexOf(tag, after);
|
||
return pos !== -1;
|
||
};
|
||
|
||
const IDENT_RE$1 = IDENT_RE;
|
||
const FRAGMENT = {
|
||
begin: '<>',
|
||
end: '</>'
|
||
};
|
||
// to avoid some special cases inside isTrulyOpeningTag
|
||
const XML_SELF_CLOSING = /<[A-Za-z0-9\\._:-]+\s*\/>/;
|
||
const XML_TAG = {
|
||
begin: /<[A-Za-z0-9\\._:-]+/,
|
||
end: /\/[A-Za-z0-9\\._:-]+>|\/>/,
|
||
/**
|
||
* @param {RegExpMatchArray} match
|
||
* @param {CallbackResponse} response
|
||
*/
|
||
isTrulyOpeningTag: (match, response) => {
|
||
const afterMatchIndex = match[0].length + match.index;
|
||
const nextChar = match.input[afterMatchIndex];
|
||
if (
|
||
// HTML should not include another raw `<` inside a tag
|
||
// nested type?
|
||
// `<Array<Array<number>>`, etc.
|
||
nextChar === "<" ||
|
||
// the , gives away that this is not HTML
|
||
// `<T, A extends keyof T, V>`
|
||
nextChar === ","
|
||
) {
|
||
response.ignoreMatch();
|
||
return;
|
||
}
|
||
|
||
// `<something>`
|
||
// Quite possibly a tag, lets look for a matching closing tag...
|
||
if (nextChar === ">") {
|
||
// if we cannot find a matching closing tag, then we
|
||
// will ignore it
|
||
if (!hasClosingTag(match, { after: afterMatchIndex })) {
|
||
response.ignoreMatch();
|
||
}
|
||
}
|
||
|
||
// `<blah />` (self-closing)
|
||
// handled by simpleSelfClosing rule
|
||
|
||
let m;
|
||
const afterMatch = match.input.substring(afterMatchIndex);
|
||
|
||
// some more template typing stuff
|
||
// <T = any>(key?: string) => Modify<
|
||
if ((m = afterMatch.match(/^\s*=/))) {
|
||
response.ignoreMatch();
|
||
return;
|
||
}
|
||
|
||
// `<From extends string>`
|
||
// technically this could be HTML, but it smells like a type
|
||
// NOTE: This is ugh, but added specifically for https://github.com/highlightjs/highlight.js/issues/3276
|
||
if ((m = afterMatch.match(/^\s+extends\s+/))) {
|
||
if (m.index === 0) {
|
||
response.ignoreMatch();
|
||
// eslint-disable-next-line no-useless-return
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
const KEYWORDS$1 = {
|
||
$pattern: IDENT_RE,
|
||
keyword: KEYWORDS,
|
||
literal: LITERALS,
|
||
built_in: BUILT_INS,
|
||
"variable.language": BUILT_IN_VARIABLES
|
||
};
|
||
|
||
// https://tc39.es/ecma262/#sec-literals-numeric-literals
|
||
const decimalDigits = '[0-9](_?[0-9])*';
|
||
const frac = `\\.(${decimalDigits})`;
|
||
// DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral
|
||
// https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
|
||
const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`;
|
||
const NUMBER = {
|
||
className: 'number',
|
||
variants: [
|
||
// DecimalLiteral
|
||
{ begin: `(\\b(${decimalInteger})((${frac})|\\.)?|(${frac}))` +
|
||
`[eE][+-]?(${decimalDigits})\\b` },
|
||
{ begin: `\\b(${decimalInteger})\\b((${frac})\\b|\\.)?|(${frac})\\b` },
|
||
|
||
// DecimalBigIntegerLiteral
|
||
{ begin: `\\b(0|[1-9](_?[0-9])*)n\\b` },
|
||
|
||
// NonDecimalIntegerLiteral
|
||
{ begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b" },
|
||
{ begin: "\\b0[bB][0-1](_?[0-1])*n?\\b" },
|
||
{ begin: "\\b0[oO][0-7](_?[0-7])*n?\\b" },
|
||
|
||
// LegacyOctalIntegerLiteral (does not include underscore separators)
|
||
// https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
|
||
{ begin: "\\b0[0-7]+n?\\b" },
|
||
],
|
||
relevance: 0
|
||
};
|
||
|
||
const SUBST = {
|
||
className: 'subst',
|
||
begin: '\\$\\{',
|
||
end: '\\}',
|
||
keywords: KEYWORDS$1,
|
||
contains: [] // defined later
|
||
};
|
||
const HTML_TEMPLATE = {
|
||
begin: 'html`',
|
||
end: '',
|
||
starts: {
|
||
end: '`',
|
||
returnEnd: false,
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
],
|
||
subLanguage: 'xml'
|
||
}
|
||
};
|
||
const CSS_TEMPLATE = {
|
||
begin: 'css`',
|
||
end: '',
|
||
starts: {
|
||
end: '`',
|
||
returnEnd: false,
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
],
|
||
subLanguage: 'css'
|
||
}
|
||
};
|
||
const GRAPHQL_TEMPLATE = {
|
||
begin: 'gql`',
|
||
end: '',
|
||
starts: {
|
||
end: '`',
|
||
returnEnd: false,
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
],
|
||
subLanguage: 'graphql'
|
||
}
|
||
};
|
||
const TEMPLATE_STRING = {
|
||
className: 'string',
|
||
begin: '`',
|
||
end: '`',
|
||
contains: [
|
||
hljs.BACKSLASH_ESCAPE,
|
||
SUBST
|
||
]
|
||
};
|
||
const JSDOC_COMMENT = hljs.COMMENT(
|
||
/\/\*\*(?!\/)/,
|
||
'\\*/',
|
||
{
|
||
relevance: 0,
|
||
contains: [
|
||
{
|
||
begin: '(?=@[A-Za-z]+)',
|
||
relevance: 0,
|
||
contains: [
|
||
{
|
||
className: 'doctag',
|
||
begin: '@[A-Za-z]+'
|
||
},
|
||
{
|
||
className: 'type',
|
||
begin: '\\{',
|
||
end: '\\}',
|
||
excludeEnd: true,
|
||
excludeBegin: true,
|
||
relevance: 0
|
||
},
|
||
{
|
||
className: 'variable',
|
||
begin: IDENT_RE$1 + '(?=\\s*(-)|$)',
|
||
endsParent: true,
|
||
relevance: 0
|
||
},
|
||
// eat spaces (not newlines) so we can find
|
||
// types or variables
|
||
{
|
||
begin: /(?=[^\n])\s/,
|
||
relevance: 0
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
);
|
||
const COMMENT = {
|
||
className: "comment",
|
||
variants: [
|
||
JSDOC_COMMENT,
|
||
hljs.C_BLOCK_COMMENT_MODE,
|
||
hljs.C_LINE_COMMENT_MODE
|
||
]
|
||
};
|
||
const SUBST_INTERNALS = [
|
||
hljs.APOS_STRING_MODE,
|
||
hljs.QUOTE_STRING_MODE,
|
||
HTML_TEMPLATE,
|
||
CSS_TEMPLATE,
|
||
GRAPHQL_TEMPLATE,
|
||
TEMPLATE_STRING,
|
||
// Skip numbers when they are part of a variable name
|
||
{ match: /\$\d+/ },
|
||
NUMBER,
|
||
// This is intentional:
|
||
// See https://github.com/highlightjs/highlight.js/issues/3288
|
||
// hljs.REGEXP_MODE
|
||
];
|
||
SUBST.contains = SUBST_INTERNALS
|
||
.concat({
|
||
// we need to pair up {} inside our subst to prevent
|
||
// it from ending too early by matching another }
|
||
begin: /\{/,
|
||
end: /\}/,
|
||
keywords: KEYWORDS$1,
|
||
contains: [
|
||
"self"
|
||
].concat(SUBST_INTERNALS)
|
||
});
|
||
const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains);
|
||
const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([
|
||
// eat recursive parens in sub expressions
|
||
{
|
||
begin: /\(/,
|
||
end: /\)/,
|
||
keywords: KEYWORDS$1,
|
||
contains: ["self"].concat(SUBST_AND_COMMENTS)
|
||
}
|
||
]);
|
||
const PARAMS = {
|
||
className: 'params',
|
||
begin: /\(/,
|
||
end: /\)/,
|
||
excludeBegin: true,
|
||
excludeEnd: true,
|
||
keywords: KEYWORDS$1,
|
||
contains: PARAMS_CONTAINS
|
||
};
|
||
|
||
// ES6 classes
|
||
const CLASS_OR_EXTENDS = {
|
||
variants: [
|
||
// class Car extends vehicle
|
||
{
|
||
match: [
|
||
/class/,
|
||
/\s+/,
|
||
IDENT_RE$1,
|
||
/\s+/,
|
||
/extends/,
|
||
/\s+/,
|
||
regex.concat(IDENT_RE$1, "(", regex.concat(/\./, IDENT_RE$1), ")*")
|
||
],
|
||
scope: {
|
||
1: "keyword",
|
||
3: "title.class",
|
||
5: "keyword",
|
||
7: "title.class.inherited"
|
||
}
|
||
},
|
||
// class Car
|
||
{
|
||
match: [
|
||
/class/,
|
||
/\s+/,
|
||
IDENT_RE$1
|
||
],
|
||
scope: {
|
||
1: "keyword",
|
||
3: "title.class"
|
||
}
|
||
},
|
||
|
||
]
|
||
};
|
||
|
||
const CLASS_REFERENCE = {
|
||
relevance: 0,
|
||
match:
|
||
regex.either(
|
||
// Hard coded exceptions
|
||
/\bJSON/,
|
||
// Float32Array, OutT
|
||
/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,
|
||
// CSSFactory, CSSFactoryT
|
||
/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,
|
||
// FPs, FPsT
|
||
/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/,
|
||
// P
|
||
// single letters are not highlighted
|
||
// BLAH
|
||
// this will be flagged as a UPPER_CASE_CONSTANT instead
|
||
),
|
||
className: "title.class",
|
||
keywords: {
|
||
_: [
|
||
// se we still get relevance credit for JS library classes
|
||
...TYPES,
|
||
...ERROR_TYPES
|
||
]
|
||
}
|
||
};
|
||
|
||
const USE_STRICT = {
|
||
label: "use_strict",
|
||
className: 'meta',
|
||
relevance: 10,
|
||
begin: /^\s*['"]use (strict|asm)['"]/
|
||
};
|
||
|
||
const FUNCTION_DEFINITION = {
|
||
variants: [
|
||
{
|
||
match: [
|
||
/function/,
|
||
/\s+/,
|
||
IDENT_RE$1,
|
||
/(?=\s*\()/
|
||
]
|
||
},
|
||
// anonymous function
|
||
{
|
||
match: [
|
||
/function/,
|
||
/\s*(?=\()/
|
||
]
|
||
}
|
||
],
|
||
className: {
|
||
1: "keyword",
|
||
3: "title.function"
|
||
},
|
||
label: "func.def",
|
||
contains: [ PARAMS ],
|
||
illegal: /%/
|
||
};
|
||
|
||
const UPPER_CASE_CONSTANT = {
|
||
relevance: 0,
|
||
match: /\b[A-Z][A-Z_0-9]+\b/,
|
||
className: "variable.constant"
|
||
};
|
||
|
||
function noneOf(list) {
|
||
return regex.concat("(?!", list.join("|"), ")");
|
||
}
|
||
|
||
const FUNCTION_CALL = {
|
||
match: regex.concat(
|
||
/\b/,
|
||
noneOf([
|
||
...BUILT_IN_GLOBALS,
|
||
"super",
|
||
"import"
|
||
]),
|
||
IDENT_RE$1, regex.lookahead(/\(/)),
|
||
className: "title.function",
|
||
relevance: 0
|
||
};
|
||
|
||
const PROPERTY_ACCESS = {
|
||
begin: regex.concat(/\./, regex.lookahead(
|
||
regex.concat(IDENT_RE$1, /(?![0-9A-Za-z$_(])/)
|
||
)),
|
||
end: IDENT_RE$1,
|
||
excludeBegin: true,
|
||
keywords: "prototype",
|
||
className: "property",
|
||
relevance: 0
|
||
};
|
||
|
||
const GETTER_OR_SETTER = {
|
||
match: [
|
||
/get|set/,
|
||
/\s+/,
|
||
IDENT_RE$1,
|
||
/(?=\()/
|
||
],
|
||
className: {
|
||
1: "keyword",
|
||
3: "title.function"
|
||
},
|
||
contains: [
|
||
{ // eat to avoid empty params
|
||
begin: /\(\)/
|
||
},
|
||
PARAMS
|
||
]
|
||
};
|
||
|
||
const FUNC_LEAD_IN_RE = '(\\(' +
|
||
'[^()]*(\\(' +
|
||
'[^()]*(\\(' +
|
||
'[^()]*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\s*=>';
|
||
|
||
const FUNCTION_VARIABLE = {
|
||
match: [
|
||
/const|var|let/, /\s+/,
|
||
IDENT_RE$1, /\s*/,
|
||
/=\s*/,
|
||
/(async\s*)?/, // async is optional
|
||
regex.lookahead(FUNC_LEAD_IN_RE)
|
||
],
|
||
keywords: "async",
|
||
className: {
|
||
1: "keyword",
|
||
3: "title.function"
|
||
},
|
||
contains: [
|
||
PARAMS
|
||
]
|
||
};
|
||
|
||
return {
|
||
name: 'JavaScript',
|
||
aliases: ['js', 'jsx', 'mjs', 'cjs'],
|
||
keywords: KEYWORDS$1,
|
||
// this will be extended by TypeScript
|
||
exports: { PARAMS_CONTAINS, CLASS_REFERENCE },
|
||
illegal: /#(?![$_A-z])/,
|
||
contains: [
|
||
hljs.SHEBANG({
|
||
label: "shebang",
|
||
binary: "node",
|
||
relevance: 5
|
||
}),
|
||
USE_STRICT,
|
||
hljs.APOS_STRING_MODE,
|
||
hljs.QUOTE_STRING_MODE,
|
||
HTML_TEMPLATE,
|
||
CSS_TEMPLATE,
|
||
GRAPHQL_TEMPLATE,
|
||
TEMPLATE_STRING,
|
||
COMMENT,
|
||
// Skip numbers when they are part of a variable name
|
||
{ match: /\$\d+/ },
|
||
NUMBER,
|
||
CLASS_REFERENCE,
|
||
{
|
||
className: 'attr',
|
||
begin: IDENT_RE$1 + regex.lookahead(':'),
|
||
relevance: 0
|
||
},
|
||
FUNCTION_VARIABLE,
|
||
{ // "value" container
|
||
begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*',
|
||
keywords: 'return throw case',
|
||
relevance: 0,
|
||
contains: [
|
||
COMMENT,
|
||
hljs.REGEXP_MODE,
|
||
{
|
||
className: 'function',
|
||
// we have to count the parens to make sure we actually have the
|
||
// correct bounding ( ) before the =>. There could be any number of
|
||
// sub-expressions inside also surrounded by parens.
|
||
begin: FUNC_LEAD_IN_RE,
|
||
returnBegin: true,
|
||
end: '\\s*=>',
|
||
contains: [
|
||
{
|
||
className: 'params',
|
||
variants: [
|
||
{
|
||
begin: hljs.UNDERSCORE_IDENT_RE,
|
||
relevance: 0
|
||
},
|
||
{
|
||
className: null,
|
||
begin: /\(\s*\)/,
|
||
skip: true
|
||
},
|
||
{
|
||
begin: /\(/,
|
||
end: /\)/,
|
||
excludeBegin: true,
|
||
excludeEnd: true,
|
||
keywords: KEYWORDS$1,
|
||
contains: PARAMS_CONTAINS
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{ // could be a comma delimited list of params to a function call
|
||
begin: /,/,
|
||
relevance: 0
|
||
},
|
||
{
|
||
match: /\s+/,
|
||
relevance: 0
|
||
},
|
||
{ // JSX
|
||
variants: [
|
||
{ begin: FRAGMENT.begin, end: FRAGMENT.end },
|
||
{ match: XML_SELF_CLOSING },
|
||
{
|
||
begin: XML_TAG.begin,
|
||
// we carefully check the opening tag to see if it truly
|
||
// is a tag and not a false positive
|
||
'on:begin': XML_TAG.isTrulyOpeningTag,
|
||
end: XML_TAG.end
|
||
}
|
||
],
|
||
subLanguage: 'xml',
|
||
contains: [
|
||
{
|
||
begin: XML_TAG.begin,
|
||
end: XML_TAG.end,
|
||
skip: true,
|
||
contains: ['self']
|
||
}
|
||
]
|
||
}
|
||
],
|
||
},
|
||
FUNCTION_DEFINITION,
|
||
{
|
||
// prevent this from getting swallowed up by function
|
||
// since they appear "function like"
|
||
beginKeywords: "while if switch catch for"
|
||
},
|
||
{
|
||
// we have to count the parens to make sure we actually have the correct
|
||
// bounding ( ). There could be any number of sub-expressions inside
|
||
// also surrounded by parens.
|
||
begin: '\\b(?!function)' + hljs.UNDERSCORE_IDENT_RE +
|
||
'\\(' + // first parens
|
||
'[^()]*(\\(' +
|
||
'[^()]*(\\(' +
|
||
'[^()]*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)[^()]*)*' +
|
||
'\\)\\s*\\{', // end parens
|
||
returnBegin:true,
|
||
label: "func.def",
|
||
contains: [
|
||
PARAMS,
|
||
hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1, className: "title.function" })
|
||
]
|
||
},
|
||
// catch ... so it won't trigger the property rule below
|
||
{
|
||
match: /\.\.\./,
|
||
relevance: 0
|
||
},
|
||
PROPERTY_ACCESS,
|
||
// hack: prevents detection of keywords in some circumstances
|
||
// .keyword()
|
||
// $keyword = x
|
||
{
|
||
match: '\\$' + IDENT_RE$1,
|
||
relevance: 0
|
||
},
|
||
{
|
||
match: [ /\bconstructor(?=\s*\()/ ],
|
||
className: { 1: "title.function" },
|
||
contains: [ PARAMS ]
|
||
},
|
||
FUNCTION_CALL,
|
||
UPPER_CASE_CONSTANT,
|
||
CLASS_OR_EXTENDS,
|
||
GETTER_OR_SETTER,
|
||
{
|
||
match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`
|
||
}
|
||
]
|
||
};
|
||
}
|
||
|
||
/*
|
||
Language: TypeScript
|
||
Author: Panu Horsmalahti <panu.horsmalahti@iki.fi>
|
||
Contributors: Ike Ku <dempfi@yahoo.com>
|
||
Description: TypeScript is a strict superset of JavaScript
|
||
Website: https://www.typescriptlang.org
|
||
Category: common, scripting
|
||
*/
|
||
|
||
|
||
/** @type LanguageFn */
|
||
function typescript(hljs) {
|
||
const tsLanguage = javascript(hljs);
|
||
|
||
const IDENT_RE$1 = IDENT_RE;
|
||
const TYPES = [
|
||
"any",
|
||
"void",
|
||
"number",
|
||
"boolean",
|
||
"string",
|
||
"object",
|
||
"never",
|
||
"symbol",
|
||
"bigint",
|
||
"unknown"
|
||
];
|
||
const NAMESPACE = {
|
||
beginKeywords: 'namespace',
|
||
end: /\{/,
|
||
excludeEnd: true,
|
||
contains: [ tsLanguage.exports.CLASS_REFERENCE ]
|
||
};
|
||
const INTERFACE = {
|
||
beginKeywords: 'interface',
|
||
end: /\{/,
|
||
excludeEnd: true,
|
||
keywords: {
|
||
keyword: 'interface extends',
|
||
built_in: TYPES
|
||
},
|
||
contains: [ tsLanguage.exports.CLASS_REFERENCE ]
|
||
};
|
||
const USE_STRICT = {
|
||
className: 'meta',
|
||
relevance: 10,
|
||
begin: /^\s*['"]use strict['"]/
|
||
};
|
||
const TS_SPECIFIC_KEYWORDS = [
|
||
"type",
|
||
"namespace",
|
||
"interface",
|
||
"public",
|
||
"private",
|
||
"protected",
|
||
"implements",
|
||
"declare",
|
||
"abstract",
|
||
"readonly",
|
||
"enum",
|
||
"override"
|
||
];
|
||
const KEYWORDS$1 = {
|
||
$pattern: IDENT_RE,
|
||
keyword: KEYWORDS.concat(TS_SPECIFIC_KEYWORDS),
|
||
literal: LITERALS,
|
||
built_in: BUILT_INS.concat(TYPES),
|
||
"variable.language": BUILT_IN_VARIABLES
|
||
};
|
||
const DECORATOR = {
|
||
className: 'meta',
|
||
begin: '@' + IDENT_RE$1,
|
||
};
|
||
|
||
const swapMode = (mode, label, replacement) => {
|
||
const indx = mode.contains.findIndex(m => m.label === label);
|
||
if (indx === -1) { throw new Error("can not find mode to replace"); }
|
||
|
||
mode.contains.splice(indx, 1, replacement);
|
||
};
|
||
|
||
|
||
// this should update anywhere keywords is used since
|
||
// it will be the same actual JS object
|
||
Object.assign(tsLanguage.keywords, KEYWORDS$1);
|
||
|
||
tsLanguage.exports.PARAMS_CONTAINS.push(DECORATOR);
|
||
tsLanguage.contains = tsLanguage.contains.concat([
|
||
DECORATOR,
|
||
NAMESPACE,
|
||
INTERFACE,
|
||
]);
|
||
|
||
// TS gets a simpler shebang rule than JS
|
||
swapMode(tsLanguage, "shebang", hljs.SHEBANG());
|
||
// JS use strict rule purposely excludes `asm` which makes no sense
|
||
swapMode(tsLanguage, "use_strict", USE_STRICT);
|
||
|
||
const functionDeclaration = tsLanguage.contains.find(m => m.label === "func.def");
|
||
functionDeclaration.relevance = 0; // () => {} is more typical in TypeScript
|
||
|
||
Object.assign(tsLanguage, {
|
||
name: 'TypeScript',
|
||
aliases: [
|
||
'ts',
|
||
'tsx',
|
||
'mts',
|
||
'cts'
|
||
]
|
||
});
|
||
|
||
return tsLanguage;
|
||
}
|
||
|
||
/*
|
||
Language: Shell Session
|
||
Requires: bash.js
|
||
Author: TSUYUSATO Kitsune <make.just.on@gmail.com>
|
||
Category: common
|
||
Audit: 2020
|
||
*/
|
||
|
||
/** @type LanguageFn */
|
||
function shell(hljs) {
|
||
return {
|
||
name: 'Shell Session',
|
||
aliases: [
|
||
'console',
|
||
'shellsession'
|
||
],
|
||
contains: [
|
||
{
|
||
className: 'meta.prompt',
|
||
// We cannot add \s (spaces) in the regular expression otherwise it will be too broad and produce unexpected result.
|
||
// For instance, in the following example, it would match "echo /path/to/home >" as a prompt:
|
||
// echo /path/to/home > t.exe
|
||
begin: /^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,
|
||
starts: {
|
||
end: /[^\\](?=\s*$)/,
|
||
subLanguage: 'bash'
|
||
}
|
||
}
|
||
]
|
||
};
|
||
}
|
||
|
||
const storePopup = writable(void 0);
|
||
const DRAWER_STORE_KEY = "drawerStore";
|
||
function getDrawerStore() {
|
||
const drawerStore = getContext(DRAWER_STORE_KEY);
|
||
if (!drawerStore)
|
||
throw new Error("drawerStore is not initialized. Please ensure that `initializeStores()` is invoked in the root layout file of this app!");
|
||
return drawerStore;
|
||
}
|
||
function initializeDrawerStore() {
|
||
const drawerStore = drawerService();
|
||
return setContext(DRAWER_STORE_KEY, drawerStore);
|
||
}
|
||
function drawerService() {
|
||
const { subscribe: subscribe2, set, update } = writable({});
|
||
return {
|
||
subscribe: subscribe2,
|
||
set,
|
||
update,
|
||
/** Open the drawer. */
|
||
open: (newSettings) => update(() => {
|
||
return { open: true, ...newSettings };
|
||
}),
|
||
/** Close the drawer. */
|
||
close: () => update((d) => {
|
||
d.open = false;
|
||
return d;
|
||
})
|
||
};
|
||
}
|
||
const toastDefaults = { message: "Missing Toast Message", autohide: true, timeout: 5e3 };
|
||
const TOAST_STORE_KEY = "toastStore";
|
||
function initializeToastStore() {
|
||
const toastStore = toastService();
|
||
return setContext(TOAST_STORE_KEY, toastStore);
|
||
}
|
||
function randomUUID() {
|
||
const random = Math.random();
|
||
return Number(random).toString(32);
|
||
}
|
||
function toastService() {
|
||
const { subscribe: subscribe2, set, update } = writable([]);
|
||
const close = (id) => update((tStore) => {
|
||
if (tStore.length > 0) {
|
||
const index = tStore.findIndex((t) => t.id === id);
|
||
const selectedToast = tStore[index];
|
||
if (selectedToast) {
|
||
if (selectedToast.callback)
|
||
selectedToast.callback({ id, status: "closed" });
|
||
if (selectedToast.timeoutId)
|
||
clearTimeout(selectedToast.timeoutId);
|
||
tStore.splice(index, 1);
|
||
}
|
||
}
|
||
return tStore;
|
||
});
|
||
function handleAutoHide(toast) {
|
||
if (toast.autohide === true) {
|
||
return setTimeout(() => {
|
||
close(toast.id);
|
||
}, toast.timeout);
|
||
}
|
||
}
|
||
return {
|
||
subscribe: subscribe2,
|
||
close,
|
||
/** Add a new toast to the queue. */
|
||
trigger: (toast) => {
|
||
const id = randomUUID();
|
||
update((tStore) => {
|
||
if (toast && toast.callback)
|
||
toast.callback({ id, status: "queued" });
|
||
if (toast.hideDismiss)
|
||
toast.autohide = true;
|
||
const tMerged = { ...toastDefaults, ...toast, id };
|
||
tMerged.timeoutId = handleAutoHide(tMerged);
|
||
tStore.push(tMerged);
|
||
return tStore;
|
||
});
|
||
return id;
|
||
},
|
||
/** Remain visible on hover */
|
||
freeze: (index) => update((tStore) => {
|
||
if (tStore.length > 0)
|
||
clearTimeout(tStore[index].timeoutId);
|
||
return tStore;
|
||
}),
|
||
/** Cancel remain visible on leave */
|
||
unfreeze: (index) => update((tStore) => {
|
||
if (tStore.length > 0)
|
||
tStore[index].timeoutId = handleAutoHide(tStore[index]);
|
||
return tStore;
|
||
}),
|
||
/** Remove all toasts from queue */
|
||
clear: () => set([])
|
||
};
|
||
}
|
||
function initializeStores() {
|
||
initializeModalStore();
|
||
initializeToastStore();
|
||
initializeDrawerStore();
|
||
}
|
||
function cubicOut(t) {
|
||
const f = t - 1;
|
||
return f * f * f + 1;
|
||
}
|
||
function fly(node, { delay = 0, duration = 400, easing = cubicOut, x = 0, y = 0, opacity = 0 } = {}) {
|
||
const style = getComputedStyle(node);
|
||
const target_opacity = +style.opacity;
|
||
const transform = style.transform === "none" ? "" : style.transform;
|
||
const od = target_opacity * (1 - opacity);
|
||
const [xValue, xUnit] = split_css_unit(x);
|
||
const [yValue, yUnit] = split_css_unit(y);
|
||
return {
|
||
delay,
|
||
duration,
|
||
easing,
|
||
css: (t, u) => `
|
||
transform: ${transform} translate(${(1 - t) * xValue}${xUnit}, ${(1 - t) * yValue}${yUnit});
|
||
opacity: ${target_opacity - od * u}`
|
||
};
|
||
}
|
||
const cBase$1 = "flex flex-col";
|
||
const cRowMain = "grid items-center";
|
||
const cRowHeadline = "";
|
||
const cSlotLead = "flex-none flex justify-between items-center";
|
||
const cSlotDefault = "flex-auto";
|
||
const cSlotTrail = "flex-none flex items-center space-x-4";
|
||
const AppBar = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let classesBase;
|
||
let classesRowMain;
|
||
let classesRowHeadline;
|
||
let classesSlotLead;
|
||
let classesSlotDefault;
|
||
let classesSlotTrail;
|
||
let $$slots = compute_slots(slots);
|
||
let { background = "bg-surface-100-800-token" } = $$props;
|
||
let { border = "" } = $$props;
|
||
let { padding = "p-4" } = $$props;
|
||
let { shadow = "" } = $$props;
|
||
let { spacing = "space-y-4" } = $$props;
|
||
let { gridColumns = "grid-cols-[auto_1fr_auto]" } = $$props;
|
||
let { gap = "gap-4" } = $$props;
|
||
let { regionRowMain = "" } = $$props;
|
||
let { regionRowHeadline = "" } = $$props;
|
||
let { slotLead = "" } = $$props;
|
||
let { slotDefault = "" } = $$props;
|
||
let { slotTrail = "" } = $$props;
|
||
let { label = "" } = $$props;
|
||
let { labelledby = "" } = $$props;
|
||
if ($$props.background === void 0 && $$bindings.background && background !== void 0)
|
||
$$bindings.background(background);
|
||
if ($$props.border === void 0 && $$bindings.border && border !== void 0)
|
||
$$bindings.border(border);
|
||
if ($$props.padding === void 0 && $$bindings.padding && padding !== void 0)
|
||
$$bindings.padding(padding);
|
||
if ($$props.shadow === void 0 && $$bindings.shadow && shadow !== void 0)
|
||
$$bindings.shadow(shadow);
|
||
if ($$props.spacing === void 0 && $$bindings.spacing && spacing !== void 0)
|
||
$$bindings.spacing(spacing);
|
||
if ($$props.gridColumns === void 0 && $$bindings.gridColumns && gridColumns !== void 0)
|
||
$$bindings.gridColumns(gridColumns);
|
||
if ($$props.gap === void 0 && $$bindings.gap && gap !== void 0)
|
||
$$bindings.gap(gap);
|
||
if ($$props.regionRowMain === void 0 && $$bindings.regionRowMain && regionRowMain !== void 0)
|
||
$$bindings.regionRowMain(regionRowMain);
|
||
if ($$props.regionRowHeadline === void 0 && $$bindings.regionRowHeadline && regionRowHeadline !== void 0)
|
||
$$bindings.regionRowHeadline(regionRowHeadline);
|
||
if ($$props.slotLead === void 0 && $$bindings.slotLead && slotLead !== void 0)
|
||
$$bindings.slotLead(slotLead);
|
||
if ($$props.slotDefault === void 0 && $$bindings.slotDefault && slotDefault !== void 0)
|
||
$$bindings.slotDefault(slotDefault);
|
||
if ($$props.slotTrail === void 0 && $$bindings.slotTrail && slotTrail !== void 0)
|
||
$$bindings.slotTrail(slotTrail);
|
||
if ($$props.label === void 0 && $$bindings.label && label !== void 0)
|
||
$$bindings.label(label);
|
||
if ($$props.labelledby === void 0 && $$bindings.labelledby && labelledby !== void 0)
|
||
$$bindings.labelledby(labelledby);
|
||
classesBase = `${cBase$1} ${background} ${border} ${spacing} ${padding} ${shadow} ${$$props.class ?? ""}`;
|
||
classesRowMain = `${cRowMain} ${gridColumns} ${gap} ${regionRowMain}`;
|
||
classesRowHeadline = `${cRowHeadline} ${regionRowHeadline}`;
|
||
classesSlotLead = `${cSlotLead} ${slotLead}`;
|
||
classesSlotDefault = `${cSlotDefault} ${slotDefault}`;
|
||
classesSlotTrail = `${cSlotTrail} ${slotTrail}`;
|
||
return `<div class="${"app-bar " + escape(classesBase, true)}" data-testid="app-bar" role="toolbar"${add_attribute("aria-label", label, 0)}${add_attribute("aria-labelledby", labelledby, 0)}> <div class="${"app-bar-row-main " + escape(classesRowMain, true)}"> ${$$slots.lead ? `<div class="${"app-bar-slot-lead " + escape(classesSlotLead, true)}">${slots.lead ? slots.lead({}) : ``}</div>` : ``} <div class="${"app-bar-slot-default " + escape(classesSlotDefault, true)}">${slots.default ? slots.default({}) : ``}</div> ${$$slots.trail ? `<div class="${"app-bar-slot-trail " + escape(classesSlotTrail, true)}">${slots.trail ? slots.trail({}) : ``}</div>` : ``}</div> ${$$slots.headline ? `<div class="${"app-bar-row-headline " + escape(classesRowHeadline, true)}">${slots.headline ? slots.headline({}) : ``}</div>` : ``}</div>`;
|
||
});
|
||
const cBaseAppShell = "w-full h-full flex flex-col overflow-hidden";
|
||
const cContentArea = "w-full h-full flex overflow-hidden";
|
||
const cPage = "flex-1 overflow-x-hidden flex flex-col";
|
||
const cSidebarLeft = "flex-none overflow-x-hidden overflow-y-auto";
|
||
const cSidebarRight = "flex-none overflow-x-hidden overflow-y-auto";
|
||
const AppShell = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let classesBase;
|
||
let classesHeader;
|
||
let classesSidebarLeft;
|
||
let classesSidebarRight;
|
||
let classesPageHeader;
|
||
let classesPageContent;
|
||
let classesPageFooter;
|
||
let classesFooter;
|
||
let $$slots = compute_slots(slots);
|
||
let { scrollbarGutter = "auto" } = $$props;
|
||
let { regionPage = "" } = $$props;
|
||
let { slotHeader = "z-10" } = $$props;
|
||
let { slotSidebarLeft = "w-auto" } = $$props;
|
||
let { slotSidebarRight = "w-auto" } = $$props;
|
||
let { slotPageHeader = "" } = $$props;
|
||
let { slotPageContent = "" } = $$props;
|
||
let { slotPageFooter = "" } = $$props;
|
||
let { slotFooter = "" } = $$props;
|
||
if ($$props.scrollbarGutter === void 0 && $$bindings.scrollbarGutter && scrollbarGutter !== void 0)
|
||
$$bindings.scrollbarGutter(scrollbarGutter);
|
||
if ($$props.regionPage === void 0 && $$bindings.regionPage && regionPage !== void 0)
|
||
$$bindings.regionPage(regionPage);
|
||
if ($$props.slotHeader === void 0 && $$bindings.slotHeader && slotHeader !== void 0)
|
||
$$bindings.slotHeader(slotHeader);
|
||
if ($$props.slotSidebarLeft === void 0 && $$bindings.slotSidebarLeft && slotSidebarLeft !== void 0)
|
||
$$bindings.slotSidebarLeft(slotSidebarLeft);
|
||
if ($$props.slotSidebarRight === void 0 && $$bindings.slotSidebarRight && slotSidebarRight !== void 0)
|
||
$$bindings.slotSidebarRight(slotSidebarRight);
|
||
if ($$props.slotPageHeader === void 0 && $$bindings.slotPageHeader && slotPageHeader !== void 0)
|
||
$$bindings.slotPageHeader(slotPageHeader);
|
||
if ($$props.slotPageContent === void 0 && $$bindings.slotPageContent && slotPageContent !== void 0)
|
||
$$bindings.slotPageContent(slotPageContent);
|
||
if ($$props.slotPageFooter === void 0 && $$bindings.slotPageFooter && slotPageFooter !== void 0)
|
||
$$bindings.slotPageFooter(slotPageFooter);
|
||
if ($$props.slotFooter === void 0 && $$bindings.slotFooter && slotFooter !== void 0)
|
||
$$bindings.slotFooter(slotFooter);
|
||
classesBase = `${cBaseAppShell} ${$$props.class ?? ""}`;
|
||
classesHeader = `${slotHeader}`;
|
||
classesSidebarLeft = `${cSidebarLeft} ${slotSidebarLeft}`;
|
||
classesSidebarRight = `${cSidebarRight} ${slotSidebarRight}`;
|
||
classesPageHeader = `${slotPageHeader}`;
|
||
classesPageContent = `${slotPageContent}`;
|
||
classesPageFooter = `${slotPageFooter}`;
|
||
classesFooter = `${slotFooter}`;
|
||
return `<div id="appShell"${add_attribute("class", classesBase, 0)} data-testid="app-shell"> ${$$slots.header ? `<header id="shell-header" class="${"flex-none " + escape(classesHeader, true)}">${slots.header ? slots.header({}) : ``}</header>` : ``} <div class="${"flex-auto " + escape(cContentArea, true)}"> ${$$slots.sidebarLeft ? `<aside id="sidebar-left"${add_attribute("class", classesSidebarLeft, 0)}>${slots.sidebarLeft ? slots.sidebarLeft({}) : ``}</aside>` : ``} <div id="page" class="${escape(regionPage, true) + " " + escape(cPage, true)}"${add_styles({ "scrollbar-gutter": scrollbarGutter })}> ${$$slots.pageHeader ? `<header id="page-header" class="${"flex-none " + escape(classesPageHeader, true)}">${slots.pageHeader ? slots.pageHeader({}) : `(slot:header)`}</header>` : ``} <main id="page-content" class="${"flex-auto " + escape(classesPageContent, true)}">${slots.default ? slots.default({}) : ``}</main> ${$$slots.pageFooter ? `<footer id="page-footer" class="${"flex-none " + escape(classesPageFooter, true)}">${slots.pageFooter ? slots.pageFooter({}) : `(slot:footer)`}</footer>` : ``}</div> ${$$slots.sidebarRight ? `<aside id="sidebar-right"${add_attribute("class", classesSidebarRight, 0)}>${slots.sidebarRight ? slots.sidebarRight({}) : ``}</aside>` : ``}</div> ${$$slots.footer ? `<footer id="shell-footer" class="${"flex-none " + escape(classesFooter, true)}">${slots.footer ? slots.footer({}) : ``}</footer>` : ``}</div>`;
|
||
});
|
||
let cBase = "flex aspect-square text-surface-50 font-semibold justify-center items-center overflow-hidden isolate";
|
||
let cImage = "w-full object-cover";
|
||
const Avatar = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let classesBase;
|
||
let $$restProps = compute_rest_props($$props, [
|
||
"initials",
|
||
"fill",
|
||
"fontSize",
|
||
"src",
|
||
"fallback",
|
||
"action",
|
||
"actionParams",
|
||
"background",
|
||
"width",
|
||
"border",
|
||
"rounded",
|
||
"shadow",
|
||
"cursor"
|
||
]);
|
||
let { initials = "AB" } = $$props;
|
||
let { fill = "fill-token" } = $$props;
|
||
let { fontSize = 150 } = $$props;
|
||
let { src = "" } = $$props;
|
||
let { fallback = "" } = $$props;
|
||
let { action = () => {
|
||
} } = $$props;
|
||
let { actionParams = "" } = $$props;
|
||
let { background = "bg-surface-400-500-token" } = $$props;
|
||
let { width = "w-16" } = $$props;
|
||
let { border = "" } = $$props;
|
||
let { rounded = "rounded-full" } = $$props;
|
||
let { shadow = "" } = $$props;
|
||
let { cursor = "" } = $$props;
|
||
function prunedRestProps() {
|
||
delete $$restProps.class;
|
||
return $$restProps;
|
||
}
|
||
if ($$props.initials === void 0 && $$bindings.initials && initials !== void 0)
|
||
$$bindings.initials(initials);
|
||
if ($$props.fill === void 0 && $$bindings.fill && fill !== void 0)
|
||
$$bindings.fill(fill);
|
||
if ($$props.fontSize === void 0 && $$bindings.fontSize && fontSize !== void 0)
|
||
$$bindings.fontSize(fontSize);
|
||
if ($$props.src === void 0 && $$bindings.src && src !== void 0)
|
||
$$bindings.src(src);
|
||
if ($$props.fallback === void 0 && $$bindings.fallback && fallback !== void 0)
|
||
$$bindings.fallback(fallback);
|
||
if ($$props.action === void 0 && $$bindings.action && action !== void 0)
|
||
$$bindings.action(action);
|
||
if ($$props.actionParams === void 0 && $$bindings.actionParams && actionParams !== void 0)
|
||
$$bindings.actionParams(actionParams);
|
||
if ($$props.background === void 0 && $$bindings.background && background !== void 0)
|
||
$$bindings.background(background);
|
||
if ($$props.width === void 0 && $$bindings.width && width !== void 0)
|
||
$$bindings.width(width);
|
||
if ($$props.border === void 0 && $$bindings.border && border !== void 0)
|
||
$$bindings.border(border);
|
||
if ($$props.rounded === void 0 && $$bindings.rounded && rounded !== void 0)
|
||
$$bindings.rounded(rounded);
|
||
if ($$props.shadow === void 0 && $$bindings.shadow && shadow !== void 0)
|
||
$$bindings.shadow(shadow);
|
||
if ($$props.cursor === void 0 && $$bindings.cursor && cursor !== void 0)
|
||
$$bindings.cursor(cursor);
|
||
classesBase = `${cBase} ${background} ${width} ${border} ${rounded} ${shadow} ${cursor} ${$$props.class ?? ""}`;
|
||
return ` <figure class="${"avatar " + escape(classesBase, true)}" data-testid="avatar">${src ? `<img${spread(
|
||
[
|
||
{
|
||
class: "avatar-image " + escape(cImage, true)
|
||
},
|
||
{
|
||
style: escape_attribute_value($$props.style ?? "")
|
||
},
|
||
{ src: escape_attribute_value(src) },
|
||
{
|
||
alt: escape_attribute_value($$props.alt || "")
|
||
},
|
||
escape_object(prunedRestProps())
|
||
],
|
||
{}
|
||
)}>` : `<svg class="avatar-initials w-full h-full" viewBox="0 0 512 512"><text x="50%" y="50%" dominant-baseline="central" text-anchor="middle" font-weight="bold"${add_attribute("font-size", fontSize, 0)} class="${"avatar-text " + escape(fill, true)}">${escape(String(initials).substring(0, 2).toUpperCase())}</text></svg>`}</figure>`;
|
||
});
|
||
const cBackdrop$1 = "fixed top-0 left-0 right-0 bottom-0 bg-surface-backdrop-token p-4";
|
||
const cTransitionLayer = "w-full h-fit min-h-full overflow-y-auto flex justify-center";
|
||
const cModal = "block overflow-y-auto";
|
||
const cModalImage = "w-full h-auto";
|
||
const Modal = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let cPosition;
|
||
let classesBackdrop;
|
||
let classesTransitionLayer;
|
||
let classesModal;
|
||
let parent;
|
||
let $modalStore, $$unsubscribe_modalStore;
|
||
let $prefersReducedMotionStore, $$unsubscribe_prefersReducedMotionStore;
|
||
$$unsubscribe_prefersReducedMotionStore = subscribe(prefersReducedMotionStore, (value) => $prefersReducedMotionStore = value);
|
||
createEventDispatcher();
|
||
let { components = {} } = $$props;
|
||
let { position = "items-center" } = $$props;
|
||
let { background = "bg-surface-100-800-token" } = $$props;
|
||
let { width = "w-modal" } = $$props;
|
||
let { height = "h-auto" } = $$props;
|
||
let { padding = "p-4" } = $$props;
|
||
let { spacing = "space-y-4" } = $$props;
|
||
let { rounded = "rounded-container-token" } = $$props;
|
||
let { shadow = "shadow-xl" } = $$props;
|
||
let { zIndex = "z-[999]" } = $$props;
|
||
let { buttonNeutral = "variant-ghost-surface" } = $$props;
|
||
let { buttonPositive = "variant-filled" } = $$props;
|
||
let { buttonTextCancel = "Cancel" } = $$props;
|
||
let { buttonTextConfirm = "Confirm" } = $$props;
|
||
let { buttonTextSubmit = "Submit" } = $$props;
|
||
let { regionBackdrop = "" } = $$props;
|
||
let { regionHeader = "text-2xl font-bold" } = $$props;
|
||
let { regionBody = "max-h-[200px] overflow-hidden" } = $$props;
|
||
let { regionFooter = "flex justify-end space-x-2" } = $$props;
|
||
let { transitions = !$prefersReducedMotionStore } = $$props;
|
||
let { transitionIn = fly } = $$props;
|
||
let { transitionInParams = { duration: 150, opacity: 0, x: 0, y: 100 } } = $$props;
|
||
let { transitionOut = fly } = $$props;
|
||
let { transitionOutParams = { duration: 150, opacity: 0, x: 0, y: 100 } } = $$props;
|
||
let promptValue;
|
||
const buttonTextDefaults = {
|
||
buttonTextCancel,
|
||
buttonTextConfirm,
|
||
buttonTextSubmit
|
||
};
|
||
let currentComponent;
|
||
let modalElement;
|
||
let windowHeight;
|
||
let backdropOverflow = "overflow-y-hidden";
|
||
const modalStore = getModalStore();
|
||
$$unsubscribe_modalStore = subscribe(modalStore, (value) => $modalStore = value);
|
||
function handleModals(modals) {
|
||
if (modals[0].type === "prompt")
|
||
promptValue = modals[0].value;
|
||
buttonTextCancel = modals[0].buttonTextCancel || buttonTextDefaults.buttonTextCancel;
|
||
buttonTextConfirm = modals[0].buttonTextConfirm || buttonTextDefaults.buttonTextConfirm;
|
||
buttonTextSubmit = modals[0].buttonTextSubmit || buttonTextDefaults.buttonTextSubmit;
|
||
currentComponent = typeof modals[0].component === "string" ? components[modals[0].component] : modals[0].component;
|
||
}
|
||
function onModalHeightChange(modal) {
|
||
let modalHeight = modal?.clientHeight;
|
||
if (!modalHeight)
|
||
modalHeight = modal?.firstChild?.clientHeight;
|
||
if (!modalHeight)
|
||
return;
|
||
if (modalHeight > windowHeight) {
|
||
backdropOverflow = "overflow-y-auto";
|
||
} else {
|
||
backdropOverflow = "overflow-y-hidden";
|
||
}
|
||
}
|
||
function onClose() {
|
||
if ($modalStore[0].response)
|
||
$modalStore[0].response(false);
|
||
modalStore.close();
|
||
}
|
||
if ($$props.components === void 0 && $$bindings.components && components !== void 0)
|
||
$$bindings.components(components);
|
||
if ($$props.position === void 0 && $$bindings.position && position !== void 0)
|
||
$$bindings.position(position);
|
||
if ($$props.background === void 0 && $$bindings.background && background !== void 0)
|
||
$$bindings.background(background);
|
||
if ($$props.width === void 0 && $$bindings.width && width !== void 0)
|
||
$$bindings.width(width);
|
||
if ($$props.height === void 0 && $$bindings.height && height !== void 0)
|
||
$$bindings.height(height);
|
||
if ($$props.padding === void 0 && $$bindings.padding && padding !== void 0)
|
||
$$bindings.padding(padding);
|
||
if ($$props.spacing === void 0 && $$bindings.spacing && spacing !== void 0)
|
||
$$bindings.spacing(spacing);
|
||
if ($$props.rounded === void 0 && $$bindings.rounded && rounded !== void 0)
|
||
$$bindings.rounded(rounded);
|
||
if ($$props.shadow === void 0 && $$bindings.shadow && shadow !== void 0)
|
||
$$bindings.shadow(shadow);
|
||
if ($$props.zIndex === void 0 && $$bindings.zIndex && zIndex !== void 0)
|
||
$$bindings.zIndex(zIndex);
|
||
if ($$props.buttonNeutral === void 0 && $$bindings.buttonNeutral && buttonNeutral !== void 0)
|
||
$$bindings.buttonNeutral(buttonNeutral);
|
||
if ($$props.buttonPositive === void 0 && $$bindings.buttonPositive && buttonPositive !== void 0)
|
||
$$bindings.buttonPositive(buttonPositive);
|
||
if ($$props.buttonTextCancel === void 0 && $$bindings.buttonTextCancel && buttonTextCancel !== void 0)
|
||
$$bindings.buttonTextCancel(buttonTextCancel);
|
||
if ($$props.buttonTextConfirm === void 0 && $$bindings.buttonTextConfirm && buttonTextConfirm !== void 0)
|
||
$$bindings.buttonTextConfirm(buttonTextConfirm);
|
||
if ($$props.buttonTextSubmit === void 0 && $$bindings.buttonTextSubmit && buttonTextSubmit !== void 0)
|
||
$$bindings.buttonTextSubmit(buttonTextSubmit);
|
||
if ($$props.regionBackdrop === void 0 && $$bindings.regionBackdrop && regionBackdrop !== void 0)
|
||
$$bindings.regionBackdrop(regionBackdrop);
|
||
if ($$props.regionHeader === void 0 && $$bindings.regionHeader && regionHeader !== void 0)
|
||
$$bindings.regionHeader(regionHeader);
|
||
if ($$props.regionBody === void 0 && $$bindings.regionBody && regionBody !== void 0)
|
||
$$bindings.regionBody(regionBody);
|
||
if ($$props.regionFooter === void 0 && $$bindings.regionFooter && regionFooter !== void 0)
|
||
$$bindings.regionFooter(regionFooter);
|
||
if ($$props.transitions === void 0 && $$bindings.transitions && transitions !== void 0)
|
||
$$bindings.transitions(transitions);
|
||
if ($$props.transitionIn === void 0 && $$bindings.transitionIn && transitionIn !== void 0)
|
||
$$bindings.transitionIn(transitionIn);
|
||
if ($$props.transitionInParams === void 0 && $$bindings.transitionInParams && transitionInParams !== void 0)
|
||
$$bindings.transitionInParams(transitionInParams);
|
||
if ($$props.transitionOut === void 0 && $$bindings.transitionOut && transitionOut !== void 0)
|
||
$$bindings.transitionOut(transitionOut);
|
||
if ($$props.transitionOutParams === void 0 && $$bindings.transitionOutParams && transitionOutParams !== void 0)
|
||
$$bindings.transitionOutParams(transitionOutParams);
|
||
{
|
||
if ($modalStore.length)
|
||
handleModals($modalStore);
|
||
}
|
||
{
|
||
onModalHeightChange(modalElement);
|
||
}
|
||
cPosition = $modalStore[0]?.position ?? position;
|
||
classesBackdrop = `${cBackdrop$1} ${regionBackdrop} ${zIndex} ${$$props.class ?? ""} ${$modalStore[0]?.backdropClasses ?? ""}`;
|
||
classesTransitionLayer = `${cTransitionLayer} ${cPosition ?? ""}`;
|
||
classesModal = `${cModal} ${background} ${width} ${height} ${padding} ${spacing} ${rounded} ${shadow} ${$modalStore[0]?.modalClasses ?? ""}`;
|
||
parent = {
|
||
position,
|
||
// ---
|
||
background,
|
||
width,
|
||
height,
|
||
padding,
|
||
spacing,
|
||
rounded,
|
||
shadow,
|
||
// ---
|
||
buttonNeutral,
|
||
buttonPositive,
|
||
buttonTextCancel,
|
||
buttonTextConfirm,
|
||
buttonTextSubmit,
|
||
// ---
|
||
regionBackdrop,
|
||
regionHeader,
|
||
regionBody,
|
||
regionFooter,
|
||
// ---
|
||
onClose
|
||
};
|
||
$$unsubscribe_modalStore();
|
||
$$unsubscribe_prefersReducedMotionStore();
|
||
return ` ${$modalStore.length > 0 ? ` <div class="${"modal-backdrop " + escape(classesBackdrop, true) + " " + escape(backdropOverflow, true)}" data-testid="modal-backdrop"> <div class="${"modal-transition " + escape(classesTransitionLayer, true)}">${$modalStore[0].type !== "component" ? ` <div class="${"modal " + escape(classesModal, true)}" data-testid="modal" role="dialog" aria-modal="true"${add_attribute("aria-label", $modalStore[0].title ?? "", 0)}${add_attribute("this", modalElement, 0)}> ${$modalStore[0]?.title ? `<header class="${"modal-header " + escape(regionHeader, true)}"><!-- HTML_TAG_START -->${$modalStore[0].title}<!-- HTML_TAG_END --></header>` : ``} ${$modalStore[0]?.body ? `<article class="${"modal-body " + escape(regionBody, true)}"><!-- HTML_TAG_START -->${$modalStore[0].body}<!-- HTML_TAG_END --></article>` : ``} ${$modalStore[0]?.image && typeof $modalStore[0]?.image === "string" ? `<img class="${"modal-image " + escape(cModalImage, true)}"${add_attribute("src", $modalStore[0]?.image, 0)} alt="Modal">` : ``} ${$modalStore[0].type === "alert" ? ` <footer class="${"modal-footer " + escape(regionFooter, true)}"><button type="button" class="${"btn " + escape(buttonNeutral, true)}">${escape(buttonTextCancel)}</button></footer>` : `${$modalStore[0].type === "confirm" ? ` <footer class="${"modal-footer " + escape(regionFooter, true)}"><button type="button" class="${"btn " + escape(buttonNeutral, true)}">${escape(buttonTextCancel)}</button> <button type="button" class="${"btn " + escape(buttonPositive, true)}">${escape(buttonTextConfirm)}</button></footer>` : `${$modalStore[0].type === "prompt" ? ` <form class="space-y-4"><input${spread(
|
||
[
|
||
{ class: "modal-prompt-input input" },
|
||
{ name: "prompt" },
|
||
{ type: "text" },
|
||
escape_object($modalStore[0].valueAttr)
|
||
],
|
||
{}
|
||
)}${add_attribute("value", promptValue, 0)}> <footer class="${"modal-footer " + escape(regionFooter, true)}"><button type="button" class="${"btn " + escape(buttonNeutral, true)}">${escape(buttonTextCancel)}</button> <button type="submit" class="${"btn " + escape(buttonPositive, true)}">${escape(buttonTextSubmit)}</button></footer></form>` : ``}`}`}</div>` : ` <div class="${"modal contents " + escape($modalStore[0]?.modalClasses ?? "", true)}" data-testid="modal-component" role="dialog" aria-modal="true"${add_attribute("aria-label", $modalStore[0].title ?? "", 0)}${add_attribute("this", modalElement, 0)}>${currentComponent?.slot ? `${validate_component(currentComponent?.ref || missing_component, "svelte:component").$$render($$result, Object.assign({}, currentComponent?.props, { parent }), {}, {
|
||
default: () => {
|
||
return `<!-- HTML_TAG_START -->${currentComponent?.slot}<!-- HTML_TAG_END -->`;
|
||
}
|
||
})}` : `${validate_component(currentComponent?.ref || missing_component, "svelte:component").$$render($$result, Object.assign({}, currentComponent?.props, { parent }), {}, {})}`}</div>`}</div></div>` : ``}`;
|
||
});
|
||
const cBackdrop = "fixed top-0 left-0 right-0 bottom-0 flex";
|
||
const cDrawer = "overflow-y-auto transition-transform";
|
||
const Drawer = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let classesPosition;
|
||
let classesWidth;
|
||
let classesHeight;
|
||
let classesRounded;
|
||
let classesBackdrop;
|
||
let classesDrawer;
|
||
let $drawerStore, $$unsubscribe_drawerStore;
|
||
let $prefersReducedMotionStore, $$unsubscribe_prefersReducedMotionStore;
|
||
$$unsubscribe_prefersReducedMotionStore = subscribe(prefersReducedMotionStore, (value) => $prefersReducedMotionStore = value);
|
||
createEventDispatcher();
|
||
let { position = "left" } = $$props;
|
||
let { bgDrawer = "bg-surface-100-800-token" } = $$props;
|
||
let { border = "" } = $$props;
|
||
let { rounded = "" } = $$props;
|
||
let { shadow = "shadow-xl" } = $$props;
|
||
let { width = "" } = $$props;
|
||
let { height = "" } = $$props;
|
||
let { bgBackdrop = "bg-surface-backdrop-token" } = $$props;
|
||
let { blur = "" } = $$props;
|
||
let { padding = "" } = $$props;
|
||
let { zIndex = "z-40" } = $$props;
|
||
let { regionBackdrop = "" } = $$props;
|
||
let { regionDrawer = "" } = $$props;
|
||
let { labelledby = "" } = $$props;
|
||
let { describedby = "" } = $$props;
|
||
let { duration = 200 } = $$props;
|
||
let { transitions = !$prefersReducedMotionStore } = $$props;
|
||
let { opacityTransition = true } = $$props;
|
||
const presets = {
|
||
top: {
|
||
alignment: "items-start",
|
||
width: "w-full",
|
||
height: "h-[50%]",
|
||
rounded: "rounded-bl-container-token rounded-br-container-token"
|
||
},
|
||
bottom: {
|
||
alignment: "items-end",
|
||
width: "w-full",
|
||
height: " h-[50%]",
|
||
rounded: "rounded-tl-container-token rounded-tr-container-token"
|
||
},
|
||
left: {
|
||
alignment: "justify-start",
|
||
width: "w-[90%]",
|
||
height: "h-full",
|
||
rounded: "rounded-tr-container-token rounded-br-container-token"
|
||
},
|
||
right: {
|
||
alignment: "justify-end",
|
||
width: "w-[90%]",
|
||
height: "h-full",
|
||
rounded: "rounded-tl-container-token rounded-bl-container-token"
|
||
}
|
||
};
|
||
let elemBackdrop;
|
||
let elemDrawer;
|
||
const drawerStore = getDrawerStore();
|
||
$$unsubscribe_drawerStore = subscribe(drawerStore, (value) => $drawerStore = value);
|
||
const propDefaults = {
|
||
position,
|
||
bgBackdrop,
|
||
blur,
|
||
padding,
|
||
bgDrawer,
|
||
border,
|
||
rounded,
|
||
shadow,
|
||
width,
|
||
height,
|
||
opacityTransition,
|
||
regionBackdrop,
|
||
regionDrawer,
|
||
labelledby,
|
||
describedby,
|
||
duration
|
||
};
|
||
function applyPropSettings(settings) {
|
||
position = settings.position || propDefaults.position;
|
||
bgBackdrop = settings.bgBackdrop || propDefaults.bgBackdrop;
|
||
blur = settings.blur || propDefaults.blur;
|
||
padding = settings.padding || propDefaults.padding;
|
||
bgDrawer = settings.bgDrawer || propDefaults.bgDrawer;
|
||
border = settings.border || propDefaults.border;
|
||
rounded = settings.rounded || propDefaults.rounded;
|
||
shadow = settings.shadow || propDefaults.shadow;
|
||
width = settings.width || propDefaults.width;
|
||
height = settings.height || propDefaults.height;
|
||
regionBackdrop = settings.regionBackdrop || propDefaults.regionBackdrop;
|
||
regionDrawer = settings.regionDrawer || propDefaults.regionDrawer;
|
||
labelledby = settings.labelledby || propDefaults.labelledby;
|
||
describedby = settings.describedby || propDefaults.describedby;
|
||
opacityTransition = settings.opacityTransition || propDefaults.opacityTransition;
|
||
duration = settings.duration || propDefaults.duration;
|
||
}
|
||
drawerStore.subscribe((settings) => {
|
||
if (settings.open !== true)
|
||
return;
|
||
applyPropSettings(settings);
|
||
});
|
||
if ($$props.position === void 0 && $$bindings.position && position !== void 0)
|
||
$$bindings.position(position);
|
||
if ($$props.bgDrawer === void 0 && $$bindings.bgDrawer && bgDrawer !== void 0)
|
||
$$bindings.bgDrawer(bgDrawer);
|
||
if ($$props.border === void 0 && $$bindings.border && border !== void 0)
|
||
$$bindings.border(border);
|
||
if ($$props.rounded === void 0 && $$bindings.rounded && rounded !== void 0)
|
||
$$bindings.rounded(rounded);
|
||
if ($$props.shadow === void 0 && $$bindings.shadow && shadow !== void 0)
|
||
$$bindings.shadow(shadow);
|
||
if ($$props.width === void 0 && $$bindings.width && width !== void 0)
|
||
$$bindings.width(width);
|
||
if ($$props.height === void 0 && $$bindings.height && height !== void 0)
|
||
$$bindings.height(height);
|
||
if ($$props.bgBackdrop === void 0 && $$bindings.bgBackdrop && bgBackdrop !== void 0)
|
||
$$bindings.bgBackdrop(bgBackdrop);
|
||
if ($$props.blur === void 0 && $$bindings.blur && blur !== void 0)
|
||
$$bindings.blur(blur);
|
||
if ($$props.padding === void 0 && $$bindings.padding && padding !== void 0)
|
||
$$bindings.padding(padding);
|
||
if ($$props.zIndex === void 0 && $$bindings.zIndex && zIndex !== void 0)
|
||
$$bindings.zIndex(zIndex);
|
||
if ($$props.regionBackdrop === void 0 && $$bindings.regionBackdrop && regionBackdrop !== void 0)
|
||
$$bindings.regionBackdrop(regionBackdrop);
|
||
if ($$props.regionDrawer === void 0 && $$bindings.regionDrawer && regionDrawer !== void 0)
|
||
$$bindings.regionDrawer(regionDrawer);
|
||
if ($$props.labelledby === void 0 && $$bindings.labelledby && labelledby !== void 0)
|
||
$$bindings.labelledby(labelledby);
|
||
if ($$props.describedby === void 0 && $$bindings.describedby && describedby !== void 0)
|
||
$$bindings.describedby(describedby);
|
||
if ($$props.duration === void 0 && $$bindings.duration && duration !== void 0)
|
||
$$bindings.duration(duration);
|
||
if ($$props.transitions === void 0 && $$bindings.transitions && transitions !== void 0)
|
||
$$bindings.transitions(transitions);
|
||
if ($$props.opacityTransition === void 0 && $$bindings.opacityTransition && opacityTransition !== void 0)
|
||
$$bindings.opacityTransition(opacityTransition);
|
||
classesPosition = presets[position].alignment;
|
||
classesWidth = width ? width : presets[position].width;
|
||
classesHeight = height ? height : presets[position].height;
|
||
classesRounded = rounded ? rounded : presets[position].rounded;
|
||
classesBackdrop = `${cBackdrop} ${bgBackdrop} ${padding} ${blur} ${classesPosition} ${regionBackdrop} ${zIndex} ${$$props.class ?? ""}`;
|
||
classesDrawer = `${cDrawer} ${bgDrawer} ${border} ${rounded} ${shadow} ${classesWidth} ${classesHeight} ${classesRounded} ${regionDrawer}`;
|
||
$$unsubscribe_drawerStore();
|
||
$$unsubscribe_prefersReducedMotionStore();
|
||
return ` ${$drawerStore.open === true ? ` <div class="${"drawer-backdrop " + escape(classesBackdrop, true)}" data-testid="drawer-backdrop"${add_attribute("this", elemBackdrop, 0)}> <div class="${"drawer " + escape(classesDrawer, true)}" data-testid="drawer" role="dialog" aria-modal="true"${add_attribute("aria-labelledby", labelledby, 0)}${add_attribute("aria-describedby", describedby, 0)}${add_attribute("this", elemDrawer, 0)}> ${slots.default ? slots.default({}) : ``}</div></div>` : ``}`;
|
||
});
|
||
const cTrack = "cursor-pointer";
|
||
const cThumb = "aspect-square scale-[0.8] flex justify-center items-center";
|
||
const cIcon = "w-[70%] aspect-square";
|
||
const LightSwitch = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let trackBg;
|
||
let thumbBg;
|
||
let thumbPosition;
|
||
let iconFill;
|
||
let classesTrack;
|
||
let classesThumb;
|
||
let classesIcon;
|
||
let $modeCurrent, $$unsubscribe_modeCurrent;
|
||
$$unsubscribe_modeCurrent = subscribe(modeCurrent, (value) => $modeCurrent = value);
|
||
let { title = "Toggle light or dark mode." } = $$props;
|
||
let { bgLight = "bg-surface-50" } = $$props;
|
||
let { bgDark = "bg-surface-900" } = $$props;
|
||
let { fillLight = "fill-surface-50" } = $$props;
|
||
let { fillDark = "fill-surface-900" } = $$props;
|
||
let { width = "w-12" } = $$props;
|
||
let { height = "h-6" } = $$props;
|
||
let { ring = "ring-[1px] ring-surface-500/30" } = $$props;
|
||
let { rounded = "rounded-token" } = $$props;
|
||
const cTransition = `transition-all duration-[200ms]`;
|
||
const svgPath = {
|
||
sun: "M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM352 256c0 53-43 96-96 96s-96-43-96-96s43-96 96-96s96 43 96 96zm32 0c0-70.7-57.3-128-128-128s-128 57.3-128 128s57.3 128 128 128s128-57.3 128-128z",
|
||
moon: "M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"
|
||
};
|
||
if ($$props.title === void 0 && $$bindings.title && title !== void 0)
|
||
$$bindings.title(title);
|
||
if ($$props.bgLight === void 0 && $$bindings.bgLight && bgLight !== void 0)
|
||
$$bindings.bgLight(bgLight);
|
||
if ($$props.bgDark === void 0 && $$bindings.bgDark && bgDark !== void 0)
|
||
$$bindings.bgDark(bgDark);
|
||
if ($$props.fillLight === void 0 && $$bindings.fillLight && fillLight !== void 0)
|
||
$$bindings.fillLight(fillLight);
|
||
if ($$props.fillDark === void 0 && $$bindings.fillDark && fillDark !== void 0)
|
||
$$bindings.fillDark(fillDark);
|
||
if ($$props.width === void 0 && $$bindings.width && width !== void 0)
|
||
$$bindings.width(width);
|
||
if ($$props.height === void 0 && $$bindings.height && height !== void 0)
|
||
$$bindings.height(height);
|
||
if ($$props.ring === void 0 && $$bindings.ring && ring !== void 0)
|
||
$$bindings.ring(ring);
|
||
if ($$props.rounded === void 0 && $$bindings.rounded && rounded !== void 0)
|
||
$$bindings.rounded(rounded);
|
||
trackBg = $modeCurrent === true ? bgLight : bgDark;
|
||
thumbBg = $modeCurrent === true ? bgDark : bgLight;
|
||
thumbPosition = $modeCurrent === true ? "translate-x-[100%]" : "";
|
||
iconFill = $modeCurrent === true ? fillLight : fillDark;
|
||
classesTrack = `${cTrack} ${cTransition} ${width} ${height} ${ring} ${rounded} ${trackBg} ${$$props.class ?? ""}`;
|
||
classesThumb = `${cThumb} ${cTransition} ${height} ${rounded} ${thumbBg} ${thumbPosition}`;
|
||
classesIcon = `${cIcon} ${iconFill}`;
|
||
$$unsubscribe_modeCurrent();
|
||
return `${$$result.head += `<!-- HEAD_svelte-gewkj4_START --><!-- HTML_TAG_START -->${`<script nonce="%sveltekit.nonce%">(${setInitialClassState.toString()})();<\/script>`}<!-- HTML_TAG_END --><!-- HEAD_svelte-gewkj4_END -->`, ""} <div class="${"lightswitch-track " + escape(classesTrack, true)}" role="switch" aria-label="Light Switch"${add_attribute("aria-checked", $modeCurrent, 0)}${add_attribute("title", title, 0)} tabindex="0"> <div class="${"lightswitch-thumb " + escape(classesThumb, true)}"> <svg class="${"lightswitch-icon " + escape(classesIcon, true)}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path${add_attribute("d", $modeCurrent ? svgPath.sun : svgPath.moon, 0)}></path></svg></div></div>`;
|
||
});
|
||
const CodeBlockModal = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let $modalStore, $$unsubscribe_modalStore;
|
||
const modalStore = getModalStore();
|
||
$$unsubscribe_modalStore = subscribe(modalStore, (value) => $modalStore = value);
|
||
$$unsubscribe_modalStore();
|
||
return `<div class="card p-4 w-[85%]">${validate_component(CodeBlock, "CodeBlock").$$render(
|
||
$$result,
|
||
{
|
||
lineNumbers: true,
|
||
language: $modalStore[0]?.meta?.language || "json",
|
||
code: $modalStore[0]?.meta?.code || ""
|
||
},
|
||
{},
|
||
{}
|
||
)}</div>`;
|
||
});
|
||
const HomeSVG = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
return `<svg class="w-6 h-6 stroke-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path></svg>`;
|
||
});
|
||
const ReportsSVG = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
return `<svg class="w-6 h-6 stroke-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 8v8m-4-5v5m-4-2v2m-2 4h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>`;
|
||
});
|
||
const navigation = [
|
||
{
|
||
name: "Main",
|
||
content: [
|
||
{
|
||
url: "/home",
|
||
name: "Home",
|
||
description: "Home page for the application.",
|
||
icon: HomeSVG
|
||
},
|
||
{
|
||
url: "/home/example-pages",
|
||
name: "Example Pages",
|
||
description: "a list of example pages showcasing how to implement the IdentityNow SDK.",
|
||
icon: ReportsSVG
|
||
},
|
||
{
|
||
url: "/home/example-form",
|
||
name: "Example Form",
|
||
description: "A form example using the IdentityNow SDK."
|
||
},
|
||
{
|
||
url: "/home/form-integration",
|
||
name: "SailPoint Form Integration",
|
||
description: "A form example using the IdentityNow SDK."
|
||
}
|
||
]
|
||
}
|
||
];
|
||
const Sidebar = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let $page, $$unsubscribe_page;
|
||
$$unsubscribe_page = subscribe(page, (value) => $page = value);
|
||
$$unsubscribe_page();
|
||
return `<div class="${escape($$props.class ?? "", true) + " w-[144px] overflow-hidden bg-surface-50-900-token h-full"}"><div class="flex flex-col w-36 items-center h-full overflow-hidden"><div class="w-full px-2"><div class="flex flex-col items-center w-full mt-3 border-surface-400-500-token">${each(navigation, (section) => {
|
||
return `${each(section.content, (link) => {
|
||
return `<a${add_attribute("href", link.url, 0)} data-sveltekit-preload-data="hover" class="${[
|
||
"flex items-center w-full h-12 px-3 mt-2 rounded",
|
||
(link.url === $page.url.pathname ? "bg-surface-active-token" : "") + " " + (link.url === $page.url.pathname ? "!text-white" : "")
|
||
].join(" ").trim()}">${link.icon ? `${validate_component(link.icon || missing_component, "svelte:component").$$render($$result, {}, {}, {})}` : ``} <p class="ml-2 text-sm font-medium">${escape(link.name)}</p> </a>`;
|
||
})}`;
|
||
})}</div></div></div></div>`;
|
||
});
|
||
const HamburgerSVG = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let $$restProps = compute_rest_props($$props, []);
|
||
return `<svg${add_attribute("class", $$restProps.class || "", 0)} width="800px" height="800px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" id="Editable-line" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><line fill="none" id="XMLID_103_" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" x1="7" x2="25" y1="16" y2="16"></line><line fill="none" id="XMLID_102_" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" x1="7" x2="25" y1="25" y2="25"></line><line fill="none" id="XMLID_101_" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" x1="7" x2="25" y1="7" y2="7"></line></svg>`;
|
||
});
|
||
const SidebarDrawer = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let classesDrawer;
|
||
let $drawerStore, $$unsubscribe_drawerStore;
|
||
const drawerStore = getDrawerStore();
|
||
$$unsubscribe_drawerStore = subscribe(drawerStore, (value) => $drawerStore = value);
|
||
classesDrawer = $drawerStore.id === "doc-sidenav" ? "lg:hidden" : "";
|
||
$$unsubscribe_drawerStore();
|
||
return `${validate_component(Drawer, "Drawer").$$render($$result, { width: "w-[144px]", class: classesDrawer }, {}, {
|
||
default: () => {
|
||
return `${$drawerStore.id === "doc-sidenav" ? ` ${validate_component(Sidebar, "Sidebar").$$render($$result, {}, {}, {})}` : ``}`;
|
||
}
|
||
})}`;
|
||
});
|
||
const Layout = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
||
let $page, $$unsubscribe_page;
|
||
$$unsubscribe_page = subscribe(page, (value) => $page = value);
|
||
initializeStores();
|
||
const modalRegistry = {
|
||
// Set a unique modal ID, then pass the component reference
|
||
codeBlockModal: { ref: CodeBlockModal }
|
||
};
|
||
storePopup.set({
|
||
computePosition,
|
||
autoUpdate,
|
||
offset,
|
||
shift,
|
||
flip,
|
||
arrow
|
||
});
|
||
let { data } = $$props;
|
||
HighlightJS.registerLanguage("xml", xml);
|
||
HighlightJS.registerLanguage("css", css);
|
||
HighlightJS.registerLanguage("json", json);
|
||
HighlightJS.registerLanguage("javascript", javascript$1);
|
||
HighlightJS.registerLanguage("typescript", typescript);
|
||
HighlightJS.registerLanguage("shell", shell);
|
||
storeHighlightJs.set(HighlightJS);
|
||
let crumbs = [];
|
||
getDrawerStore();
|
||
if ($$props.data === void 0 && $$bindings.data && data !== void 0)
|
||
$$bindings.data(data);
|
||
{
|
||
{
|
||
const tokens = $page.url.pathname.split("/").filter((t) => t !== "");
|
||
let tokenPath = "";
|
||
crumbs = tokens.map((t) => {
|
||
tokenPath += "/" + t;
|
||
return {
|
||
label: t.split("-").map((word) => capitalize(word)).join(" "),
|
||
href: tokenPath
|
||
};
|
||
});
|
||
crumbs = crumbs.filter((c) => c.label !== "Logout" && c.label !== "Callback");
|
||
}
|
||
}
|
||
$$unsubscribe_page();
|
||
return `${validate_component(Modal, "Modal").$$render($$result, { components: modalRegistry }, {}, {})} ${validate_component(SidebarDrawer, "SidebarDrawer").$$render($$result, {}, {}, {})} ${validate_component(AppShell, "AppShell").$$render($$result, {}, {}, {
|
||
sidebarLeft: () => {
|
||
return `${data.tokenDetails ? `${validate_component(Sidebar, "Sidebar").$$render($$result, { class: "hidden lg:grid overflow-hidden" }, {}, {})}` : ``} `;
|
||
},
|
||
header: () => {
|
||
return `${validate_component(AppBar, "AppBar").$$render($$result, { padding: "p-2", class: "h-![72px]" }, {}, {
|
||
trail: () => {
|
||
return `${validate_component(LightSwitch, "LightSwitch").$$render($$result, {}, {}, {})} ${data.tokenDetails ? `<div class="rounded-full w-fit">${validate_component(Avatar, "Avatar").$$render(
|
||
$$result,
|
||
{
|
||
initials: parseInitials(data?.tokenDetails?.user_name),
|
||
border: "hover:border-2 border-surface-300-600-token hover:!border-primary-500",
|
||
cursor: "cursor-pointer",
|
||
width: "w-10"
|
||
},
|
||
{},
|
||
{}
|
||
)} <div class="card p-4 w-72 !shadow-xl bg-surface-100-800-token" data-popup="popupAccount"><div class="arrow bg-surface-50-900-token"></div> <div class="flex flex-col gap-2"><div class="space-y-4">${validate_component(Avatar, "Avatar").$$render(
|
||
$$result,
|
||
{
|
||
initials: parseInitials(data?.tokenDetails?.user_name),
|
||
width: "w-16"
|
||
},
|
||
{},
|
||
{}
|
||
)} <div><p class="font-bold">${escape(data?.tokenDetails?.user_name)}</p> <div class="flex flex-wrap gap-4"><small><span class="opacity-50" data-svelte-h="svelte-1n6iv9c">Tenant:</span> <strong>${escape(data?.tokenDetails?.org)}</strong></small> <small><span class="opacity-50" data-svelte-h="svelte-1xersvb">Pod:</span> <strong>${escape(data?.tokenDetails?.pod)}</strong></small></div> <small data-svelte-h="svelte-emcw36"><span class="opacity-50">Scopes:</span></small> <div class="flex gap-4 flex-wrap">${each(data?.tokenDetails?.scope, (scope) => {
|
||
return `<small><strong></strong>${escape(scope)}</small>`;
|
||
})}</div></div> <a href="/logout" class="btn variant-soft w-full" data-svelte-h="svelte-1bzcp1l">Logout</a></div></div></div></div>` : ``} `;
|
||
},
|
||
lead: () => {
|
||
return `<div class="flex items-center space-x-4">${data.tokenDetails ? `<button class="btn-icon btn-icon-sm lg:!hidden">${validate_component(HamburgerSVG, "HamburgerSvg").$$render($$result, { class: "w-6 h-6" }, {}, {})}</button>` : ``} <img class="h-8 w-8" src="/logo.ico" alt="SailPoint TetraSail"></div> `;
|
||
},
|
||
default: () => {
|
||
return `<p class="text-xl lg:!block hidden" data-svelte-h="svelte-u6prqd">IdentityNow Starter Application</p>`;
|
||
}
|
||
})} `;
|
||
},
|
||
default: () => {
|
||
return ` <div class="flex flex-col h-full">${crumbs.length > 0 ? `<div class="pl-2 pt-2 pr-2"><ol class="breadcrumb card p-2">${each(crumbs, (crumb, i) => {
|
||
return ` ${i < crumbs.length - 1 ? `<li class="crumb"><a class="anchor"${add_attribute("href", crumb.href, 0)}>${escape(crumb.label)}</a></li> <li class="crumb-separator" aria-hidden data-svelte-h="svelte-16i7nlm">›</li>` : `<li class="crumb">${escape(crumb.label)}</li>`}`;
|
||
})}</ol></div>` : ``} <div class="p-2 grow">${``}</div></div> `;
|
||
}
|
||
})}`;
|
||
});
|
||
|
||
export { Layout as default };
|
||
//# sourceMappingURL=_layout.svelte-LzGJOOI2.js.map
|