feat: migrate to starlight

This commit is contained in:
DuroCodes
2024-05-06 17:15:30 -04:00
parent 767acedea7
commit bb190f2d81
15140 changed files with 2828326 additions and 35408 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Tibor Schiemann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,15 @@
# @expressive-code/plugin-text-markers
A default plugin of Expressive Code, an engine for presenting source code on the web.
It allows you to mark entire lines & line ranges, as well as individual text inside your lines using a selection of marker styles (marked, inserted, deleted).
It also ensures accessible color contrast of the marked code, automatically tweaking the text colors if necessary while keeping syntax highlighting intact.
## Documentation
[Read this plugin's documentation](https://expressive-code.com/key-features/text-markers/) on the Expressive Code website to learn more about its features.
## Installation (not required)
No installation is required. This package is **installed by default** by our higher-level packages.

View File

@@ -0,0 +1,230 @@
import { ExpressiveCodePlugin } from '@expressive-code/core';
interface TextMarkersStyleSettings {
/**
* The margin between the code block border and the line marker accent bar
* displayed on the left side of a full-line text marker.
* @default '0rem'
*/
lineMarkerAccentMargin: string;
/**
* The width of the line marker accent bar. This is the vertical border-like bar
* displayed on the left side of a full-line text marker.
* @default '0.15rem'
*/
lineMarkerAccentWidth: string;
/**
* The inline padding (= left & right padding in horizontal writing mode)
* around line marker labels.
*
* @note If your line marker labels overlap with the code content,
* consider increasing the root style setting `codePaddingInline`.
*
* @default '0.2rem'
*/
lineMarkerLabelPaddingInline: string;
/**
* The text color of the optional labels that can be displayed on the left side
* of a full-line text marker.
* @default 'white'
*/
lineMarkerLabelColor: string;
/**
* The margin between the code block border and the diff indicator (e.g. `+` or `-`)
* displayed on the left side of a full-line text marker.
* @default '0.3rem'
*/
lineDiffIndicatorMarginLeft: string;
/**
* The width of the border around inline text markers, rendered in a way
* that does not cause marked code to shift.
* @default '1.5px'
*/
inlineMarkerBorderWidth: string;
/**
* The border radius of inline text markers.
* @default '0.2rem'
*/
inlineMarkerBorderRadius: string;
/**
* The inline padding of inline text markers. Keep this low to prevent marked code
* from shifting too much compared to the original text.
* @default '0.15rem'
*/
inlineMarkerPadding: string;
/**
* The LCH hue to be used for marked text (text marker type `mark`).
* @default '284' (a blue hue)
*/
markHue: string;
/**
* The LCH hue to be used for inserted text (text marker type `ins`).
* @default '136' (a green hue)
*/
insHue: string;
/**
* The LCH hue to be used for deleted text (text marker type `del`).
* @default '33' (a red hue)
*/
delHue: string;
/**
* The LCH chroma to be used for all text marker types.
*
* The chroma value defines the saturation of the color. Higher values lead to
* more saturated colors, lower values lead to less saturated colors.
*
* @default '40'
*/
defaultChroma: string;
/**
* The LCH luminance to be used for all text marker types.
* @default
* ['32%', '75%'] // 32% for dark themes, 75% for light themes
*/
defaultLuminance: string;
/**
* The opacity of the background color of all text marker types.
* @default '50%'
*/
backgroundOpacity: string;
/**
* The LCH luminance to be used for the border color of all text marker types.
* @default '48%'
*/
borderLuminance: string;
/**
* The opacity of the border color of all text marker types.
* @default '81.6%'
*/
borderOpacity: string;
/**
* The LCH luminance to be used for the diff indicator (e.g. `+` or `-`).
* @default
* ['67%', '40%'] // 67% for dark themes, 40% for light themes
*/
indicatorLuminance: string;
/**
* The opacity of the diff indicator (e.g. `+` or `-`).
* @default '81.6%'
*/
indicatorOpacity: string;
/**
* The content to be displayed inside the diff indicator of inserted lines.
*
* Note that this is used as the `content` value in a CSS pseudo-element,
* so you need to wrap any text in additional quotes.
*
* @default "'+'"
*/
insDiffIndicatorContent: string;
/**
* The content to be displayed inside the diff indicator of deleted lines.
*
* Note that this is used as the `content` value in a CSS pseudo-element,
* so you need to wrap any text in additional quotes.
*
* @default "'-'"
*/
delDiffIndicatorContent: string;
/**
* The background color of marked text (text marker type `mark`).
* @default
* lch(<defaultLuminance> <defaultChroma> <markHue> / <backgroundOpacity>)
*/
markBackground: string;
/**
* The border color of marked text (text marker type `mark`).
* @default
* lch(<borderLuminance> <defaultChroma> <markHue> / <borderOpacity>)
*/
markBorderColor: string;
/**
* The background color of inserted text (text marker type `ins`).
* @default
* lch(<defaultLuminance> <defaultChroma> <insHue> / <backgroundOpacity>)
*/
insBackground: string;
/**
* The border color of inserted text (text marker type `ins`).
* @default
* lch(<borderLuminance> <defaultChroma> <insHue> / <borderOpacity>)
*/
insBorderColor: string;
/**
* The color of the diff indicator (e.g. `+` or `-`) of inserted lines.
* @default
* lch(<indicatorLuminance> <defaultChroma> <insHue> / <indicatorOpacity>)
*/
insDiffIndicatorColor: string;
/**
* The background color of deleted text (text marker type `del`).
* @default
* lch(<defaultLuminance> <defaultChroma> <delHue> / <backgroundOpacity>)
*/
delBackground: string;
/**
* The border color of deleted text (text marker type `del`).
* @default
* lch(<borderLuminance> <defaultChroma> <delHue> / <borderOpacity>)
*/
delBorderColor: string;
/**
* The color of the diff indicator (e.g. `+` or `-`) of deleted lines.
* @default
* lch(<indicatorLuminance> <defaultChroma> <delHue> / <indicatorOpacity>)
*/
delDiffIndicatorColor: string;
}
declare module '@expressive-code/core' {
interface StyleSettings {
textMarkers: TextMarkersStyleSettings;
}
}
type MarkerLineOrRange = number | {
range: string;
label?: string | undefined;
};
/**
* A single text marker definition that can be used in the `mark`, `ins`, and `del` props
* to define text and line markers.
*/
type MarkerDefinition = string | RegExp | MarkerLineOrRange;
interface PluginTextMarkersProps {
/**
* Defines the code block's [text & line markers](https://expressive-code.com/key-features/text-markers/)
* of the default neutral type.
*
* You can either pass a single marker definition or an array of them.
*/
mark: MarkerDefinition | MarkerDefinition[];
/**
* Defines the code block's [text & line markers](https://expressive-code.com/key-features/text-markers/)
* of the "inserted" type.
*
* You can either pass a single marker definition or an array of them.
*/
ins: MarkerDefinition | MarkerDefinition[];
/**
* Defines the code block's [text & line markers](https://expressive-code.com/key-features/text-markers/)
* of the "deleted" type.
*
* You can either pass a single marker definition or an array of them.
*/
del: MarkerDefinition | MarkerDefinition[];
/**
* Allows you to enable processing of diff syntax for non-diff languages.
*
* If set to `true`, you can prefix lines with `+` or `-`, no matter what the language of
* the code block is. The prefixes will be removed and the lines will be highlighted as
* inserted or deleted lines.
*/
useDiffSyntax: boolean;
}
declare module '@expressive-code/core' {
interface ExpressiveCodeBlockProps extends PluginTextMarkersProps {
}
}
declare function pluginTextMarkers(): ExpressiveCodePlugin;
export { MarkerDefinition, MarkerLineOrRange, PluginTextMarkersProps, TextMarkersStyleSettings, pluginTextMarkers };

View File

@@ -0,0 +1,590 @@
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// ../../../node_modules/.pnpm/parse-numeric-range@1.3.0/node_modules/parse-numeric-range/index.js
var require_parse_numeric_range = __commonJS({
"../../../node_modules/.pnpm/parse-numeric-range@1.3.0/node_modules/parse-numeric-range/index.js"(exports, module) {
"use strict";
function parsePart(string) {
let res = [];
let m;
for (let str of string.split(",").map((str2) => str2.trim())) {
if (/^-?\d+$/.test(str)) {
res.push(parseInt(str, 10));
} else if (m = str.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)) {
let [_, lhs, sep, rhs] = m;
if (lhs && rhs) {
lhs = parseInt(lhs);
rhs = parseInt(rhs);
const incr = lhs < rhs ? 1 : -1;
if (sep === "-" || sep === ".." || sep === "\u2025")
rhs += incr;
for (let i = lhs; i !== rhs; i += incr)
res.push(i);
}
}
}
return res;
}
exports.default = parsePart;
module.exports = parsePart;
}
});
// src/index.ts
var import_parse_numeric_range = __toESM(require_parse_numeric_range(), 1);
import {
AnnotationRenderPhaseOrder,
InlineStyleAnnotation,
ensureColorContrastOnBackground,
getStaticBackgroundColor,
isInlineStyleAnnotation,
onBackground
} from "@expressive-code/core";
// src/marker-types.ts
var MarkerTypeOrder = ["mark", "del", "ins"];
function markerTypeFromString(input) {
if (input === "add")
input = "ins";
if (input === "rem")
input = "del";
const markerType = input;
return MarkerTypeOrder.includes(markerType) ? markerType : void 0;
}
// src/styles.ts
import { PluginStyleSettings, codeLineClass, toHexColor } from "@expressive-code/core";
var textMarkersStyleSettings = new PluginStyleSettings({
defaultValues: {
textMarkers: {
lineMarkerAccentMargin: "0rem",
lineMarkerAccentWidth: "0.15rem",
lineMarkerLabelPaddingInline: "0.2rem",
lineMarkerLabelColor: "white",
lineDiffIndicatorMarginLeft: "0.3rem",
inlineMarkerBorderWidth: "1.5px",
inlineMarkerBorderRadius: "0.2rem",
inlineMarkerPadding: "0.15rem",
// Define base colors for all markers in the LCH color space,
// which leads to consistent perceived brightness independent of hue
markHue: "284",
insHue: "136",
delHue: "33",
defaultChroma: "40",
defaultLuminance: ["32%", "75%"],
backgroundOpacity: "50%",
borderLuminance: "48%",
borderOpacity: "81.6%",
indicatorLuminance: ["67%", "40%"],
indicatorOpacity: "81.6%",
// You can use these to override the diff indicator content
insDiffIndicatorContent: "'+'",
delDiffIndicatorContent: "'-'",
// The settings below will be calculated based on the settings above
markBackground: (context) => resolveBg(context, "textMarkers.markHue"),
markBorderColor: (context) => resolveBorder(context, "textMarkers.markHue"),
insBackground: (context) => resolveBg(context, "textMarkers.insHue"),
insBorderColor: (context) => resolveBorder(context, "textMarkers.insHue"),
insDiffIndicatorColor: (context) => resolveIndicator(context, "textMarkers.insHue"),
delBackground: (context) => resolveBg(context, "textMarkers.delHue"),
delBorderColor: (context) => resolveBorder(context, "textMarkers.delHue"),
delDiffIndicatorColor: (context) => resolveIndicator(context, "textMarkers.delHue")
}
},
cssVarExclusions: [
// Exclude all settings from CSS variable output that will not be used directly in styles,
// but instead be used to calculate other settings
"textMarkers.markHue",
"textMarkers.insHue",
"textMarkers.delHue",
"textMarkers.defaultChroma",
"textMarkers.defaultLuminance",
"textMarkers.backgroundOpacity",
"textMarkers.borderLuminance",
"textMarkers.borderOpacity",
"textMarkers.indicatorLuminance",
"textMarkers.indicatorOpacity"
]
});
function getTextMarkersBaseStyles({ cssVar }) {
const result = `
.${codeLineClass} {
/* Support line-level mark/ins/del */
&.mark {
--tmLineBgCol: ${cssVar("textMarkers.markBackground")};
& .code {
--ecLineBrdCol: ${cssVar("textMarkers.markBorderColor")};
}
}
&.ins {
--tmLineBgCol: ${cssVar("textMarkers.insBackground")};
--tmLabel: ${cssVar("textMarkers.insDiffIndicatorContent")};
& .code {
--ecLineBrdCol: ${cssVar("textMarkers.insBorderColor")};
&::before {
color: ${cssVar("textMarkers.insDiffIndicatorColor")};
}
}
}
&.del {
--tmLineBgCol: ${cssVar("textMarkers.delBackground")};
--tmLabel: ${cssVar("textMarkers.delDiffIndicatorContent")};
& .code {
--ecLineBrdCol: ${cssVar("textMarkers.delBorderColor")};
&::before {
color: ${cssVar("textMarkers.delDiffIndicatorColor")};
}
}
}
&.mark,
&.ins,
&.del {
background: var(--tmLineBgCol);
& .code {
--ecGtrBrdWd: ${cssVar("textMarkers.lineMarkerAccentWidth")};
}
& .code::before {
display: block;
position: absolute;
left: 0;
box-sizing: border-box;
content: var(--tmLabel, ' ');
padding-inline-start: ${cssVar("textMarkers.lineDiffIndicatorMarginLeft")};
text-align: center;
/* Prevent long labels from wrapping to avoid overlapping the code */
white-space: pre;
}
&.tm-label {
& .code::before {
background: var(--ecLineBrdCol);
padding: 0 calc(${cssVar("textMarkers.lineMarkerLabelPaddingInline")} + ${cssVar("textMarkers.lineMarkerAccentWidth")}) 0 ${cssVar("textMarkers.lineMarkerLabelPaddingInline")};
color: ${cssVar("textMarkers.lineMarkerLabelColor")};
}
}
}
/* Support inline mark/ins/del */
& mark {
--tmInlineBgCol: ${cssVar("textMarkers.markBackground")};
--tmInlineBrdCol: ${cssVar("textMarkers.markBorderColor")};
}
& ins {
--tmInlineBgCol: ${cssVar("textMarkers.insBackground")};
--tmInlineBrdCol: ${cssVar("textMarkers.insBorderColor")};
}
& del {
--tmInlineBgCol: ${cssVar("textMarkers.delBackground")};
--tmInlineBrdCol: ${cssVar("textMarkers.delBorderColor")};
}
& mark,
& ins,
& del {
all: unset;
display: inline-block;
position: relative;
--tmBrdL: ${cssVar("textMarkers.inlineMarkerBorderWidth")};
--tmBrdR: ${cssVar("textMarkers.inlineMarkerBorderWidth")};
--tmRadL: ${cssVar("textMarkers.inlineMarkerBorderRadius")};
--tmRadR: ${cssVar("textMarkers.inlineMarkerBorderRadius")};
margin-inline: 0.025rem;
padding-inline: ${cssVar("textMarkers.inlineMarkerPadding")};
border-radius: var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);
background: var(--tmInlineBgCol);
background-clip: padding-box;
&.open-start {
margin-inline-start: 0;
padding-inline-start: 0;
--tmBrdL: 0px;
--tmRadL: 0;
}
&.open-end {
margin-inline-end: 0;
padding-inline-end: 0;
--tmBrdR: 0px;
--tmRadR: 0;
}
&::before {
content: '';
position: absolute;
pointer-events: none;
display: inline-block;
inset: 0;
border-radius: var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);
border: ${cssVar("textMarkers.inlineMarkerBorderWidth")} solid var(--tmInlineBrdCol);
border-inline-width: var(--tmBrdL) var(--tmBrdR);
}
}
}
`;
return result;
}
var markerBgColorPaths = {
mark: "textMarkers.markBackground",
ins: "textMarkers.insBackground",
del: "textMarkers.delBackground"
};
function resolveBg({ resolveSetting: r }, hue) {
return toHexColor(`lch(${r("textMarkers.defaultLuminance")} ${r("textMarkers.defaultChroma")} ${r(hue)} / ${r("textMarkers.backgroundOpacity")})`);
}
function resolveBorder({ resolveSetting: r }, hue) {
return toHexColor(`lch(${r("textMarkers.borderLuminance")} ${r("textMarkers.defaultChroma")} ${r(hue)} / ${r("textMarkers.borderOpacity")})`);
}
function resolveIndicator({ resolveSetting: r }, hue) {
return toHexColor(`lch(${r("textMarkers.indicatorLuminance")} ${r("textMarkers.defaultChroma")} ${r(hue)} / ${r("textMarkers.indicatorOpacity")})`);
}
// src/utils.ts
function getGroupIndicesFromRegExpMatch(match) {
let groupIndices = match.indices;
if (groupIndices?.length)
return groupIndices;
const fullMatchIndex = match.index;
groupIndices = match.map((groupValue) => {
const groupIndex = groupValue ? match[0].indexOf(groupValue) : -1;
if (groupIndex === -1)
return null;
const groupStart = fullMatchIndex + groupIndex;
const groupEnd = groupStart + groupValue.length;
return [groupStart, groupEnd];
});
return groupIndices;
}
function toDefinitionsArray(value) {
if (value === void 0)
return [];
return Array.isArray(value) ? value : [value];
}
// src/inline-markers.ts
function getInlineSearchTermMatches(lineText, codeBlock) {
const markerMatches = [];
MarkerTypeOrder.forEach((markerType) => {
toDefinitionsArray(codeBlock.props[markerType]).forEach((definition) => {
if (typeof definition === "string") {
let idx = lineText.indexOf(definition, 0);
while (idx > -1) {
markerMatches.push({
markerType,
start: idx,
end: idx + definition.length
});
idx = lineText.indexOf(definition, idx + definition.length);
}
}
if (definition instanceof RegExp) {
const matches = lineText.matchAll(definition);
for (const match of matches) {
const rawGroupIndices = getGroupIndicesFromRegExpMatch(match);
let groupIndices = rawGroupIndices.flatMap((range) => range ? [range] : []);
if (!groupIndices.length) {
const fullMatchIndex = match.index;
groupIndices = [[fullMatchIndex, fullMatchIndex + match[0].length]];
}
if (groupIndices.length > 1) {
groupIndices.shift();
}
groupIndices.forEach((range) => {
markerMatches.push({
markerType,
start: range[0],
end: range[1]
});
});
}
}
});
});
return markerMatches;
}
function flattenInlineMarkerRanges(markerRanges) {
const flattenedRanges = [];
const addRange = (newRange) => {
for (let idx = flattenedRanges.length - 1; idx >= 0; idx--) {
const curRange = flattenedRanges[idx];
if (newRange.end <= curRange.start || newRange.start >= curRange.end)
continue;
if (newRange.start <= curRange.start && newRange.end >= curRange.end) {
flattenedRanges.splice(idx, 1);
continue;
}
if (newRange.markerType === curRange.markerType) {
flattenedRanges.splice(idx, 1);
newRange = {
...newRange,
start: Math.min(newRange.start, curRange.start),
end: Math.max(newRange.end, curRange.end)
};
continue;
}
if (newRange.start > curRange.start && newRange.end < curRange.end) {
flattenedRanges.splice(idx, 1, { ...curRange, end: newRange.start }, { ...curRange, start: newRange.end });
continue;
}
if (newRange.start > curRange.start) {
curRange.end = newRange.start;
}
if (newRange.end < curRange.end) {
curRange.start = newRange.end;
}
}
flattenedRanges.push(newRange);
flattenedRanges.sort((a, b) => a.start - b.start);
};
MarkerTypeOrder.forEach((markerType) => {
markerRanges.filter((range) => range.markerType === markerType).forEach(addRange);
});
return flattenedRanges;
}
// src/annotations.ts
import { ExpressiveCodeAnnotation } from "@expressive-code/core";
import { addClassName, h, setInlineStyle } from "@expressive-code/core/hast";
var TextMarkerAnnotation = class extends ExpressiveCodeAnnotation {
markerType;
backgroundColor;
label;
constructor({ markerType, backgroundColor, label, ...baseOptions }) {
super(baseOptions);
this.markerType = markerType;
this.backgroundColor = backgroundColor;
this.label = label;
}
render(options) {
if (!this.inlineRange)
return this.renderFullLineMarker(options);
return this.renderInlineMarker(options);
}
renderFullLineMarker({ nodesToTransform }) {
return nodesToTransform.map((node) => {
if (node.type === "element") {
addClassName(node, "highlight");
addClassName(node, this.markerType);
if (this.label) {
addClassName(node, "tm-label");
setInlineStyle(node, "--tmLabel", this.label, "string");
}
}
return node;
});
}
renderInlineMarker({ nodesToTransform }) {
return nodesToTransform.map((node, idx) => {
const transformedNode = h(this.markerType, node);
if (nodesToTransform.length > 0 && idx > 0) {
addClassName(transformedNode, "open-start");
}
if (nodesToTransform.length > 0 && idx < nodesToTransform.length - 1) {
addClassName(transformedNode, "open-end");
}
return transformedNode;
});
}
};
// src/index.ts
function pluginTextMarkers() {
return {
name: "TextMarkers",
styleSettings: textMarkersStyleSettings,
baseStyles: (context) => getTextMarkersBaseStyles(context),
hooks: {
preprocessLanguage: ({ codeBlock }) => {
const lang = codeBlock.metaOptions.getString("lang");
if (lang && codeBlock.language === "diff") {
codeBlock.language = lang;
codeBlock.props.useDiffSyntax = true;
}
},
preprocessMetadata: ({ codeBlock, cssVar }) => {
const addDefinition = (target, definition) => {
const definitions = toDefinitionsArray(codeBlock.props[target]);
definitions.push(definition);
codeBlock.props[target] = definitions;
};
codeBlock.metaOptions.list([...MarkerTypeOrder, "", "add", "rem"]).forEach((option) => {
const { kind, key, value } = option;
const markerType = markerTypeFromString(key || "mark");
if (!markerType)
return;
if (kind === "string" || kind === "regexp")
addDefinition(markerType, value);
if (kind === "range") {
let label = void 0;
const range = value.replace(/^\s*?(["'])([^\1]+?)\1:\s*?/, (_match, _quote, labelValue) => {
label = labelValue;
return "";
});
addDefinition(markerType, { range, label });
}
});
codeBlock.props.useDiffSyntax = codeBlock.metaOptions.getBoolean("useDiffSyntax") ?? codeBlock.props.useDiffSyntax;
MarkerTypeOrder.forEach((markerType) => {
toDefinitionsArray(codeBlock.props[markerType]).forEach((definition) => {
if (typeof definition === "string" || definition instanceof RegExp)
return;
const objDefinition = typeof definition === "number" ? { range: `${definition}` } : definition;
const { range = "", label } = objDefinition;
const lineNumbers = (0, import_parse_numeric_range.default)(range);
lineNumbers.forEach((lineNumber, idx) => {
const lineIndex = lineNumber - 1;
codeBlock.getLine(lineIndex)?.addAnnotation(
new TextMarkerAnnotation({
markerType,
backgroundColor: cssVar(markerBgColorPaths[markerType]),
// Add a label to the first line of each consecutive range
label: idx === 0 || lineNumber - lineNumbers[idx - 1] !== 1 ? label : void 0
})
);
});
});
});
},
preprocessCode: ({ codeBlock, cssVar }) => {
if (codeBlock.language === "diff" || codeBlock.props.useDiffSyntax) {
const lines = codeBlock.getLines();
const couldBeRealDiffFile = lines.slice(0, 4).some((line) => line.text.match(/^([*+-]{3}\s|@@\s|[0-9,]+[acd][0-9,]+\s*$)/));
if (!couldBeRealDiffFile) {
let minIndentation = Infinity;
const parsedLines = lines.map((line) => {
const [, indentation, marker, content] = line.text.match(/^(([+-](?![+-]))?\s*)(.*)$/) || [];
const markerType = marker === "+" ? "ins" : marker === "-" ? "del" : void 0;
if (content.trim().length > 0 && indentation.length < minIndentation)
minIndentation = indentation.length;
return {
line,
markerType
};
});
parsedLines.forEach(({ line, markerType }) => {
const colsToRemove = minIndentation || (markerType ? 1 : 0);
if (colsToRemove > 0)
line.editText(0, colsToRemove, "");
if (markerType) {
line.addAnnotation(
new TextMarkerAnnotation({
markerType,
backgroundColor: cssVar(markerBgColorPaths[markerType])
})
);
}
});
}
}
},
annotateCode: ({ codeBlock, cssVar }) => {
codeBlock.getLines().forEach((line) => {
const markerRanges = getInlineSearchTermMatches(line.text, codeBlock);
if (!markerRanges.length)
return;
const flattenedRanges = flattenInlineMarkerRanges(markerRanges);
flattenedRanges.forEach(({ markerType, start, end }) => {
line.addAnnotation(
new TextMarkerAnnotation({
markerType,
backgroundColor: cssVar(markerBgColorPaths[markerType]),
inlineRange: {
columnStart: start,
columnEnd: end
}
})
);
});
});
},
postprocessAnnotations: ({ codeBlock, styleVariants, config }) => {
if (config.minSyntaxHighlightingColorContrast <= 0)
return;
codeBlock.getLines().forEach((line) => {
const annotations = line.getAnnotations();
const markers = [];
let fullLineMarker = void 0;
for (const annotation of annotations) {
if (!(annotation instanceof TextMarkerAnnotation))
continue;
if (annotation.inlineRange) {
markers.push(annotation);
continue;
}
if (fullLineMarker) {
if (MarkerTypeOrder.indexOf(annotation.markerType) < MarkerTypeOrder.indexOf(fullLineMarker.markerType))
continue;
if (AnnotationRenderPhaseOrder.indexOf(annotation.renderPhase || "normal") < AnnotationRenderPhaseOrder.indexOf(fullLineMarker.renderPhase || "normal"))
continue;
}
fullLineMarker = annotation;
}
if (fullLineMarker)
markers.unshift(fullLineMarker);
styleVariants.forEach((styleVariant, styleVariantIndex) => {
const fullLineMarkerBgColor = fullLineMarker && styleVariant.resolvedStyleSettings.get(markerBgColorPaths[fullLineMarker.markerType]) || "transparent";
const lineBgColor = onBackground(fullLineMarkerBgColor, getStaticBackgroundColor(styleVariant));
const textColors = annotations.filter(
(annotation) => isInlineStyleAnnotation(annotation) && annotation.color && // Only consider annotations that apply to the current style variant
(annotation.styleVariantIndex === void 0 || annotation.styleVariantIndex === styleVariantIndex)
);
textColors.forEach((textColor) => {
const textFgColor = textColor.color;
const textStart = textColor.inlineRange?.columnStart;
const textEnd = textColor.inlineRange?.columnEnd;
if (textFgColor === void 0 || textStart === void 0 || textEnd === void 0)
return;
markers.forEach((marker) => {
const markerStart = marker.inlineRange?.columnStart ?? 0;
const markerEnd = marker.inlineRange?.columnEnd ?? line.text.length;
if (markerStart > textEnd || markerEnd < textStart)
return;
const inlineMarkerBgColor = marker.inlineRange && styleVariant.resolvedStyleSettings.get(markerBgColorPaths[marker.markerType]) || "transparent";
const combinedBgColor = onBackground(inlineMarkerBgColor, lineBgColor);
const readableTextColor = ensureColorContrastOnBackground(textFgColor, combinedBgColor, config.minSyntaxHighlightingColorContrast);
if (readableTextColor.toLowerCase() === textFgColor.toLowerCase())
return;
line.addAnnotation(
new InlineStyleAnnotation({
styleVariantIndex,
inlineRange: {
columnStart: Math.max(textStart, markerStart),
columnEnd: Math.min(textEnd, markerEnd)
},
color: readableTextColor,
renderPhase: "earlier"
})
);
});
});
});
});
}
}
};
}
export {
pluginTextMarkers
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,40 @@
{
"name": "@expressive-code/plugin-text-markers",
"version": "0.35.3",
"description": "Text marker plugin for Expressive Code, a text marking & annotation engine for presenting source code on the web.",
"keywords": [],
"author": "Tibor Schiemann",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/expressive-code/expressive-code.git",
"directory": "packages/@expressive-code/plugin-text-markers"
},
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"exports": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"dependencies": {
"@expressive-code/core": "^0.35.3"
},
"devDependencies": {
"@expressive-code/plugin-shiki": "^0.35.3",
"parse-numeric-range": "^1.3.0",
"@internal/test-utils": "^0.2.28"
},
"scripts": {
"build": "tsup ./src/index.ts --format esm --dts --sourcemap --clean",
"coverage": "vitest run --coverage",
"test": "vitest run --reporter verbose",
"test-short": "vitest run --reporter basic",
"test-watch": "vitest --reporter verbose",
"watch": "pnpm build --watch src"
}
}