@motionscript/code 0.1.0-alpha.0 → 0.1.0-alpha.10

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/NOTICE +49 -0
  3. package/README.md +148 -50
  4. package/dist/browser/THIRD_PARTY_LICENSES.txt +431 -0
  5. package/dist/browser/index.js +10 -7
  6. package/dist/browser/index.js.map +3 -3
  7. package/dist/browser/manifest.json +85 -3
  8. package/dist/code-range.d.ts +7 -1
  9. package/dist/code-range.d.ts.map +1 -1
  10. package/dist/code-range.js +9 -1
  11. package/dist/code-range.js.map +1 -1
  12. package/dist/diff.d.ts +14 -0
  13. package/dist/diff.d.ts.map +1 -1
  14. package/dist/diff.js +134 -2
  15. package/dist/diff.js.map +1 -1
  16. package/dist/engine.d.ts +2 -2
  17. package/dist/engine.d.ts.map +1 -1
  18. package/dist/engine.js +4 -4
  19. package/dist/engine.js.map +1 -1
  20. package/dist/highlight.d.ts +10 -2
  21. package/dist/highlight.d.ts.map +1 -1
  22. package/dist/highlight.js +40 -6
  23. package/dist/highlight.js.map +1 -1
  24. package/dist/layout.d.ts +1 -1
  25. package/dist/layout.d.ts.map +1 -1
  26. package/dist/layout.js.map +1 -1
  27. package/dist/measure-cache.d.ts +2 -2
  28. package/dist/measure-cache.d.ts.map +1 -1
  29. package/dist/measure-cache.js +0 -0
  30. package/dist/measure-cache.js.map +1 -1
  31. package/dist/node.d.ts +275 -281
  32. package/dist/node.d.ts.map +1 -1
  33. package/dist/node.js +634 -700
  34. package/dist/node.js.map +1 -1
  35. package/dist/nodes.d.ts +6 -9
  36. package/dist/nodes.d.ts.map +1 -1
  37. package/dist/nodes.js +7 -9
  38. package/dist/nodes.js.map +1 -1
  39. package/dist/render.d.ts +10 -3
  40. package/dist/render.d.ts.map +1 -1
  41. package/dist/render.js +60 -1
  42. package/dist/render.js.map +1 -1
  43. package/dist/style.d.ts +3 -3
  44. package/dist/style.d.ts.map +1 -1
  45. package/dist/style.js +10 -6
  46. package/dist/style.js.map +1 -1
  47. package/dist/tokens.d.ts.map +1 -1
  48. package/dist/tokens.js +5 -1
  49. package/dist/tokens.js.map +1 -1
  50. package/dist/transitions.d.ts +19 -1
  51. package/dist/transitions.d.ts.map +1 -1
  52. package/dist/transitions.js.map +1 -1
  53. package/package.json +7 -4
  54. package/src/code-range.ts +10 -1
  55. package/src/diff.ts +137 -2
  56. package/src/engine.ts +5 -5
  57. package/src/highlight.ts +54 -5
  58. package/src/layout.ts +1 -1
  59. package/src/measure-cache.ts +0 -0
  60. package/src/node.ts +767 -747
  61. package/src/nodes.ts +8 -10
  62. package/src/render.ts +71 -3
  63. package/src/style.ts +11 -7
  64. package/src/tokens.ts +5 -1
  65. package/src/transitions.ts +21 -1
package/src/highlight.ts CHANGED
@@ -54,6 +54,28 @@ const LANGUAGE_ALIASES: Record<string, string> = {
54
54
  shell: "javascript", // no shell grammar bundled; fall back rather than throw
55
55
  };
56
56
 
