@jacobknightley/fabric-format 0.0.3 → 0.0.4
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.
- package/README.md +4 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/notebook-formatter.d.ts +8 -0
- package/dist/notebook-formatter.js +62 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,13 +50,11 @@ Format Fabric notebooks directly in your browser with a single click.
|
|
|
50
50
|
|
|
51
51
|
1. Download `fabric-format-chromium.zip` from the [latest release](https://github.com/jacobknightley/fabric-format/releases)
|
|
52
52
|
2. Extract the zip file
|
|
53
|
-
3.
|
|
54
|
-
- **Chrome:**
|
|
55
|
-
- **Edge:**
|
|
56
|
-
4. Enable **Developer mode** (toggle in top-right)
|
|
57
|
-
5. Click **Load unpacked** and select the extracted folder
|
|
53
|
+
3. Load the unpacked extension in your browser:
|
|
54
|
+
- **Chrome:** [Install an unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked)
|
|
55
|
+
- **Edge:** [Sideload an extension](https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/getting-started/extension-sideloading)
|
|
58
56
|
|
|
59
|
-
> **Note:** Plan to eventually
|
|
57
|
+
> **Note:** Plan to eventually publish to the Chrome Web Store and Edge Add-ons.
|
|
60
58
|
|
|
61
59
|
### Usage
|
|
62
60
|
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
export { formatSql, needsFormatting } from './formatters/sparksql/index.js';
|
|
13
13
|
export { getFormatterRegistry, detectLanguage, SqlFormatter, getSqlFormatter, isSqlCode, PythonFormatter, getPythonFormatter, isPythonCode, type LanguageFormatter, type FormatterOptions, type FormatResult, type FormatterConfig, type FormatterRegistry, } from './formatters/index.js';
|
|
14
14
|
export { formatCell, formatCellSync, initializePythonFormatter, isPythonFormatterReady, type FormatCellResult, type CellType, } from './cell-formatter.js';
|
|
15
|
-
export { parseNotebook, formatNotebook, type NotebookCell, type FabricNotebook, type FormatStats, } from './notebook-formatter.js';
|
|
15
|
+
export { parseNotebook, formatNotebook, NotebookStructureError, type NotebookCell, type FabricNotebook, type FormatStats, } from './notebook-formatter.js';
|
|
16
16
|
export { DEFAULT_RUFF_CONFIG, RUFF_WASM_CONFIG, type RuffConfig, type RuffFormatConfig, type WasmInitOptions, } from './formatters/python/index.js';
|
|
17
17
|
export { hasFormatOff, detectCollapseDirectives, hasCollapseDirective, type FormatDirectiveInfo } from './formatters/sparksql/index.js';
|
|
18
18
|
export type { AnalyzerResult, FormattingState, MultiArgFunctionInfo, WindowDefInfo, TokenContext, PendingComment, ExpandedFunction, ExpandedWindow } from './formatters/sparksql/types.js';
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ export { formatCell, formatCellSync, initializePythonFormatter, isPythonFormatte
|
|
|
30
30
|
// ============================================================================
|
|
31
31
|
// Notebook Formatter (High-level API)
|
|
32
32
|
// ============================================================================
|
|
33
|
-
export { parseNotebook, formatNotebook, } from './notebook-formatter.js';
|
|
33
|
+
export { parseNotebook, formatNotebook, NotebookStructureError, } from './notebook-formatter.js';
|
|
34
34
|
// ============================================================================
|
|
35
35
|
// Configuration (Python/Ruff)
|
|
36
36
|
// ============================================================================
|
|
@@ -79,6 +79,14 @@ export interface FormatStats {
|
|
|
79
79
|
cellsSkipped: number;
|
|
80
80
|
errors: string[];
|
|
81
81
|
}
|
|
82
|
+
/** Error thrown when a notebook cell has invalid structure */
|
|
83
|
+
export declare class NotebookStructureError extends Error {
|
|
84
|
+
readonly cellIndex: number;
|
|
85
|
+
readonly lineNumber: number;
|
|
86
|
+
readonly metadataLanguage: string;
|
|
87
|
+
readonly fileDefaultLanguage: string;
|
|
88
|
+
constructor(message: string, cellIndex: number, lineNumber: number, metadataLanguage: string, fileDefaultLanguage: string);
|
|
89
|
+
}
|
|
82
90
|
/**
|
|
83
91
|
* Parse a Fabric notebook file into cells.
|
|
84
92
|
* @param content The file content
|
|
@@ -66,12 +66,68 @@ const R_CONFIG = {
|
|
|
66
66
|
fabricHeader: '# Fabric notebook source', // Check if R has different header
|
|
67
67
|
defaultLanguage: 'r',
|
|
68
68
|
};
|
|
69
|
+
/** Error thrown when a notebook cell has invalid structure */
|
|
70
|
+
export class NotebookStructureError extends Error {
|
|
71
|
+
cellIndex;
|
|
72
|
+
lineNumber;
|
|
73
|
+
metadataLanguage;
|
|
74
|
+
fileDefaultLanguage;
|
|
75
|
+
constructor(message, cellIndex, lineNumber, metadataLanguage, fileDefaultLanguage) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.cellIndex = cellIndex;
|
|
78
|
+
this.lineNumber = lineNumber;
|
|
79
|
+
this.metadataLanguage = metadataLanguage;
|
|
80
|
+
this.fileDefaultLanguage = fileDefaultLanguage;
|
|
81
|
+
this.name = 'NotebookStructureError';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
69
84
|
// ============================================================================
|
|
70
85
|
// INTERNAL UTILITIES
|
|
71
86
|
// ============================================================================
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Get the valid raw (uncommented) languages for a file type.
|
|
89
|
+
* Raw cells must match the file's native language - other languages must use MAGIC prefix.
|
|
90
|
+
*/
|
|
91
|
+
function getValidRawLanguages(defaultLanguage) {
|
|
92
|
+
switch (defaultLanguage) {
|
|
93
|
+
case 'python':
|
|
94
|
+
// Python files: raw cells can be python or pyspark
|
|
95
|
+
return new Set(['python', 'pyspark']);
|
|
96
|
+
case 'sparksql':
|
|
97
|
+
// SQL files: raw cells must be sparksql
|
|
98
|
+
return new Set(['sparksql']);
|
|
99
|
+
case 'scala':
|
|
100
|
+
// Scala files: raw cells must be scala
|
|
101
|
+
return new Set(['scala']);
|
|
102
|
+
case 'r':
|
|
103
|
+
// R files: raw cells must be r
|
|
104
|
+
return new Set(['r']);
|
|
105
|
+
default:
|
|
106
|
+
return new Set([defaultLanguage]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Validate that a raw cell's metadata language matches the file type.
|
|
111
|
+
* Throws NotebookStructureError if there's a mismatch.
|
|
112
|
+
*/
|
|
113
|
+
function validateRawCellLanguage(metadataLanguage, isRawCell, config, cellIndex, lineNumber) {
|
|
114
|
+
if (!isRawCell || !metadataLanguage) {
|
|
115
|
+
// MAGIC cells can have any language, and cells without metadata are fine
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const validRawLanguages = getValidRawLanguages(config.defaultLanguage);
|
|
119
|
+
const normalizedLanguage = metadataLanguage.toLowerCase();
|
|
120
|
+
if (!validRawLanguages.has(normalizedLanguage)) {
|
|
121
|
+
const fileType = config.defaultLanguage === 'python' ? '.py' :
|
|
122
|
+
config.defaultLanguage === 'sparksql' ? '.sql' :
|
|
123
|
+
config.defaultLanguage === 'scala' ? '.scala' :
|
|
124
|
+
config.defaultLanguage === 'r' ? '.r' :
|
|
125
|
+
`.${config.defaultLanguage}`;
|
|
126
|
+
throw new NotebookStructureError(`Invalid notebook structure: Cell ${cellIndex + 1} (line ${lineNumber + 1}) has metadata language "${metadataLanguage}" ` +
|
|
127
|
+
`but is not wrapped with MAGIC prefix. In ${fileType} files, only ${config.defaultLanguage} cells can be raw/uncommented. ` +
|
|
128
|
+
`Other languages (like ${metadataLanguage}) must use the "${config.magicPrefix}%%" prefix.`, cellIndex, lineNumber, metadataLanguage, config.defaultLanguage);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
75
131
|
/**
|
|
76
132
|
* Line ending constant - this library standardizes on LF.
|
|
77
133
|
*/
|
|
@@ -291,6 +347,9 @@ export function parseNotebook(content, fileExtension) {
|
|
|
291
347
|
const magicCommand = extractMagicCommand(originalLines, config);
|
|
292
348
|
// Check if it's a MAGIC cell
|
|
293
349
|
const isMagicCell = originalLines.some(l => l.trim().startsWith(config.magicPrefix.trim()));
|
|
350
|
+
// Validate that raw cells have a language matching the file type
|
|
351
|
+
const cellIndex = result.cells.length;
|
|
352
|
+
validateRawCellLanguage(metadataLanguage, !isMagicCell, config, cellIndex, j);
|
|
294
353
|
// Extract content
|
|
295
354
|
let content;
|
|
296
355
|
let contentStartLine = j;
|
package/package.json
CHANGED