mirror of
https://github.com/samuele-cozzi/obsidian-marp-slides.git
synced 2026-07-22 07:40:25 +00:00
feat: enhance image handling by converting Obsidian wiki-link images to standard Markdown format and update MarpExport to support this functionality
This commit is contained in:
parent
1a6b11be0f
commit
715093b773
7 changed files with 643 additions and 69 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -5,6 +5,7 @@
|
|||
*.iml
|
||||
.idea
|
||||
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
|
||||
|
|
@ -26,3 +27,7 @@ tests/coverage
|
|||
vault/.obsidian
|
||||
|
||||
lib
|
||||
|
||||
# claude
|
||||
.claude/*
|
||||
tmpclaude-*
|
||||
|
|
|
|||
525
PROJECT.md
Normal file
525
PROJECT.md
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
# Obsidian Marp Slides - Technical Documentation
|
||||
|
||||
> For user documentation and getting started guides, see [README.md](README.md) and the [online documentation](https://samuele-cozzi.github.io/obsidian-marp-slides/).
|
||||
|
||||
## Overview
|
||||
|
||||
**Obsidian Marp Slides** is a plugin that integrates [Marp](https://marp.app/) (Markdown Presentation Ecosystem) into [Obsidian](https://obsidian.md/), enabling users to create, preview, and export slide presentations directly from Markdown files.
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Plugin ID | `marp-slides` |
|
||||
| Version | 0.45.6 |
|
||||
| Author | Samuele Cozzi |
|
||||
| License | MIT |
|
||||
| Min Obsidian Version | 0.15.0 |
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Obsidian App │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌──────────────────┐ ┌───────────────┐ │
|
||||
│ │ MarpSlides │───▶│ MarpPreviewView │───▶│ Marp Core │ │
|
||||
│ │ (Plugin) │ │ (ItemView) │ │ (Renderer) │ │
|
||||
│ └──────┬──────┘ └──────────────────┘ └───────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌──────────────────┐ ┌───────────────┐ │
|
||||
│ └──────────▶│ MarpExport │───▶│ Marp CLI │ │
|
||||
│ │ (Exporter) │ │ (Export) │ │
|
||||
│ └────────┬─────────┘ └───────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────▼─────────┐ │
|
||||
│ │ FilePath │ │
|
||||
│ │ (Utilities) │ │
|
||||
│ └──────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Data Flow
|
||||
|
||||
**Preview Pipeline:**
|
||||
1. User opens Markdown file and triggers "Slide Preview" command
|
||||
2. `MarpSlides` retrieves active `MarkdownView` and creates `MarpPreviewView`
|
||||
3. `MarpPreviewView` uses Marp Core to render Markdown → HTML/CSS
|
||||
4. Rendered slides displayed in split pane with file base path for assets
|
||||
5. File change events trigger re-render automatically
|
||||
|
||||
**Export Pipeline:**
|
||||
1. User triggers export command (PDF/HTML/PPTX/PNG)
|
||||
2. `MarpSlides` creates `MarpExport` instance with current settings
|
||||
3. `FilePath` resolves file paths, themes, and resources
|
||||
4. `MarpExport` constructs CLI arguments and invokes Marp CLI
|
||||
5. Marp CLI uses Chrome/Chromium for PDF/PPTX rendering
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
obsidian-marp-slides/
|
||||
├── src/
|
||||
│ ├── main.ts # Plugin entry point, commands, settings
|
||||
│ ├── config/
|
||||
│ │ └── marp.config.js # Marp engine configuration for markdown-it plugins
|
||||
│ ├── utilities/
|
||||
│ │ ├── settings.ts # Settings interface and defaults
|
||||
│ │ ├── marpExport.ts # Export functionality (PDF, HTML, PPTX, PNG)
|
||||
│ │ ├── filePath.ts # File/path resolution utilities
|
||||
│ │ ├── libs.ts # External library management
|
||||
│ │ └── icons.ts # SVG icon definitions
|
||||
│ └── views/
|
||||
│ └── marpPreviewView.ts # Slide preview rendering
|
||||
├── tests/
|
||||
│ ├── filePath.test.ts # Path utility tests
|
||||
│ └── __mocks__/
|
||||
│ └── obsidian.ts # Obsidian API mocks
|
||||
├── docs/ # User documentation
|
||||
├── vault/samples/ # Sample presentations
|
||||
├── .github/workflows/
|
||||
│ └── release-please.yml # CI/CD pipeline
|
||||
├── esbuild.config.mjs # Build configuration
|
||||
├── tsconfig.json # TypeScript configuration
|
||||
├── jest.config.js # Test configuration
|
||||
├── package.json # Dependencies and scripts
|
||||
├── manifest.json # Obsidian plugin metadata
|
||||
├── styles.css # Plugin styling
|
||||
└── version-bump.mjs # Version management script
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Components
|
||||
|
||||
### MarpSlides (`src/main.ts:10-147`)
|
||||
|
||||
Main plugin class extending Obsidian's `Plugin`.
|
||||
|
||||
**Responsibilities:**
|
||||
- Plugin lifecycle management (`onload`, `onunload`)
|
||||
- Command registration (preview, export)
|
||||
- Settings management
|
||||
- Event listeners (file changes, cursor position)
|
||||
|
||||
**Key Methods:**
|
||||
| Method | Line | Description |
|
||||
|--------|------|-------------|
|
||||
| `onload()` | 16 | Initializes plugin, registers views/commands |
|
||||
| `loadSettings()` | 90 | Loads persisted settings |
|
||||
| `saveSettings()` | 94 | Persists settings to disk |
|
||||
| `showPreviewSlide()` | 112 | Opens preview pane |
|
||||
| `exportFile()` | 104 | Triggers export operation |
|
||||
| `onChange()` | 98 | Handles file modification events |
|
||||
|
||||
**Registered Commands:**
|
||||
- `marp-slides:preview` - Slide Preview
|
||||
- `marp-slides:export-pdf` - Export PDF
|
||||
- `marp-slides:export-pdf-notes` - Export PDF with Notes
|
||||
- `marp-slides:export-html` - Export HTML
|
||||
- `marp-slides:export-pptx` - Export PPTX
|
||||
- `marp-slides:export-png` - Export PNG
|
||||
|
||||
---
|
||||
|
||||
### MarpPreviewView (`src/views/marpPreviewView.ts:16-166`)
|
||||
|
||||
Custom view for rendering slides, extending Obsidian's `ItemView`.
|
||||
|
||||
**Responsibilities:**
|
||||
- Marp Core initialization and configuration
|
||||
- Theme loading from vault
|
||||
- Slide rendering (Markdown → HTML)
|
||||
- Cursor-to-slide synchronization
|
||||
- Export action buttons
|
||||
|
||||
**Key Methods:**
|
||||
| Method | Line | Description |
|
||||
|--------|------|-------------|
|
||||
| `onOpen()` | 58 | Initializes container, loads themes |
|
||||
| `displaySlides()` | 131 | Renders Markdown to HTML slides |
|
||||
| `onLineChanged()` | 89 | Scrolls to slide based on cursor |
|
||||
| `addActions()` | 97 | Adds export buttons to view header |
|
||||
|
||||
**Marp Configuration** (lines 29-40):
|
||||
```typescript
|
||||
new Marp({
|
||||
container: { tag: 'div', id: '__marp-vscode' },
|
||||
slideContainer: { tag: 'div', 'data-marp-vscode-slide-wrapper': '' },
|
||||
html: this.settings.EnableHTML,
|
||||
inlineSVG: { enabled: true, backdropSelector: false },
|
||||
math: this.settings.MathTypesettings,
|
||||
minifyCSS: true,
|
||||
script: false
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MarpExport (`src/utilities/marpExport.ts:8-158`)
|
||||
|
||||
Handles exporting presentations to various formats.
|
||||
|
||||
**Responsibilities:**
|
||||
- Building Marp CLI argument arrays
|
||||
- Managing export types and options
|
||||
- Browser path resolution
|
||||
- Error handling for missing Chrome
|
||||
|
||||
**Key Methods:**
|
||||
| Method | Line | Description |
|
||||
|--------|------|-------------|
|
||||
| `export()` | 16 | Main export orchestrator |
|
||||
| `run()` | 101 | Sets up environment and executes CLI |
|
||||
| `runMarpCli()` | 136 | Executes Marp CLI with arguments |
|
||||
|
||||
**Supported Export Types:**
|
||||
| Type | CLI Flags | Output |
|
||||
|------|-----------|--------|
|
||||
| `pdf` | `--pdf` | PDF file |
|
||||
| `pdf-with-notes` | `--pdf --pdf-notes --pdf-outlines` | PDF with speaker notes |
|
||||
| `pptx` | `--pptx` | PowerPoint file |
|
||||
| `png` | `--images --png` | PNG images |
|
||||
| `html` | `--html --template [mode]` | HTML file |
|
||||
| `preview` | `--html --preview` | Live preview server |
|
||||
|
||||
---
|
||||
|
||||
### FilePath (`src/utilities/filePath.ts:4-112`)
|
||||
|
||||
Utility class for file and path resolution.
|
||||
|
||||
**Responsibilities:**
|
||||
- Vault base path resolution
|
||||
- Absolute vs relative link format handling
|
||||
- Theme directory resolution
|
||||
- Plugin directory management
|
||||
|
||||
**Key Methods:**
|
||||
| Method | Line | Description |
|
||||
|--------|------|-------------|
|
||||
| `getCompleteFileBasePath()` | 41 | Gets resource base path for assets |
|
||||
| `getCompleteFilePath()` | 56 | Gets full file path for export |
|
||||
| `getThemePath()` | 80 | Resolves custom theme directory |
|
||||
| `getLibDirectory()` | 99 | Gets markdown-it plugins directory |
|
||||
| `getMarpEngine()` | 106 | Gets Marp engine config path |
|
||||
|
||||
---
|
||||
|
||||
### MarpSlidesSettings (`src/utilities/settings.ts:1-21`)
|
||||
|
||||
Settings interface and defaults.
|
||||
|
||||
```typescript
|
||||
interface MarpSlidesSettings {
|
||||
CHROME_PATH: string; // Custom browser path for export
|
||||
ThemePath: string; // Custom theme CSS directory
|
||||
EnableHTML: boolean; // Allow HTML in Markdown
|
||||
MathTypesettings: string; // 'mathjax' or 'katex'
|
||||
HTMLExportMode: string; // 'bare' or 'bespoke'
|
||||
EXPORT_PATH: string; // Custom export output directory
|
||||
EnableSyncPreview: boolean; // Sync preview with cursor
|
||||
EnableMarkdownItPlugins: boolean; // Enable markdown-it extensions
|
||||
}
|
||||
```
|
||||
|
||||
**Default Values:**
|
||||
| Setting | Default |
|
||||
|---------|---------|
|
||||
| CHROME_PATH | `''` (auto-detect) |
|
||||
| ThemePath | `''` (none) |
|
||||
| EnableHTML | `false` |
|
||||
| MathTypesettings | `'mathjax'` |
|
||||
| HTMLExportMode | `'bare'` |
|
||||
| EXPORT_PATH | `''` (same as source) |
|
||||
| EnableSyncPreview | `true` |
|
||||
| EnableMarkdownItPlugins | `false` |
|
||||
|
||||
---
|
||||
|
||||
### Libs (`src/utilities/libs.ts:8-61`)
|
||||
|
||||
Manages external markdown-it plugin libraries.
|
||||
|
||||
**Responsibilities:**
|
||||
- Check if libraries exist locally
|
||||
- Download compiled plugins from GitHub releases
|
||||
- Extract ZIP archive and cache plugins
|
||||
|
||||
**Library Source:** `https://github.com/samuele-cozzi/obsidian-marp-slides/releases/download/lib-v3/lib.zip`
|
||||
|
||||
**Included Plugins:**
|
||||
- `markdown-it-container` - Custom containers
|
||||
- `markdown-it-mark` - Text highlighting
|
||||
- `markdown-it-kroki` - Diagram rendering via Kroki.io
|
||||
|
||||
---
|
||||
|
||||
### LineSelectionListener (`src/main.ts:255-300`)
|
||||
|
||||
Experimental feature for cursor-to-slide synchronization.
|
||||
|
||||
**Implementation:** Extends `EditorSuggest` (non-intrusive approach to track cursor)
|
||||
|
||||
**How it works:**
|
||||
1. Listens to cursor position changes
|
||||
2. Counts slide separators (`---`) before cursor
|
||||
3. Parses YAML frontmatter to adjust slide count
|
||||
4. Scrolls preview to corresponding slide
|
||||
|
||||
---
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Runtime Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `@marp-team/marp-core` | ^3.9.0 | Core slide rendering engine |
|
||||
| `@marp-team/marp-cli` | ^2.5.0 | Export engine (PDF, PPTX, HTML, PNG) |
|
||||
| `@marp-team/marpit` | ^2.6.1 | Markdown presentation framework |
|
||||
| `gray-matter` | ^4.0.3 | YAML frontmatter parsing |
|
||||
| `fs-extra` | ^11.2.0 | Extended file system operations |
|
||||
| `jszip` | ^3.10.1 | ZIP handling for library distribution |
|
||||
| `request` | ^2.88.2 | HTTP requests for library download |
|
||||
|
||||
### Development Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `typescript` | ^4.9.5 | Type-safe development |
|
||||
| `esbuild` | 0.17.3 | Fast bundler |
|
||||
| `jest` | ^29.7.0 | Testing framework |
|
||||
| `ts-jest` | ^29.1.2 | TypeScript support for Jest |
|
||||
| `obsidian` | ^1.5.7-1 | Obsidian API types |
|
||||
| `@typescript-eslint/*` | 5.29.0 | Linting |
|
||||
|
||||
### External Requirements
|
||||
|
||||
- **Chrome/Chromium/Edge** - Required for PDF, PPTX, and PNG export
|
||||
- **Node.js** - Development and build environment
|
||||
|
||||
---
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js (v16+)
|
||||
- npm
|
||||
- Obsidian (for testing)
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/samuele-cozzi/obsidian-marp-slides.git
|
||||
cd obsidian-marp-slides
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
```
|
||||
|
||||
### Build Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Watch mode with inline sourcemaps |
|
||||
| `npm run build` | TypeScript check + production build |
|
||||
| `npm run test` | Run tests with coverage |
|
||||
| `npm run test:watch` | Run tests in watch mode |
|
||||
| `npm run version` | Bump version in manifest |
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. **Start watch mode:**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
2. **Link to Obsidian vault:**
|
||||
- Copy or symlink the project directory to your vault's `.obsidian/plugins/marp-slides/`
|
||||
- Or set up the vault's plugin directory to point to your development folder
|
||||
|
||||
3. **Enable plugin:**
|
||||
- Open Obsidian Settings → Community Plugins
|
||||
- Enable "Marp Slides"
|
||||
- Use "Reload app without saving" (Ctrl/Cmd+R) after changes
|
||||
|
||||
4. **Debug:**
|
||||
- Open Developer Tools (Ctrl/Cmd+Shift+I)
|
||||
- Check Console for logs and errors
|
||||
|
||||
### Build Configuration (`esbuild.config.mjs`)
|
||||
|
||||
- **Entry:** `main.ts`
|
||||
- **Output:** `main.js`
|
||||
- **Format:** CommonJS
|
||||
- **Target:** ES2018
|
||||
- **External:** `obsidian`, `electron`, `@codemirror/*`
|
||||
- **Production:** Minified, no sourcemap
|
||||
- **Development:** Inline sourcemap
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Framework
|
||||
|
||||
- **Jest** with **ts-jest** preset
|
||||
- Coverage reporting via **lcov**
|
||||
- Mocks for Obsidian API
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests with coverage
|
||||
npm run test
|
||||
|
||||
# Watch mode
|
||||
npm run test:watch
|
||||
```
|
||||
|
||||
### Test Structure
|
||||
|
||||
```
|
||||
tests/
|
||||
├── filePath.test.ts # Path resolution tests
|
||||
├── coverage/ # Coverage reports (generated)
|
||||
└── __mocks__/
|
||||
└── obsidian.ts # Obsidian API mocks
|
||||
```
|
||||
|
||||
### Coverage
|
||||
|
||||
Coverage reports are generated in `tests/coverage/` and uploaded to CodeClimate during CI.
|
||||
|
||||
---
|
||||
|
||||
## CI/CD Pipeline
|
||||
|
||||
### GitHub Actions Workflow (`.github/workflows/release-please.yml`)
|
||||
|
||||
**Trigger:** Push to `main` branch
|
||||
|
||||
### Jobs
|
||||
|
||||
#### 1. release-please
|
||||
- Uses `google-github-actions/release-please-action@v3`
|
||||
- Analyzes commits for version bump
|
||||
- Creates release PR if warranted
|
||||
- Generates changelog in `docs/CHANGELOG.md`
|
||||
|
||||
#### 2. release-plugin (if release created)
|
||||
1. Updates `manifest.json` version
|
||||
2. Commits version update
|
||||
3. Builds plugin (`npm install && npm run build`)
|
||||
4. Runs tests with CodeClimate coverage upload
|
||||
5. Packages artifacts:
|
||||
- `main.js`
|
||||
- `manifest.json`
|
||||
- `styles.css`
|
||||
- `obsidian-marp-slides-{version}.zip`
|
||||
6. Uploads to GitHub release
|
||||
|
||||
### Release Artifacts
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `main.js` | Compiled plugin code |
|
||||
| `manifest.json` | Plugin metadata |
|
||||
| `styles.css` | Plugin styling |
|
||||
| `obsidian-marp-slides-{version}.zip` | Complete plugin package |
|
||||
|
||||
---
|
||||
|
||||
## Configuration Options Reference
|
||||
|
||||
### CHROME_PATH
|
||||
**Type:** `string` | **Default:** `''`
|
||||
|
||||
Custom path to Chrome, Chromium, or Edge browser for PDF/PPTX/PNG export. If empty, Marp CLI auto-detects installed browsers.
|
||||
|
||||
### ThemePath
|
||||
**Type:** `string` | **Default:** `''`
|
||||
|
||||
Vault-relative path to directory containing custom Marp theme CSS files. Themes are loaded on preview open.
|
||||
|
||||
### EXPORT_PATH
|
||||
**Type:** `string` | **Default:** `''`
|
||||
|
||||
Custom output directory for exports. If empty, exports to same directory as source file. Does not affect HTML export.
|
||||
|
||||
### EnableHTML
|
||||
**Type:** `boolean` | **Default:** `false`
|
||||
|
||||
Allow HTML elements in Marp Markdown. Use with caution.
|
||||
|
||||
### MathTypesettings
|
||||
**Type:** `'mathjax' | 'katex'` | **Default:** `'mathjax'`
|
||||
|
||||
Math rendering library. Can be overridden per-slide via frontmatter.
|
||||
|
||||
### HTMLExportMode
|
||||
**Type:** `'bare' | 'bespoke'` | **Default:** `'bare'`
|
||||
|
||||
HTML export template. `bespoke` is experimental and provides interactive features.
|
||||
|
||||
### EnableSyncPreview
|
||||
**Type:** `boolean` | **Default:** `true`
|
||||
|
||||
(Experimental) Synchronize slide preview with editor cursor position.
|
||||
|
||||
### EnableMarkdownItPlugins
|
||||
**Type:** `boolean` | **Default:** `false`
|
||||
|
||||
(Experimental) Enable markdown-it plugins for containers, marks, and Kroki diagrams.
|
||||
|
||||
---
|
||||
|
||||
## Obsidian API Integration
|
||||
|
||||
### Used APIs
|
||||
|
||||
| API | Usage |
|
||||
|-----|-------|
|
||||
| `Plugin` | Base class for plugin |
|
||||
| `ItemView` | Custom preview view |
|
||||
| `MarkdownView` | Access editor content |
|
||||
| `PluginSettingTab` | Settings UI |
|
||||
| `EditorSuggest` | Cursor position tracking |
|
||||
| `Vault` | File operations |
|
||||
| `FileSystemAdapter` | Path resolution |
|
||||
| `WorkspaceLeaf` | View management |
|
||||
|
||||
### Registered Entities
|
||||
|
||||
| Type | ID/Name |
|
||||
|------|---------|
|
||||
| View | `marp-preview-view` |
|
||||
| Icons | `slides-preview-marp`, `slides-marp-export-pdf`, `slides-marp-export-pptx`, `slides-marp-slide-present` |
|
||||
| Commands | 6 commands (see MarpSlides section) |
|
||||
| Ribbon | Preview button |
|
||||
|
||||
---
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- **Wiki Links** not supported in slides
|
||||
- **Mobile App** plugin is in alpha state
|
||||
- **Export** (except HTML) requires Chrome/Chromium/Edge installed
|
||||
- **Sync Preview** is experimental and may have edge cases
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make changes with tests
|
||||
4. Submit a pull request
|
||||
|
||||
For bug reports and feature requests, use [GitHub Issues](https://github.com/samuele-cozzi/obsidian-marp-slides/issues).
|
||||
76
package-lock.json
generated
76
package-lock.json
generated
|
|
@ -42,7 +42,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
|
||||
"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -150,6 +149,7 @@
|
|||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz",
|
||||
"integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
|
|
@ -1046,7 +1046,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
"integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
|
|
@ -1062,7 +1061,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
|
||||
"integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
}
|
||||
|
|
@ -1072,7 +1070,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
|
||||
"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
|
|
@ -1096,7 +1093,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
|
||||
"integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
|
|
@ -1106,7 +1102,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@humanwhocodes/object-schema": "^2.0.2",
|
||||
"debug": "^4.3.1",
|
||||
|
|
@ -1121,7 +1116,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.22"
|
||||
},
|
||||
|
|
@ -1134,8 +1128,7 @@
|
|||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
|
||||
"integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@istanbuljs/load-nyc-config": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -1987,6 +1980,7 @@
|
|||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz",
|
||||
"integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.29.0",
|
||||
"@typescript-eslint/types": "5.29.0",
|
||||
|
|
@ -2137,8 +2131,7 @@
|
|||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
|
|
@ -2170,7 +2163,6 @@
|
|||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
|
|
@ -2534,6 +2526,7 @@
|
|||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001587",
|
||||
"electron-to-chromium": "^1.4.668",
|
||||
|
|
@ -2973,8 +2966,7 @@
|
|||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
|
|
@ -3013,7 +3005,8 @@
|
|||
"node_modules/devtools-protocol": {
|
||||
"version": "0.0.1107588",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1107588.tgz",
|
||||
"integrity": "sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg=="
|
||||
"integrity": "sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/diff-sequences": {
|
||||
"version": "29.6.3",
|
||||
|
|
@ -3040,7 +3033,6 @@
|
|||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esutils": "^2.0.2"
|
||||
},
|
||||
|
|
@ -3112,6 +3104,7 @@
|
|||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz",
|
||||
"integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==",
|
||||
"hasInstallScript": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
|
|
@ -3188,7 +3181,6 @@
|
|||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
|
@ -3309,7 +3301,6 @@
|
|||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
|
||||
"integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^5.2.0"
|
||||
|
|
@ -3326,7 +3317,6 @@
|
|||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
|
|
@ -3336,7 +3326,6 @@
|
|||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.3"
|
||||
},
|
||||
|
|
@ -3357,7 +3346,6 @@
|
|||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
||||
"integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.9.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
|
|
@ -3387,7 +3375,6 @@
|
|||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
|
||||
"integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"estraverse": "^5.1.0"
|
||||
},
|
||||
|
|
@ -3400,7 +3387,6 @@
|
|||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
|
|
@ -3440,7 +3426,6 @@
|
|||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -3579,8 +3564,7 @@
|
|||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.17.1",
|
||||
|
|
@ -3612,7 +3596,6 @@
|
|||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"flat-cache": "^3.0.4"
|
||||
},
|
||||
|
|
@ -3636,7 +3619,6 @@
|
|||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"locate-path": "^6.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
|
|
@ -3653,7 +3635,6 @@
|
|||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
|
||||
"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"flatted": "^3.2.9",
|
||||
"keyv": "^4.5.3",
|
||||
|
|
@ -3667,8 +3648,7 @@
|
|||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
|
||||
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/forever-agent": {
|
||||
"version": "0.6.1",
|
||||
|
|
@ -3826,7 +3806,6 @@
|
|||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
|
||||
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^0.20.2"
|
||||
},
|
||||
|
|
@ -3865,8 +3844,7 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/gray-matter": {
|
||||
"version": "4.0.3",
|
||||
|
|
@ -4222,7 +4200,6 @@
|
|||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -4342,6 +4319,7 @@
|
|||
"resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
|
||||
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^29.7.0",
|
||||
"@jest/types": "^29.6.3",
|
||||
|
|
@ -4929,8 +4907,7 @@
|
|||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
|
|
@ -4951,8 +4928,7 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
|
|
@ -5027,7 +5003,6 @@
|
|||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
|
|
@ -5063,7 +5038,6 @@
|
|||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"prelude-ls": "^1.2.1",
|
||||
"type-check": "~0.4.0"
|
||||
|
|
@ -5098,7 +5072,6 @@
|
|||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"p-locate": "^5.0.0"
|
||||
},
|
||||
|
|
@ -5124,8 +5097,7 @@
|
|||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
|
|
@ -5446,7 +5418,6 @@
|
|||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
|
||||
"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@aashutoshrathi/word-wrap": "^1.2.3",
|
||||
"deep-is": "^0.1.3",
|
||||
|
|
@ -5479,7 +5450,6 @@
|
|||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
|
||||
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"p-limit": "^3.0.2"
|
||||
},
|
||||
|
|
@ -5724,7 +5694,6 @@
|
|||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
|
|
@ -6072,7 +6041,6 @@
|
|||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
|
|
@ -6459,8 +6427,7 @@
|
|||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
|
|
@ -6542,8 +6509,7 @@
|
|||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/through": {
|
||||
"version": "2.3.8",
|
||||
|
|
@ -6700,7 +6666,6 @@
|
|||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"prelude-ls": "^1.2.1"
|
||||
},
|
||||
|
|
@ -6722,7 +6687,6 @@
|
|||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
|
@ -6735,6 +6699,7 @@
|
|||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"devOptional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
|
@ -6858,8 +6823,7 @@
|
|||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/walker": {
|
||||
"version": "1.0.8",
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ export default class MarpSlides extends Plugin {
|
|||
|
||||
async exportFile(type: string){
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
if(file !== null){
|
||||
const marpCli = new MarpExport(this.settings);
|
||||
if(file !== null){
|
||||
const marpCli = new MarpExport(this.settings, this.app);
|
||||
await marpCli.export(file,type);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Vault, normalizePath, FileSystemAdapter, TFile } from 'obsidian';
|
||||
import { Vault, normalizePath, FileSystemAdapter, TFile, App } from 'obsidian';
|
||||
import { MarpSlidesSettings } from './settings';
|
||||
|
||||
export class FilePath {
|
||||
|
|
@ -109,4 +109,66 @@ export class FilePath {
|
|||
//console.log(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Obsidian wiki-link image syntax to standard Markdown.
|
||||
* Transforms ![[image.png]] to 
|
||||
*/
|
||||
public convertImageWikiLinks(markdown: string, sourceFile: TFile, app: App): string {
|
||||
// Image extensions to convert
|
||||
const imageExtensions = /\.(png|jpg|jpeg|gif|svg|webp|bmp)$/i;
|
||||
|
||||
// Regex: ![[filename]] or ![[filename|alt text]]
|
||||
const wikiLinkRegex = /!\[\[([^\]|]+?)(?:\|([^\]]*))?\]\]/g;
|
||||
|
||||
return markdown.replace(wikiLinkRegex, (match, filename, altText) => {
|
||||
// Only process image files
|
||||
if (!imageExtensions.test(filename)) {
|
||||
return match;
|
||||
}
|
||||
|
||||
// Use Obsidian's link resolver to find the file
|
||||
const linkedFile = app.metadataCache.getFirstLinkpathDest(filename, sourceFile.path);
|
||||
|
||||
if (linkedFile) {
|
||||
// Build path based on link format setting
|
||||
let imagePath: string;
|
||||
if (this.isAbsoluteLinkFormat(sourceFile)) {
|
||||
// Absolute: path from vault root
|
||||
imagePath = linkedFile.path;
|
||||
} else {
|
||||
// Relative: path from source file's folder
|
||||
imagePath = this.getRelativePathFromFile(sourceFile, linkedFile);
|
||||
}
|
||||
|
||||
const alt = altText || filename;
|
||||
return ``;
|
||||
}
|
||||
|
||||
// File not found - return original
|
||||
return match;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate relative path from source file to target file.
|
||||
*/
|
||||
private getRelativePathFromFile(sourceFile: TFile, targetFile: TFile): string {
|
||||
const sourceParts = sourceFile.parent?.path.split('/').filter(p => p) || [];
|
||||
const targetParts = targetFile.path.split('/').filter(p => p);
|
||||
|
||||
// Find common prefix length
|
||||
let commonLength = 0;
|
||||
while (commonLength < sourceParts.length &&
|
||||
commonLength < targetParts.length - 1 &&
|
||||
sourceParts[commonLength] === targetParts[commonLength]) {
|
||||
commonLength++;
|
||||
}
|
||||
|
||||
// Build relative path
|
||||
const upCount = sourceParts.length - commonLength;
|
||||
const relativeParts = [...Array(upCount).fill('..'), ...targetParts.slice(commonLength)];
|
||||
|
||||
return relativeParts.join('/');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,19 @@
|
|||
import marpCli, { CLIError, CLIErrorCode } from '@marp-team/marp-cli'
|
||||
import { TFile } from 'obsidian';
|
||||
import { TFile, App } from 'obsidian';
|
||||
import { MarpSlidesSettings } from './settings';
|
||||
import { FilePath } from './filePath';
|
||||
import { writeFileSync, readFileSync } from 'fs-extra';
|
||||
|
||||
export class MarpCLIError extends Error {}
|
||||
|
||||
export class MarpExport {
|
||||
|
||||
private settings : MarpSlidesSettings;
|
||||
private app : App | null;
|
||||
|
||||
constructor(settings: MarpSlidesSettings) {
|
||||
constructor(settings: MarpSlidesSettings, app: App | null = null) {
|
||||
this.settings = settings;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
async export(file: TFile, type: string){
|
||||
|
|
@ -22,9 +25,20 @@ export class MarpExport {
|
|||
const resourcesPath = filesTool.getLibDirectory(file.vault);
|
||||
const marpEngineConfig = filesTool.getMarpEngine(file.vault);
|
||||
|
||||
if (completeFilePath != ''){
|
||||
// Convert wiki-link images to standard markdown before export
|
||||
if (this.app && completeFilePath != '') {
|
||||
try {
|
||||
const originalContent = readFileSync(completeFilePath, 'utf-8');
|
||||
const processedContent = filesTool.convertImageWikiLinks(originalContent, file, this.app);
|
||||
writeFileSync(completeFilePath, processedContent, 'utf-8');
|
||||
} catch (e) {
|
||||
console.error('Failed to process wiki-links for export:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if (completeFilePath != ''){
|
||||
//console.log(completeFilePath);
|
||||
|
||||
|
||||
const argv: string[] = [completeFilePath,'--allow-local-files'];
|
||||
//const argv: string[] = ['--engine', '@marp-team/marp-core', completeFilePath,'--allow-local-files'];
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export class MarpPreviewView extends ItemView {
|
|||
}
|
||||
|
||||
async addActions() {
|
||||
const marpCli = new MarpExport(this.settings);
|
||||
const marpCli = new MarpExport(this.settings, this.app);
|
||||
|
||||
this.addAction('image', 'Export as PNG', () => {
|
||||
if (this.file) {
|
||||
|
|
@ -129,17 +129,21 @@ export class MarpPreviewView extends ItemView {
|
|||
}
|
||||
|
||||
async displaySlides(view : MarkdownView) {
|
||||
|
||||
|
||||
if (view.file != null) {
|
||||
this.file = view.file;
|
||||
const basePath = (new FilePath(this.settings)).getCompleteFileBasePath(view.file);
|
||||
const filePath = new FilePath(this.settings);
|
||||
const basePath = filePath.getCompleteFileBasePath(view.file);
|
||||
const markdownText = view.data;
|
||||
|
||||
|
||||
// Convert wiki-link images to standard markdown
|
||||
const processedMarkdown = filePath.convertImageWikiLinks(markdownText, view.file, this.app);
|
||||
|
||||
const container = this.containerEl.children[1];
|
||||
container.empty();
|
||||
|
||||
|
||||
let { html, css } = this.marp.render(markdownText);
|
||||
|
||||
let { html, css } = this.marp.render(processedMarkdown);
|
||||
|
||||
// Replace Backgorund Url for images
|
||||
html = html.replace(/(?!background-image:url\("http)background-image:url\("/g, `background-image:url("${basePath}`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue