@code-hike/code-diff
Advanced tools
Comparing version 0.3.0--canary.75.b3e0bf9.0 to 0.3.0--canary.77.ade5d72.0
@@ -6,7 +6,9 @@ 'use strict'; | ||
var diff = require('diff'); | ||
var Prism$1 = require('prismjs'); | ||
var shiki = require('shiki'); | ||
var React = require('react'); | ||
var utils = require('@code-hike/utils'); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var Prism__default = /*#__PURE__*/_interopDefaultLegacy(Prism$1); | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
@@ -27,17 +29,52 @@ /*! ***************************************************************************** | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
var __assign = function() { | ||
__assign = Object.assign || function __assign(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function __read(o, n) { | ||
@@ -66,220 +103,247 @@ var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
(function(Prism) { | ||
var javascript = Prism.util.clone(Prism.languages.javascript); | ||
Prism.languages.jsx = Prism.languages.extend('markup', javascript); | ||
Prism.languages.jsx.tag.pattern= /<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:$-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}))?|\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}))*\s*\/?)?>/i; | ||
Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i; | ||
Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i; | ||
Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/; | ||
Prism.languages.insertBefore('inside', 'attr-name', { | ||
'spread': { | ||
pattern: /\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}/, | ||
inside: { | ||
'punctuation': /\.{3}|[{}.]/, | ||
'attr-value': /\w+/ | ||
} | ||
} | ||
}, Prism.languages.jsx.tag); | ||
Prism.languages.insertBefore('inside', 'attr-value',{ | ||
'script': { | ||
// Allow for two levels of nesting | ||
pattern: /=(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\})/i, | ||
inside: { | ||
'script-punctuation': { | ||
pattern: /^=(?={)/, | ||
alias: 'punctuation' | ||
}, | ||
rest: Prism.languages.jsx | ||
}, | ||
'alias': 'language-javascript' | ||
} | ||
}, Prism.languages.jsx.tag); | ||
// The following will handle plain text inside tags | ||
var stringifyToken = function (token) { | ||
if (!token) { | ||
return ''; | ||
} | ||
if (typeof token === 'string') { | ||
return token; | ||
} | ||
if (typeof token.content === 'string') { | ||
return token.content; | ||
} | ||
return token.content.map(stringifyToken).join(''); | ||
function tokenizePlaceholder(code) { | ||
var lines = code.split("\n"); | ||
return lines.map(function (line) { return [[line, {}]]; }); | ||
} | ||
function getBasicThemedCode(code, theme) { | ||
var lines = code.split("\n"); | ||
var _a = getThemeDefaultColors(theme), fg = _a.fg, bg = _a.bg; | ||
return { | ||
lines: lines.map(function (line) { return [{ content: line }]; }), | ||
fg: fg, | ||
bg: bg, | ||
}; | ||
} | ||
/** | ||
* From https://github.com/shikijs/shiki/blob/HEAD/packages/shiki/src/loader.ts | ||
*/ | ||
var VSCODE_FALLBACK_EDITOR_FG = { | ||
light: "#333333", | ||
dark: "#bbbbbb", | ||
}; | ||
var walkTokens = function (tokens) { | ||
var openedTags = []; | ||
for (var i = 0; i < tokens.length; i++) { | ||
var token = tokens[i]; | ||
var notTagNorBrace = false; | ||
if (typeof token !== 'string') { | ||
if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') { | ||
// We found a tag, now find its kind | ||
if (token.content[0].content[0].content === '</') { | ||
// Closing tag | ||
if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) { | ||
// Pop matching opening tag | ||
openedTags.pop(); | ||
} | ||
} else { | ||
if (token.content[token.content.length - 1].content === '/>') ; else { | ||
// Opening tag | ||
openedTags.push({ | ||
tagName: stringifyToken(token.content[0].content[1]), | ||
openedBraces: 0 | ||
}); | ||
} | ||
} | ||
} else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') { | ||
// Here we might have entered a JSX context inside a tag | ||
openedTags[openedTags.length - 1].openedBraces++; | ||
} else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') { | ||
// Here we might have left a JSX context inside a tag | ||
openedTags[openedTags.length - 1].openedBraces--; | ||
} else { | ||
notTagNorBrace = true; | ||
} | ||
} | ||
if (notTagNorBrace || typeof token === 'string') { | ||
if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) { | ||
// Here we are inside a tag, and not inside a JSX context. | ||
// That's plain text: drop any tokens matched. | ||
var plainText = stringifyToken(token); | ||
// And merge text with adjacent text | ||
if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) { | ||
plainText += stringifyToken(tokens[i + 1]); | ||
tokens.splice(i + 1, 1); | ||
} | ||
if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) { | ||
plainText = stringifyToken(tokens[i - 1]) + plainText; | ||
tokens.splice(i - 1, 1); | ||
i--; | ||
} | ||
tokens[i] = new Prism.Token('plain-text', plainText, null, plainText); | ||
} | ||
} | ||
if (token.content && typeof token.content !== 'string') { | ||
walkTokens(token.content); | ||
} | ||
} | ||
var VSCODE_FALLBACK_EDITOR_BG = { | ||
light: "#fffffe", | ||
dark: "#1e1e1e", | ||
}; | ||
function getThemeDefaultColors(theme) { | ||
var _a, _b, _c, _d, _e, _f; | ||
var fg, bg; | ||
/** | ||
* First try: | ||
* Theme might contain a global `tokenColor` without `name` or `scope` | ||
* Used as default value for foreground/background | ||
*/ | ||
var settings = theme.settings | ||
? theme.settings | ||
: theme.tokenColors; | ||
var globalSetting = settings | ||
? settings.find(function (s) { | ||
return !s.name && !s.scope; | ||
}) | ||
: undefined; | ||
if ((_a = globalSetting === null || globalSetting === void 0 ? void 0 : globalSetting.settings) === null || _a === void 0 ? void 0 : _a.foreground) { | ||
fg = globalSetting.settings.foreground; | ||
} | ||
if ((_b = globalSetting === null || globalSetting === void 0 ? void 0 : globalSetting.settings) === null || _b === void 0 ? void 0 : _b.background) { | ||
bg = globalSetting.settings.background; | ||
} | ||
/** | ||
* Second try: | ||
* If there's no global `tokenColor` without `name` or `scope` | ||
* Use `editor.foreground` and `editor.background` | ||
*/ | ||
if (!fg && ((_d = (_c = theme) === null || _c === void 0 ? void 0 : _c.colors) === null || _d === void 0 ? void 0 : _d["editor.foreground"])) { | ||
fg = theme.colors["editor.foreground"]; | ||
} | ||
if (!bg && ((_f = (_e = theme) === null || _e === void 0 ? void 0 : _e.colors) === null || _f === void 0 ? void 0 : _f["editor.background"])) { | ||
bg = theme.colors["editor.background"]; | ||
} | ||
/** | ||
* Last try: | ||
* If there's no fg/bg color specified in theme, use default | ||
*/ | ||
if (!fg) { | ||
fg = | ||
theme.type === "light" | ||
? VSCODE_FALLBACK_EDITOR_FG.light | ||
: VSCODE_FALLBACK_EDITOR_FG.dark; | ||
} | ||
if (!bg) { | ||
bg = | ||
theme.type === "light" | ||
? VSCODE_FALLBACK_EDITOR_BG.light | ||
: VSCODE_FALLBACK_EDITOR_BG.dark; | ||
} | ||
return { | ||
fg: fg, | ||
bg: bg, | ||
}; | ||
} | ||
Prism.hooks.add('after-tokenize', function (env) { | ||
if (env.language !== 'jsx' && env.language !== 'tsx') { | ||
return; | ||
} | ||
walkTokens(env.tokens); | ||
}); | ||
function useAsyncMemo(_a, deps) { | ||
var isReady = _a.isReady, load = _a.load, run = _a.run, placeholder = _a.placeholder; | ||
var _b = __read(React__default['default'].useState({ result: null, deps: [], version: 0 }), 2), _c = _b[0], lastLoadedResult = _c.result, lastLoadedDeps = _c.deps, version = _c.version, setState = _b[1]; | ||
React__default['default'].useEffect(function () { | ||
if (!isReady) { | ||
load().then(function () { | ||
setState(function (_a) { | ||
var version = _a.version; | ||
return ({ | ||
result: run(), | ||
deps: deps, | ||
version: version + 1, | ||
}); | ||
}); | ||
}); | ||
} | ||
}, deps); | ||
return React__default['default'].useMemo(function () { | ||
if (depsChanged(deps, lastLoadedDeps)) { | ||
return isReady ? run() : placeholder(); | ||
} | ||
else { | ||
return lastLoadedResult; | ||
} | ||
}, __spread([version], deps)); | ||
} | ||
function depsChanged(oldDeps, newDeps) { | ||
if (oldDeps === newDeps) | ||
return false; | ||
if (!oldDeps || !newDeps) | ||
return true; | ||
return oldDeps === null || oldDeps === void 0 ? void 0 : oldDeps.some(function (dep, index) { return newDeps[index] !== dep; }); | ||
} | ||
}(Prism)); | ||
var newlineRe = /\r\n|\r|\n/; | ||
Prism__default['default'].manual = true; | ||
function tokenize(code, lang) { | ||
var grammar = Prism__default['default'].languages[lang]; | ||
if (!grammar) { | ||
throw new MissingGrammarError(lang); | ||
} | ||
var prismTokens = Prism__default['default'].tokenize(code, Prism__default['default'].languages[lang]); | ||
var nestedTokens = tokenizeStrings(prismTokens); | ||
var tokens = flattenTokens(nestedTokens); | ||
var currentLine = []; | ||
var lines = [currentLine]; | ||
tokens.forEach(function (token) { | ||
var contentLines = token.content.split(newlineRe); | ||
var firstContent = contentLines.shift(); | ||
if (firstContent !== undefined && firstContent !== "") { | ||
currentLine.push([firstContent, token.type]); | ||
} | ||
contentLines.forEach(function (content) { | ||
currentLine = []; | ||
lines.push(currentLine); | ||
if (content !== "") { | ||
currentLine.push([content, token.type]); | ||
var _a; | ||
var highlighterPromise = null; | ||
var highlighter = null; | ||
function useHighlighter(code, lang, theme) { | ||
return useAsyncMemo({ | ||
isReady: isHighlighterReady(lang, theme), | ||
load: function () { return loadHighlighter(lang, theme); }, | ||
run: function () { return highlight(code, lang, theme); }, | ||
placeholder: function () { | ||
var _a = getBasicThemedCode("", theme), bg = _a.bg, fg = _a.fg; | ||
var lines = utils.mapWithDefault(code, "", tokenizePlaceholder); | ||
return { lines: lines, bg: bg, fg: fg }; | ||
}, | ||
}, [code.prev, code.next, lang, theme]); | ||
} | ||
function isHighlighterReady(lang, theme) { | ||
return (highlighter != null && | ||
!missingTheme(highlighter, theme) && | ||
!missingLang(highlighter, lang)); | ||
} | ||
function loadHighlighter(lang, theme) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (highlighterPromise === null) { | ||
shiki.setCDN("https://unpkg.com/shiki/"); | ||
highlighterPromise = shiki.getHighlighter({ | ||
theme: theme, | ||
langs: [lang], | ||
}); | ||
} | ||
if (!(highlighter === null)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, highlighterPromise]; | ||
case 1: | ||
highlighter = _a.sent(); | ||
_a.label = 2; | ||
case 2: | ||
if (!missingTheme(highlighter, theme)) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, highlighter.loadTheme(theme)]; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: | ||
if (!missingLang(highlighter, lang)) return [3 /*break*/, 6]; | ||
return [4 /*yield*/, highlighter.loadLanguage(lang)]; | ||
case 5: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
return lines; | ||
} | ||
function tokenizeStrings(prismTokens, parentType) { | ||
if (parentType === void 0) { parentType = "plain"; } | ||
return prismTokens.map(function (prismToken) { | ||
return wrapToken(prismToken, parentType); | ||
function highlight(code, lang, theme) { | ||
// assumes highlighter isReady | ||
var _a = highlighter.getTheme(theme.name), fg = _a.fg, bg = _a.bg; | ||
var lines = utils.mapWithDefault(code, "", function (code) { | ||
return getCodeLines(highlighter, code, lang, theme); | ||
}); | ||
return { lines: lines, bg: bg, fg: fg }; | ||
} | ||
function wrapToken(prismToken, parentType) { | ||
if (parentType === void 0) { parentType = "plain"; } | ||
if (typeof prismToken === "string") { | ||
return { | ||
type: parentType, | ||
content: prismToken, | ||
function getCodeLines(highlighter, code, lang, theme) { | ||
var lines = highlighter.codeToThemedTokens(code, lang, theme.name, { | ||
includeExplanation: false, | ||
}); | ||
return lines.map(function (line) { | ||
return line.map(function (token) { return [ | ||
token.content, | ||
{ style: getStyle(token) }, | ||
]; }); | ||
}); | ||
} | ||
function missingTheme(highlighter, theme) { | ||
return !highlighter | ||
.getLoadedThemes() | ||
.some(function (t) { return t === theme.name; }); | ||
} | ||
function missingLang(highlighter, lang) { | ||
return !highlighter | ||
.getLoadedLanguages() | ||
.some(function (l) { return l === lang; }); | ||
} | ||
var FONT_STYLE_TO_CSS = (_a = {}, | ||
_a[-1 /* NotSet */] = {}, | ||
_a[0 /* None */] = {}, | ||
_a[1 /* Italic */] = { fontStyle: "italic" }, | ||
_a[2 /* Bold */] = { fontWeight: "bold" }, | ||
_a[4 /* Underline */] = { textDecoration: "underline" }, | ||
_a); | ||
function getStyle(token) { | ||
var fontStyle = token.fontStyle | ||
? FONT_STYLE_TO_CSS[token.fontStyle] | ||
: {}; | ||
return __assign({ color: token.color }, fontStyle); | ||
} | ||
function useCodeDiff(_a) { | ||
var code = _a.code, lang = _a.lang, theme = _a.theme; | ||
var normalCode = utils.mapWithDefault(code, "", normalize); | ||
var _b = useHighlighter(normalCode, lang, theme), lines = _b.lines, bg = _b.bg, fg = _b.fg; | ||
return React__default['default'].useMemo(function () { | ||
var prevKeys = Array.from({ length: lines.prev.length - 1 }, function (x, i) { return i + 1; }); | ||
var nextKeys = getNextKeys(normalCode.prev, normalCode.next, prevKeys); | ||
var codeMap = { | ||
keys: { prev: prevKeys, next: nextKeys }, | ||
lines: {}, | ||
}; | ||
} | ||
if (Array.isArray(prismToken.content)) { | ||
prevKeys.forEach(function (key, index) { | ||
return (codeMap.lines[key] = { | ||
tokens: lines.prev[index], | ||
lineNumber: { prev: index + 1 }, | ||
}); | ||
}); | ||
nextKeys.forEach(function (key, index) { | ||
if (key in codeMap.lines) { | ||
codeMap.lines[key].lineNumber.next = index + 1; | ||
} | ||
else { | ||
codeMap.lines[key] = { | ||
tokens: lines.next[index], | ||
lineNumber: { next: index + 1 }, | ||
}; | ||
} | ||
}); | ||
return { | ||
type: prismToken.type, | ||
content: tokenizeStrings(prismToken.content, prismToken.type), | ||
codeMap: codeMap, | ||
backgroundColor: bg, | ||
color: fg, | ||
}; | ||
} | ||
return wrapToken(prismToken.content, prismToken.type); | ||
}, [lines.prev, lines.next, bg, fg]); | ||
} | ||
// Take a list of nested tokens | ||
// (token.content may contain an array of tokens) | ||
// and flatten it so content is always a string | ||
// and type the type of the leaf | ||
function flattenTokens(tokens) { | ||
var flatList = []; | ||
tokens.forEach(function (token) { | ||
var type = token.type, content = token.content; | ||
if (Array.isArray(content)) { | ||
flatList.push.apply(flatList, __spread(flattenTokens(content))); | ||
} | ||
else { | ||
flatList.push({ type: type, content: content }); | ||
} | ||
}); | ||
return flatList; | ||
} | ||
var MissingGrammarError = /** @class */ (function (_super) { | ||
__extends(MissingGrammarError, _super); | ||
function MissingGrammarError(lang) { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Missing syntax highlighting for language \"" + lang + "\"") || this; | ||
_this.lang = lang; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return MissingGrammarError; | ||
}(Error)); | ||
function codeDiff(_a) { | ||
var prevCode = _a.prevCode, nextCode = _a.nextCode, lineKeys = _a.lineKeys, lang = _a.lang; | ||
var prevNormalCode = normalize(prevCode || ""); | ||
var nextNormalCode = normalize(nextCode || ""); | ||
var prevLines = tokenize(prevNormalCode, lang); | ||
var nextLines = tokenize(nextNormalCode, lang); | ||
var prevKeys = lineKeys || | ||
Array.from({ length: prevLines.length - 1 }, function (x, i) { return i + 1; }); | ||
var nextKeys = getNextKeys(prevNormalCode, nextNormalCode, prevKeys); | ||
var codeMap = {}; | ||
prevKeys.forEach(function (key, index) { return (codeMap[key] = prevLines[index]); }); | ||
nextKeys.forEach(function (key, index) { return (codeMap[key] = nextLines[index]); }); | ||
return { prevKeys: prevKeys, nextKeys: nextKeys, codeMap: codeMap }; | ||
} | ||
function getNextKeys(prevCode, nextCode, prevKeys) { | ||
@@ -314,5 +378,5 @@ var changes = diff.diffLines(prevCode, nextCode); | ||
function normalize(text) { | ||
return text && text.trimEnd().concat("\n"); | ||
return (text || "").trimEnd().concat("\n"); | ||
} | ||
exports.codeDiff = codeDiff; | ||
exports.useCodeDiff = useCodeDiff; |
@@ -1,16 +0,29 @@ | ||
import { CodeLine } from "./tokenizer"; | ||
import { IRawTheme } from "vscode-textmate"; | ||
import { Tween, FullTween } from "@code-hike/utils"; | ||
declare type DiffOptions = { | ||
prevCode: string; | ||
nextCode: string; | ||
lineKeys?: number[]; | ||
code: Tween<string>; | ||
lang: string; | ||
theme: IRawTheme; | ||
}; | ||
declare type CodeTokenData = { | ||
className?: string; | ||
style?: { | ||
color: string | undefined; | ||
}; | ||
}; | ||
declare type CodeToken = [string, CodeTokenData]; | ||
declare type CodeLine = { | ||
tokens: CodeToken[]; | ||
lineNumber: Tween<number>; | ||
}; | ||
declare type LineKey = number; | ||
declare type CodeMap = { | ||
[key: number]: CodeLine; | ||
keys: FullTween<LineKey[]>; | ||
lines: Record<LineKey, CodeLine>; | ||
}; | ||
export { codeDiff, CodeLine, DiffOptions, CodeMap }; | ||
declare function codeDiff({ prevCode, nextCode, lineKeys, lang, }: DiffOptions): { | ||
prevKeys: number[]; | ||
nextKeys: number[]; | ||
export { CodeLine, CodeToken, CodeTokenData, DiffOptions, CodeMap, useCodeDiff, }; | ||
declare function useCodeDiff({ code, lang, theme }: DiffOptions): { | ||
codeMap: CodeMap; | ||
backgroundColor: string; | ||
color: string; | ||
}; |
import { diffLines } from 'diff'; | ||
import Prism$1 from 'prismjs'; | ||
import { setCDN, getHighlighter } from 'shiki'; | ||
import React from 'react'; | ||
import { mapWithDefault } from '@code-hike/utils'; | ||
@@ -18,17 +20,52 @@ /*! ***************************************************************************** | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
var __assign = function() { | ||
__assign = Object.assign || function __assign(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function __read(o, n) { | ||
@@ -57,220 +94,247 @@ var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
(function(Prism) { | ||
var javascript = Prism.util.clone(Prism.languages.javascript); | ||
Prism.languages.jsx = Prism.languages.extend('markup', javascript); | ||
Prism.languages.jsx.tag.pattern= /<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:$-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}))?|\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}))*\s*\/?)?>/i; | ||
Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i; | ||
Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i; | ||
Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/; | ||
Prism.languages.insertBefore('inside', 'attr-name', { | ||
'spread': { | ||
pattern: /\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}/, | ||
inside: { | ||
'punctuation': /\.{3}|[{}.]/, | ||
'attr-value': /\w+/ | ||
} | ||
} | ||
}, Prism.languages.jsx.tag); | ||
Prism.languages.insertBefore('inside', 'attr-value',{ | ||
'script': { | ||
// Allow for two levels of nesting | ||
pattern: /=(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\})/i, | ||
inside: { | ||
'script-punctuation': { | ||
pattern: /^=(?={)/, | ||
alias: 'punctuation' | ||
}, | ||
rest: Prism.languages.jsx | ||
}, | ||
'alias': 'language-javascript' | ||
} | ||
}, Prism.languages.jsx.tag); | ||
// The following will handle plain text inside tags | ||
var stringifyToken = function (token) { | ||
if (!token) { | ||
return ''; | ||
} | ||
if (typeof token === 'string') { | ||
return token; | ||
} | ||
if (typeof token.content === 'string') { | ||
return token.content; | ||
} | ||
return token.content.map(stringifyToken).join(''); | ||
function tokenizePlaceholder(code) { | ||
var lines = code.split("\n"); | ||
return lines.map(function (line) { return [[line, {}]]; }); | ||
} | ||
function getBasicThemedCode(code, theme) { | ||
var lines = code.split("\n"); | ||
var _a = getThemeDefaultColors(theme), fg = _a.fg, bg = _a.bg; | ||
return { | ||
lines: lines.map(function (line) { return [{ content: line }]; }), | ||
fg: fg, | ||
bg: bg, | ||
}; | ||
} | ||
/** | ||
* From https://github.com/shikijs/shiki/blob/HEAD/packages/shiki/src/loader.ts | ||
*/ | ||
var VSCODE_FALLBACK_EDITOR_FG = { | ||
light: "#333333", | ||
dark: "#bbbbbb", | ||
}; | ||
var walkTokens = function (tokens) { | ||
var openedTags = []; | ||
for (var i = 0; i < tokens.length; i++) { | ||
var token = tokens[i]; | ||
var notTagNorBrace = false; | ||
if (typeof token !== 'string') { | ||
if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') { | ||
// We found a tag, now find its kind | ||
if (token.content[0].content[0].content === '</') { | ||
// Closing tag | ||
if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) { | ||
// Pop matching opening tag | ||
openedTags.pop(); | ||
} | ||
} else { | ||
if (token.content[token.content.length - 1].content === '/>') ; else { | ||
// Opening tag | ||
openedTags.push({ | ||
tagName: stringifyToken(token.content[0].content[1]), | ||
openedBraces: 0 | ||
}); | ||
} | ||
} | ||
} else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') { | ||
// Here we might have entered a JSX context inside a tag | ||
openedTags[openedTags.length - 1].openedBraces++; | ||
} else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') { | ||
// Here we might have left a JSX context inside a tag | ||
openedTags[openedTags.length - 1].openedBraces--; | ||
} else { | ||
notTagNorBrace = true; | ||
} | ||
} | ||
if (notTagNorBrace || typeof token === 'string') { | ||
if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) { | ||
// Here we are inside a tag, and not inside a JSX context. | ||
// That's plain text: drop any tokens matched. | ||
var plainText = stringifyToken(token); | ||
// And merge text with adjacent text | ||
if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) { | ||
plainText += stringifyToken(tokens[i + 1]); | ||
tokens.splice(i + 1, 1); | ||
} | ||
if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) { | ||
plainText = stringifyToken(tokens[i - 1]) + plainText; | ||
tokens.splice(i - 1, 1); | ||
i--; | ||
} | ||
tokens[i] = new Prism.Token('plain-text', plainText, null, plainText); | ||
} | ||
} | ||
if (token.content && typeof token.content !== 'string') { | ||
walkTokens(token.content); | ||
} | ||
} | ||
var VSCODE_FALLBACK_EDITOR_BG = { | ||
light: "#fffffe", | ||
dark: "#1e1e1e", | ||
}; | ||
function getThemeDefaultColors(theme) { | ||
var _a, _b, _c, _d, _e, _f; | ||
var fg, bg; | ||
/** | ||
* First try: | ||
* Theme might contain a global `tokenColor` without `name` or `scope` | ||
* Used as default value for foreground/background | ||
*/ | ||
var settings = theme.settings | ||
? theme.settings | ||
: theme.tokenColors; | ||
var globalSetting = settings | ||
? settings.find(function (s) { | ||
return !s.name && !s.scope; | ||
}) | ||
: undefined; | ||
if ((_a = globalSetting === null || globalSetting === void 0 ? void 0 : globalSetting.settings) === null || _a === void 0 ? void 0 : _a.foreground) { | ||
fg = globalSetting.settings.foreground; | ||
} | ||
if ((_b = globalSetting === null || globalSetting === void 0 ? void 0 : globalSetting.settings) === null || _b === void 0 ? void 0 : _b.background) { | ||
bg = globalSetting.settings.background; | ||
} | ||
/** | ||
* Second try: | ||
* If there's no global `tokenColor` without `name` or `scope` | ||
* Use `editor.foreground` and `editor.background` | ||
*/ | ||
if (!fg && ((_d = (_c = theme) === null || _c === void 0 ? void 0 : _c.colors) === null || _d === void 0 ? void 0 : _d["editor.foreground"])) { | ||
fg = theme.colors["editor.foreground"]; | ||
} | ||
if (!bg && ((_f = (_e = theme) === null || _e === void 0 ? void 0 : _e.colors) === null || _f === void 0 ? void 0 : _f["editor.background"])) { | ||
bg = theme.colors["editor.background"]; | ||
} | ||
/** | ||
* Last try: | ||
* If there's no fg/bg color specified in theme, use default | ||
*/ | ||
if (!fg) { | ||
fg = | ||
theme.type === "light" | ||
? VSCODE_FALLBACK_EDITOR_FG.light | ||
: VSCODE_FALLBACK_EDITOR_FG.dark; | ||
} | ||
if (!bg) { | ||
bg = | ||
theme.type === "light" | ||
? VSCODE_FALLBACK_EDITOR_BG.light | ||
: VSCODE_FALLBACK_EDITOR_BG.dark; | ||
} | ||
return { | ||
fg: fg, | ||
bg: bg, | ||
}; | ||
} | ||
Prism.hooks.add('after-tokenize', function (env) { | ||
if (env.language !== 'jsx' && env.language !== 'tsx') { | ||
return; | ||
} | ||
walkTokens(env.tokens); | ||
}); | ||
function useAsyncMemo(_a, deps) { | ||
var isReady = _a.isReady, load = _a.load, run = _a.run, placeholder = _a.placeholder; | ||
var _b = __read(React.useState({ result: null, deps: [], version: 0 }), 2), _c = _b[0], lastLoadedResult = _c.result, lastLoadedDeps = _c.deps, version = _c.version, setState = _b[1]; | ||
React.useEffect(function () { | ||
if (!isReady) { | ||
load().then(function () { | ||
setState(function (_a) { | ||
var version = _a.version; | ||
return ({ | ||
result: run(), | ||
deps: deps, | ||
version: version + 1, | ||
}); | ||
}); | ||
}); | ||
} | ||
}, deps); | ||
return React.useMemo(function () { | ||
if (depsChanged(deps, lastLoadedDeps)) { | ||
return isReady ? run() : placeholder(); | ||
} | ||
else { | ||
return lastLoadedResult; | ||
} | ||
}, __spread([version], deps)); | ||
} | ||
function depsChanged(oldDeps, newDeps) { | ||
if (oldDeps === newDeps) | ||
return false; | ||
if (!oldDeps || !newDeps) | ||
return true; | ||
return oldDeps === null || oldDeps === void 0 ? void 0 : oldDeps.some(function (dep, index) { return newDeps[index] !== dep; }); | ||
} | ||
}(Prism)); | ||
var newlineRe = /\r\n|\r|\n/; | ||
Prism$1.manual = true; | ||
function tokenize(code, lang) { | ||
var grammar = Prism$1.languages[lang]; | ||
if (!grammar) { | ||
throw new MissingGrammarError(lang); | ||
} | ||
var prismTokens = Prism$1.tokenize(code, Prism$1.languages[lang]); | ||
var nestedTokens = tokenizeStrings(prismTokens); | ||
var tokens = flattenTokens(nestedTokens); | ||
var currentLine = []; | ||
var lines = [currentLine]; | ||
tokens.forEach(function (token) { | ||
var contentLines = token.content.split(newlineRe); | ||
var firstContent = contentLines.shift(); | ||
if (firstContent !== undefined && firstContent !== "") { | ||
currentLine.push([firstContent, token.type]); | ||
} | ||
contentLines.forEach(function (content) { | ||
currentLine = []; | ||
lines.push(currentLine); | ||
if (content !== "") { | ||
currentLine.push([content, token.type]); | ||
var _a; | ||
var highlighterPromise = null; | ||
var highlighter = null; | ||
function useHighlighter(code, lang, theme) { | ||
return useAsyncMemo({ | ||
isReady: isHighlighterReady(lang, theme), | ||
load: function () { return loadHighlighter(lang, theme); }, | ||
run: function () { return highlight(code, lang, theme); }, | ||
placeholder: function () { | ||
var _a = getBasicThemedCode("", theme), bg = _a.bg, fg = _a.fg; | ||
var lines = mapWithDefault(code, "", tokenizePlaceholder); | ||
return { lines: lines, bg: bg, fg: fg }; | ||
}, | ||
}, [code.prev, code.next, lang, theme]); | ||
} | ||
function isHighlighterReady(lang, theme) { | ||
return (highlighter != null && | ||
!missingTheme(highlighter, theme) && | ||
!missingLang(highlighter, lang)); | ||
} | ||
function loadHighlighter(lang, theme) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (highlighterPromise === null) { | ||
setCDN("https://unpkg.com/shiki/"); | ||
highlighterPromise = getHighlighter({ | ||
theme: theme, | ||
langs: [lang], | ||
}); | ||
} | ||
if (!(highlighter === null)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, highlighterPromise]; | ||
case 1: | ||
highlighter = _a.sent(); | ||
_a.label = 2; | ||
case 2: | ||
if (!missingTheme(highlighter, theme)) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, highlighter.loadTheme(theme)]; | ||
case 3: | ||
_a.sent(); | ||
_a.label = 4; | ||
case 4: | ||
if (!missingLang(highlighter, lang)) return [3 /*break*/, 6]; | ||
return [4 /*yield*/, highlighter.loadLanguage(lang)]; | ||
case 5: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
return lines; | ||
} | ||
function tokenizeStrings(prismTokens, parentType) { | ||
if (parentType === void 0) { parentType = "plain"; } | ||
return prismTokens.map(function (prismToken) { | ||
return wrapToken(prismToken, parentType); | ||
function highlight(code, lang, theme) { | ||
// assumes highlighter isReady | ||
var _a = highlighter.getTheme(theme.name), fg = _a.fg, bg = _a.bg; | ||
var lines = mapWithDefault(code, "", function (code) { | ||
return getCodeLines(highlighter, code, lang, theme); | ||
}); | ||
return { lines: lines, bg: bg, fg: fg }; | ||
} | ||
function wrapToken(prismToken, parentType) { | ||
if (parentType === void 0) { parentType = "plain"; } | ||
if (typeof prismToken === "string") { | ||
return { | ||
type: parentType, | ||
content: prismToken, | ||
function getCodeLines(highlighter, code, lang, theme) { | ||
var lines = highlighter.codeToThemedTokens(code, lang, theme.name, { | ||
includeExplanation: false, | ||
}); | ||
return lines.map(function (line) { | ||
return line.map(function (token) { return [ | ||
token.content, | ||
{ style: getStyle(token) }, | ||
]; }); | ||
}); | ||
} | ||
function missingTheme(highlighter, theme) { | ||
return !highlighter | ||
.getLoadedThemes() | ||
.some(function (t) { return t === theme.name; }); | ||
} | ||
function missingLang(highlighter, lang) { | ||
return !highlighter | ||
.getLoadedLanguages() | ||
.some(function (l) { return l === lang; }); | ||
} | ||
var FONT_STYLE_TO_CSS = (_a = {}, | ||
_a[-1 /* NotSet */] = {}, | ||
_a[0 /* None */] = {}, | ||
_a[1 /* Italic */] = { fontStyle: "italic" }, | ||
_a[2 /* Bold */] = { fontWeight: "bold" }, | ||
_a[4 /* Underline */] = { textDecoration: "underline" }, | ||
_a); | ||
function getStyle(token) { | ||
var fontStyle = token.fontStyle | ||
? FONT_STYLE_TO_CSS[token.fontStyle] | ||
: {}; | ||
return __assign({ color: token.color }, fontStyle); | ||
} | ||
function useCodeDiff(_a) { | ||
var code = _a.code, lang = _a.lang, theme = _a.theme; | ||
var normalCode = mapWithDefault(code, "", normalize); | ||
var _b = useHighlighter(normalCode, lang, theme), lines = _b.lines, bg = _b.bg, fg = _b.fg; | ||
return React.useMemo(function () { | ||
var prevKeys = Array.from({ length: lines.prev.length - 1 }, function (x, i) { return i + 1; }); | ||
var nextKeys = getNextKeys(normalCode.prev, normalCode.next, prevKeys); | ||
var codeMap = { | ||
keys: { prev: prevKeys, next: nextKeys }, | ||
lines: {}, | ||
}; | ||
} | ||
if (Array.isArray(prismToken.content)) { | ||
prevKeys.forEach(function (key, index) { | ||
return (codeMap.lines[key] = { | ||
tokens: lines.prev[index], | ||
lineNumber: { prev: index + 1 }, | ||
}); | ||
}); | ||
nextKeys.forEach(function (key, index) { | ||
if (key in codeMap.lines) { | ||
codeMap.lines[key].lineNumber.next = index + 1; | ||
} | ||
else { | ||
codeMap.lines[key] = { | ||
tokens: lines.next[index], | ||
lineNumber: { next: index + 1 }, | ||
}; | ||
} | ||
}); | ||
return { | ||
type: prismToken.type, | ||
content: tokenizeStrings(prismToken.content, prismToken.type), | ||
codeMap: codeMap, | ||
backgroundColor: bg, | ||
color: fg, | ||
}; | ||
} | ||
return wrapToken(prismToken.content, prismToken.type); | ||
}, [lines.prev, lines.next, bg, fg]); | ||
} | ||
// Take a list of nested tokens | ||
// (token.content may contain an array of tokens) | ||
// and flatten it so content is always a string | ||
// and type the type of the leaf | ||
function flattenTokens(tokens) { | ||
var flatList = []; | ||
tokens.forEach(function (token) { | ||
var type = token.type, content = token.content; | ||
if (Array.isArray(content)) { | ||
flatList.push.apply(flatList, __spread(flattenTokens(content))); | ||
} | ||
else { | ||
flatList.push({ type: type, content: content }); | ||
} | ||
}); | ||
return flatList; | ||
} | ||
var MissingGrammarError = /** @class */ (function (_super) { | ||
__extends(MissingGrammarError, _super); | ||
function MissingGrammarError(lang) { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Missing syntax highlighting for language \"" + lang + "\"") || this; | ||
_this.lang = lang; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return MissingGrammarError; | ||
}(Error)); | ||
function codeDiff(_a) { | ||
var prevCode = _a.prevCode, nextCode = _a.nextCode, lineKeys = _a.lineKeys, lang = _a.lang; | ||
var prevNormalCode = normalize(prevCode || ""); | ||
var nextNormalCode = normalize(nextCode || ""); | ||
var prevLines = tokenize(prevNormalCode, lang); | ||
var nextLines = tokenize(nextNormalCode, lang); | ||
var prevKeys = lineKeys || | ||
Array.from({ length: prevLines.length - 1 }, function (x, i) { return i + 1; }); | ||
var nextKeys = getNextKeys(prevNormalCode, nextNormalCode, prevKeys); | ||
var codeMap = {}; | ||
prevKeys.forEach(function (key, index) { return (codeMap[key] = prevLines[index]); }); | ||
nextKeys.forEach(function (key, index) { return (codeMap[key] = nextLines[index]); }); | ||
return { prevKeys: prevKeys, nextKeys: nextKeys, codeMap: codeMap }; | ||
} | ||
function getNextKeys(prevCode, nextCode, prevKeys) { | ||
@@ -305,5 +369,5 @@ var changes = diffLines(prevCode, nextCode); | ||
function normalize(text) { | ||
return text && text.trimEnd().concat("\n"); | ||
return (text || "").trimEnd().concat("\n"); | ||
} | ||
export { codeDiff }; | ||
export { useCodeDiff }; |
{ | ||
"name": "@code-hike/code-diff", | ||
"version": "0.3.0--canary.75.b3e0bf9.0", | ||
"version": "0.3.0--canary.77.ade5d72.0", | ||
"main": "dist/index.cjs.js", | ||
@@ -16,3 +16,3 @@ "typings": "dist/index.d.ts", | ||
"devDependencies": { | ||
"@code-hike/script": "0.3.0--canary.75.b3e0bf9.0", | ||
"@code-hike/script": "0.3.0--canary.77.ade5d72.0", | ||
"@types/diff": "^4.0.2", | ||
@@ -36,6 +36,8 @@ "@types/jest": "^24.0.15", | ||
"dependencies": { | ||
"@code-hike/utils": "0.3.0--canary.77.ade5d72.0", | ||
"diff": "^4.0.2", | ||
"prismjs": "^1.22.0" | ||
"prismjs": "^1.22.0", | ||
"shiki": "^0.9.5" | ||
}, | ||
"gitHead": "b3e0bf994f016d67dfdd881b3654e3efff8f798b" | ||
"gitHead": "ade5d72c2e84b4893c40b07e576b9aff818d6cec" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33608
789
4
1
+ Addedshiki@^0.9.5
+ Added@code-hike/utils@0.3.0--canary.77.ade5d72.0(transitive)
+ Addedjsonc-parser@3.3.1(transitive)
+ Addedreact@19.0.0(transitive)
+ Addedshiki@0.9.15(transitive)
+ Addedvscode-oniguruma@1.7.0(transitive)
+ Addedvscode-textmate@5.2.0(transitive)