57
+ /** Names that mean "no grammar, on purpose": drawn as plain text without a warning. */
58
+ const PLAIN_LANGUAGES = new Set(["", "text", "plaintext"]);
59
+
60
+ const warned = new Set<string>();
61
+
62
+ /** One `console.warn` per `kind:name` for the life of the process, so a listing redrawn every frame says it once. */
63
+ function warnOnce(kind: string, name: string, message: string): void {
64
+ const key = `${kind}:${name}`;
65
+ if (warned.has(key)) return;
66
+ warned.add(key);
67
+ console.warn(`[Code] ${message}`);
68
+ }
69
+
70
+ /**
71
+ * The source as the highlighter and the commands see it: lines joined by `\n`.
72
+ * A `\r\n` (or a lone `\r`) from a file or a clipboard would otherwise survive
73
+ * as a character at the end of a line, measured and drawn as a token.
74
+ */
75
+ export function normalizeSource(code: string): string {
76
+ return code.indexOf("\r") === -1 ? code : code.replace(/\r\n?/g, "\n");
77
+ }
78
+
57
79
  function resolveLanguageKey(language: string): string {
58
80
  const key = language.toLowerCase();
59
81
  return LANGUAGE_ALIASES[key] ?? key;
@@ -80,11 +102,18 @@ export function registerCodeTheme(style: CodeHighlightStyle): void {
80
102
  /**
81
103
  * Resolve a theme reference (a registered name, or a CodeHighlightStyle object)
82
104
  * to a concrete style. Unknown names fall back to the Motion Canvas default so a
83
- * stray theme string never throws.
105
+ * stray theme string never throws, with one warning per name.
84
106
  */
85
107
  export function resolveTheme(theme: CodeTheme): CodeHighlightStyle {
86
108
  if (typeof theme !== "string") return theme;
87
- return themesByName.get(theme) ?? DefaultHighlightStyle;
109
+ const style = themesByName.get(theme);
110
+ if (style) return style;
111
+ warnOnce(
112
+ "theme",
113
+ theme,
114
+ `unknown theme "${theme}"; using "${DefaultHighlightStyle.name}". Built-in themes: ${Object.keys(BUILTIN_THEMES).join(", ")}; register others with registerCodeTheme.`,
115
+ );
116
+ return DefaultHighlightStyle;
88
117
  }
89
118
 
90
119
  /** Has `language` finished loading its parser? */
@@ -97,7 +126,9 @@ function isLanguageLoaded(language: string): boolean {
97
126
  * but kept in the signature for API parity with the former Shiki implementation).
98
127
  * Resolves once every requested language's parser is available. Unknown languages
99
128
  * resolve without loading anything — {@link canHighlight} stays false for them and
100
- * the node renders them as plain text.
129
+ * the node renders them as plain text, with one warning per language. A grammar
130
+ * whose import is rejected is reported the same way and is tried again by the
131
+ * next call.
101
132
  */
102
133
  export function ensureHighlighter(
103
134
  _themes: string[] = DEFAULT_THEMES,
@@ -110,7 +141,17 @@ export function ensureHighlighter(
110
141
  if (loadedParsers.has(key)) continue;
111
142
 
112
143
  const loader = LANGUAGE_LOADERS[key];
113
- if (!loader) continue; // unsupported language; leave it unhighlighted
144
+ if (!loader) {
145
+ // Unsupported language; leave it unhighlighted, and say so.
146
+ if (!PLAIN_LANGUAGES.has(key)) {
147
+ warnOnce(
148
+ "language",
149
+ key,
150
+ `no grammar for language "${lang}"; drawing it as plain text. Supported: ${Object.keys(LANGUAGE_LOADERS).join(", ")} (aliases: ${Object.keys(LANGUAGE_ALIASES).join(", ")}).`,
151
+ );
152
+ }
153
+ continue;
154
+ }
114
155
 
115
156
  let job = inFlightLangs.get(key);
116
157
  if (!job) {
@@ -119,7 +160,14 @@ export function ensureHighlighter(
119
160
  loadedParsers.set(key, parser);
120
161
  return parser;
121
162
  })
122
- .catch(() => null)
163
+ .catch((error: unknown) => {
164
+ warnOnce(
165
+ "load",
166
+ key,
167
+ `could not load the "${lang}" grammar; drawing it as plain text: ${error instanceof Error ? error.message : String(error)}`,
168
+ );
169
+ return null;
170
+ })
123
171
  .finally(() => inFlightLangs.delete(key));
124
172
  inFlightLangs.set(key, job);
125
173
  }
@@ -248,6 +296,7 @@ export function highlightToTokens(
248
296
  language: string,
249
297
  theme: CodeTheme = DefaultHighlightStyle,
250
298
  ): { content: string; color?: string }[][] {
299
+ code = normalizeSource(code);
251
300
  const style = resolveTheme(theme);
252
301
  const cache = prepareHighlight(code, language, style);
253
302
 
package/src/layout.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { InsetsResolved, MeasureContext2D, RenderContext2D } from "@motionscript/core";
1
+ import type { InsetsResolved, MeasureContext2D, RenderContext2D } from "@motionscript/sdk";
2
2
  import type { TokenAdvanceCache } from "./measure-cache";
3
3
  import type { IdLine } from "./tokens";
4
4
 
Binary file