@shikijs/core 1.2.4 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -881,6 +881,7 @@ interface ShikiTransformerContext extends ShikiTransformerContextSource {
881
881
  readonly pre: Element;
882
882
  readonly code: Element;
883
883
  readonly lines: Element[];
884
+ readonly structure: CodeToHastOptions['structure'];
884
885
  /**
885
886
  * Utility to append class to a hast node
886
887
  *
@@ -1093,6 +1094,15 @@ interface CodeToHastOptionsCommon<Languages extends string = string> extends Tra
1093
1094
  * @default true
1094
1095
  */
1095
1096
  mergeWhitespaces?: boolean | 'never';
1097
+ /**
1098
+ * The structure of the generated HAST and HTML.
1099
+ *
1100
+ * - `classic`: The classic structure with `<pre>` and `<code>` elements, each line wrapped with a `<span class="line">` element.
1101
+ * - `inline`: All tokens are rendered as `<span>`, line breaks are rendered as `<br>`. No `<pre>` or `<code>` elements. Default forground and background colors are not applied.
1102
+ *
1103
+ * @default 'classic'
1104
+ */
1105
+ structure?: 'classic' | 'inline';
1096
1106
  }
1097
1107
  interface CodeOptionsMeta {
1098
1108
  /**
package/dist/index.mjs CHANGED
@@ -1032,10 +1032,11 @@ function codeToHast(internal, code, options, transformerContext = {
1032
1032
  function tokensToHast(tokens, options, transformerContext) {
1033
1033
  const transformers = getTransformers(options);
1034
1034
  const lines = [];
1035
- const tree = {
1035
+ const root = {
1036
1036
  type: 'root',
1037
1037
  children: [],
1038
1038
  };
1039
+ const { structure = 'classic', } = options;
1039
1040
  let preNode = {
1040
1041
  type: 'element',
1041
1042
  tagName: 'pre',
@@ -1057,6 +1058,7 @@ function tokensToHast(tokens, options, transformerContext) {
1057
1058
  const lineNodes = [];
1058
1059
  const context = {
1059
1060
  ...transformerContext,
1061
+ structure,
1060
1062
  addClassToHast,
1061
1063
  get source() {
1062
1064
  return transformerContext.source;
@@ -1068,7 +1070,7 @@ function tokensToHast(tokens, options, transformerContext) {
1068
1070
  return options;
1069
1071
  },
1070
1072
  get root() {
1071
- return tree;
1073
+ return root;
1072
1074
  },
1073
1075
  get pre() {
1074
1076
  return preNode;
@@ -1081,8 +1083,12 @@ function tokensToHast(tokens, options, transformerContext) {
1081
1083
  },
1082
1084
  };
1083
1085
  tokens.forEach((line, idx) => {
1084
- if (idx)
1085
- lines.push({ type: 'text', value: '\n' });
1086
+ if (idx) {
1087
+ if (structure === 'inline')
1088
+ root.children.push({ type: 'element', tagName: 'br', properties: {}, children: [] });
1089
+ else if (structure === 'classic')
1090
+ lines.push({ type: 'text', value: '\n' });
1091
+ }
1086
1092
  let lineNode = {
1087
1093
  type: 'element',
1088
1094
  tagName: 'span',
@@ -1102,21 +1108,28 @@ function tokensToHast(tokens, options, transformerContext) {
1102
1108
  tokenNode.properties.style = style;
1103
1109
  for (const transformer of transformers)
1104
1110
  tokenNode = transformer?.span?.call(context, tokenNode, idx + 1, col, lineNode) || tokenNode;
1105
- lineNode.children.push(tokenNode);
1111
+ if (structure === 'inline')
1112
+ root.children.push(tokenNode);
1113
+ else if (structure === 'classic')
1114
+ lineNode.children.push(tokenNode);
1106
1115
  col += token.content.length;
1107
1116
  }
1108
- for (const transformer of transformers)
1109
- lineNode = transformer?.line?.call(context, lineNode, idx + 1) || lineNode;
1110
- lineNodes.push(lineNode);
1111
- lines.push(lineNode);
1117
+ if (structure === 'classic') {
1118
+ for (const transformer of transformers)
1119
+ lineNode = transformer?.line?.call(context, lineNode, idx + 1) || lineNode;
1120
+ lineNodes.push(lineNode);
1121
+ lines.push(lineNode);
1122
+ }
1112
1123
  });
1113
- for (const transformer of transformers)
1114
- codeNode = transformer?.code?.call(context, codeNode) || codeNode;
1115
- preNode.children.push(codeNode);
1116
- for (const transformer of transformers)
1117
- preNode = transformer?.pre?.call(context, preNode) || preNode;
1118
- tree.children.push(preNode);
1119
- let result = tree;
1124
+ if (structure === 'classic') {
1125
+ for (const transformer of transformers)
1126
+ codeNode = transformer?.code?.call(context, codeNode) || codeNode;
1127
+ preNode.children.push(codeNode);
1128
+ for (const transformer of transformers)
1129
+ preNode = transformer?.pre?.call(context, preNode) || preNode;
1130
+ root.children.push(preNode);
1131
+ }
1132
+ let result = root;
1120
1133
  for (const transformer of transformers)
1121
1134
  result = transformer?.root?.call(context, result) || result;
1122
1135
  return result;
@@ -3259,6 +3272,12 @@ function stringifyEntities(value, options) {
3259
3272
  */
3260
3273
 
3261
3274
 
3275
+ const htmlCommentRegex = /^>|^->|<!--|-->|--!>|<!-$/g;
3276
+
3277
+ // Declare arrays as variables so it can be cached by `stringifyEntities`
3278
+ const bogusCommentEntitySubset = ['>'];
3279
+ const commentEntitySubset = ['<', '>'];
3280
+
3262
3281
  /**
3263
3282
  * Serialize a comment.
3264
3283
  *
@@ -3279,10 +3298,12 @@ function comment(node, _1, _2, state) {
3279
3298
  ? '<?' +
3280
3299
  stringifyEntities(
3281
3300
  node.value,
3282
- Object.assign({}, state.settings.characterReferences, {subset: ['>']})
3301
+ Object.assign({}, state.settings.characterReferences, {
3302
+ subset: bogusCommentEntitySubset
3303
+ })
3283
3304
  ) +
3284
3305
  '>'
3285
- : '<!--' + node.value.replace(/^>|^->|<!--|-->|--!>|<!-$/g, encode) + '-->'
3306
+ : '<!--' + node.value.replace(htmlCommentRegex, encode) + '-->'
3286
3307
 
3287
3308
  /**
3288
3309
  * @param {string} $0
@@ -3291,7 +3312,7 @@ function comment(node, _1, _2, state) {
3291
3312
  return stringifyEntities(
3292
3313
  $0,
3293
3314
  Object.assign({}, state.settings.characterReferences, {
3294
- subset: ['<', '>']
3315
+ subset: commentEntitySubset
3295
3316
  })
3296
3317
  )
3297
3318
  }
@@ -4116,7 +4137,7 @@ function element(node, index, parent, state) {
4116
4137
  state.schema = svg;
4117
4138
  }
4118
4139
 
4119
- const attrs = serializeAttributes(state, node.properties);
4140
+ const attributes = serializeAttributes(state, node.properties);
4120
4141
 
4121
4142
  const content = state.all(
4122
4143
  schema.space === 'html' && node.tagName === 'template' ? node.content : node
@@ -4132,14 +4153,14 @@ function element(node, index, parent, state) {
4132
4153
  // longer void.
4133
4154
  if (content) selfClosing = false;
4134
4155
 
4135
- if (attrs || !omit || !opening(node, index, parent)) {
4136
- parts.push('<', node.tagName, attrs ? ' ' + attrs : '');
4156
+ if (attributes || !omit || !opening(node, index, parent)) {
4157
+ parts.push('<', node.tagName, attributes ? ' ' + attributes : '');
4137
4158
 
4138
4159
  if (
4139
4160
  selfClosing &&
4140
4161
  (schema.space === 'svg' || state.settings.closeSelfClosing)
4141
4162
  ) {
4142
- last = attrs.charAt(attrs.length - 1);
4163
+ last = attributes.charAt(attributes.length - 1);
4143
4164
  if (
4144
4165
  !state.settings.tightSelfClosing ||
4145
4166
  last === '/' ||
@@ -4165,20 +4186,20 @@ function element(node, index, parent, state) {
4165
4186
 
4166
4187
  /**
4167
4188
  * @param {State} state
4168
- * @param {Properties | null | undefined} props
4189
+ * @param {Properties | null | undefined} properties
4169
4190
  * @returns {string}
4170
4191
  */
4171
- function serializeAttributes(state, props) {
4192
+ function serializeAttributes(state, properties) {
4172
4193
  /** @type {Array<string>} */
4173
4194
  const values = [];
4174
4195
  let index = -1;
4175
4196
  /** @type {string} */
4176
4197
  let key;
4177
4198
 
4178
- if (props) {
4179
- for (key in props) {
4180
- if (props[key] !== null && props[key] !== undefined) {
4181
- const value = serializeAttribute(state, key, props[key]);
4199
+ if (properties) {
4200
+ for (key in properties) {
4201
+ if (properties[key] !== null && properties[key] !== undefined) {
4202
+ const value = serializeAttribute(state, key, properties[key]);
4182
4203
  if (value) values.push(value);
4183
4204
  }
4184
4205
  }
@@ -4317,6 +4338,9 @@ function serializeAttribute(state, key, value) {
4317
4338
  */
4318
4339
 
4319
4340
 
4341
+ // Declare array as variable so it can be cached by `stringifyEntities`
4342
+ const textEntitySubset = ['<', '&'];
4343
+
4320
4344
  /**
4321
4345
  * Serialize a text node.
4322
4346
  *
@@ -4340,7 +4364,7 @@ function text(node, _, parent, state) {
4340
4364
  : stringifyEntities(
4341
4365
  node.value,
4342
4366
  Object.assign({}, state.settings.characterReferences, {
4343
- subset: ['<', '&']
4367
+ subset: textEntitySubset
4344
4368
  })
4345
4369
  )
4346
4370
  }
@@ -4921,7 +4945,7 @@ function isResponse(dataOrOptions) {
4921
4945
  function isArrayBuffer(data) {
4922
4946
  return (typeof ArrayBuffer !== 'undefined' && (data instanceof ArrayBuffer || ArrayBuffer.isView(data)))
4923
4947
  // eslint-disable-next-line node/prefer-global/buffer
4924
- || (typeof Buffer !== 'undefined' && Buffer.isBuffer(data))
4948
+ || (typeof Buffer !== 'undefined' && Buffer.isBuffer?.(data))
4925
4949
  || (typeof SharedArrayBuffer !== 'undefined' && data instanceof SharedArrayBuffer)
4926
4950
  || (typeof Uint32Array !== 'undefined' && data instanceof Uint32Array);
4927
4951
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/core",
3
3
  "type": "module",
4
- "version": "1.2.4",
4
+ "version": "1.4.0",
5
5
  "description": "Core of Shiki",
6
6
  "author": "Pine Wu <octref@gmail.com>; Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -60,7 +60,7 @@
60
60
  "dist"
61
61
  ],
62
62
  "devDependencies": {
63
- "hast-util-to-html": "^9.0.0",
63
+ "hast-util-to-html": "^9.0.1",
64
64
  "vscode-oniguruma": "^1.7.0"
65
65
  },
66
66
  "scripts": {