Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@code-hike/code-diff

Package Overview
Dependencies
Maintainers
1
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@code-hike/code-diff - npm Package Compare versions

Comparing version 0.3.0--canary.75.b3e0bf9.0 to 0.3.0--canary.77.ade5d72.0

dist/highlighter.d.ts

500

dist/index.cjs.js

@@ -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"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc