feat: add obsidian-clipper-template-creator for creating Obsidian Web Clipper templates
This commit is contained in:
54
skills/obsidian-clipper-template-creator/SKILL.md
Normal file
54
skills/obsidian-clipper-template-creator/SKILL.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: obsidian-clipper-template-creator
|
||||
description: Guide for creating templates for the Obsidian Web Clipper. Use when you want to create a new clipping template, understand available variables, or format clipped content.
|
||||
---
|
||||
|
||||
# Obsidian Web Clipper Template Creator
|
||||
|
||||
This skill helps you create importable JSON templates for the Obsidian Web Clipper.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Identify User Intent:** specific site (YouTube), specific type (Recipe), or general clipping?
|
||||
2. **Check Existing Bases:** The user likely has a "Base" schema defined in `Templates/Bases/`.
|
||||
* **Action:** Read `Templates/Bases/*.base` to find a matching category (e.g., `Recipes.base`).
|
||||
* **Action:** Use the properties defined in the Base to structure the Clipper template properties.
|
||||
* See [references/bases-workflow.md](references/bases-workflow.md) for details.
|
||||
3. **Fetch & Analyze Reference URL:** Validate variables against a real page.
|
||||
* **Action:** Ask the user for a sample URL of the content they want to clip (if not provided).
|
||||
* **Action:** Use `WebFetch` to retrieve the page HTML.
|
||||
* **Action:** Analyze the HTML for Schema.org JSON, Meta tags, and CSS selectors.
|
||||
* See [references/analysis-workflow.md](references/analysis-workflow.md) for analysis techniques.
|
||||
4. **Draft the JSON:** Create a valid JSON object following the schema.
|
||||
* See [references/json-schema.md](references/json-schema.md).
|
||||
5. **Verify Variables:** Ensure the chosen variables (Preset, Schema, Selector) exist in your analysis.
|
||||
* See [references/variables.md](references/variables.md).
|
||||
|
||||
## Output Format
|
||||
|
||||
**ALWAYS** output the final result as a JSON code block that the user can copy and import.
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "0.1.0",
|
||||
"name": "My Template",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
* [references/variables.md](references/variables.md) - Available data variables.
|
||||
* [references/filters.md](references/filters.md) - Formatting filters.
|
||||
* [references/json-schema.md](references/json-schema.md) - JSON structure documentation.
|
||||
* [references/bases-workflow.md](references/bases-workflow.md) - How to map Bases to Templates.
|
||||
* [references/analysis-workflow.md](references/analysis-workflow.md) - How to validate page data.
|
||||
|
||||
### Official Documentation
|
||||
* [Variables](https://help.obsidian.md/web-clipper/variables)
|
||||
* [Filters](https://help.obsidian.md/web-clipper/filters)
|
||||
* [Templates](https://help.obsidian.md/web-clipper/templates)
|
||||
|
||||
## Examples
|
||||
|
||||
See [assets/](assets/) for JSON examples.
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"schemaVersion": "0.1.0",
|
||||
"name": "General Clipping",
|
||||
"behavior": "create",
|
||||
"noteContentFormat": "{{content}}",
|
||||
"properties": [
|
||||
{
|
||||
"name": "categories",
|
||||
"value": "[[Clippings]]",
|
||||
"type": "multitext"
|
||||
},
|
||||
{
|
||||
"name": "author",
|
||||
"value": "[[{{author}}]]",
|
||||
"type": "multitext"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"value": "{{url}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "via",
|
||||
"value": "",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "published",
|
||||
"value": "{{published}}",
|
||||
"type": "datetime"
|
||||
},
|
||||
{
|
||||
"name": "created",
|
||||
"value": "{{date}}",
|
||||
"type": "datetime"
|
||||
},
|
||||
{
|
||||
"name": "topics",
|
||||
"value": "",
|
||||
"type": "multitext"
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"value": "{{description}}",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"triggers": [],
|
||||
"noteNameFormat": "{{title}}",
|
||||
"path": "Clippings/"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"schemaVersion": "0.1.0",
|
||||
"name": "Recipe",
|
||||
"behavior": "create",
|
||||
"noteContentFormat": "![{{schema:Recipe:image|first}}]\n\n## Description\n{{schema:Recipe:description}}\n\n## Ingredients\n{{schema:Recipe:recipeIngredient|list}}\n\n## Instructions\n{{schema:Recipe:recipeInstructions|map:step =>> step.text|list}}\n\n## Nutrition\n- Calories: {{schema:Recipe:nutrition.calories}}",
|
||||
"properties": [
|
||||
{
|
||||
"name": "categories",
|
||||
"value": "[[Recipes]]",
|
||||
"type": "multitext"
|
||||
},
|
||||
{
|
||||
"name": "author",
|
||||
"value": "[[{{schema:Recipe:author.name}}]]",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"value": "{{url}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "ingredients",
|
||||
"value": "{{schema:Recipe:recipeIngredient}}",
|
||||
"type": "multitext"
|
||||
},
|
||||
{
|
||||
"name": "cuisine",
|
||||
"value": "{{schema:Recipe:recipeCuisine}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "rating",
|
||||
"value": "",
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "Recipe",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"triggers": [
|
||||
"schema:Recipe"
|
||||
],
|
||||
"noteNameFormat": "{{schema:Recipe:name}}",
|
||||
"path": "Recipes/"
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
# Analysis Workflow: Validating Variables
|
||||
|
||||
To ensure your template works correctly, you must validate that the target page actually contains the data you want to extract.
|
||||
|
||||
## 1. Fetch the Page
|
||||
Use the `WebFetch` tool to retrieve the content of a representative URL provided by the user.
|
||||
|
||||
```
|
||||
WebFetch(url="https://example.com/recipe/chocolate-cake")
|
||||
```
|
||||
|
||||
## 2. Analyze the Output
|
||||
|
||||
### Check for Schema.org (Recommended)
|
||||
Look for `<script type="application/ld+json">`. This contains structured data which is the most reliable way to extract info.
|
||||
|
||||
**Example Found in HTML:**
|
||||
```html
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org/",
|
||||
"@type": "Recipe",
|
||||
"name": "Chocolate Cake",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "John Doe"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Conclusion:**
|
||||
* `{{schema:Recipe:name}}` is valid.
|
||||
* `{{schema:Recipe:author.name}}` is valid.
|
||||
* **Tip:** You can use `schema:Recipe` in the `triggers` array to automatically select this template for any page with this schema.
|
||||
|
||||
### Check for Meta Tags
|
||||
Look for `<meta>` tags in the `<head>` section.
|
||||
|
||||
**Example Found in HTML:**
|
||||
```html
|
||||
<meta property="og:title" content="The Best Chocolate Cake" />
|
||||
<meta name="description" content="A rich, moist chocolate cake recipe." />
|
||||
```
|
||||
|
||||
**Conclusion:**
|
||||
* `{{meta:og:title}}` is valid.
|
||||
* `{{meta:description}}` is valid.
|
||||
|
||||
### Check for CSS Selectors (Fallback)
|
||||
If Schema and Meta tags are missing, look for HTML structure (classes and IDs) to use with `{{selector:...}}`.
|
||||
|
||||
**Example Found in HTML:**
|
||||
```html
|
||||
<div class="article-body">
|
||||
<h1 id="main-title">Chocolate Cake</h1>
|
||||
<span class="author-name">By John Doe</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Conclusion:**
|
||||
* `{{selector:h1#main-title}}` or `{{selector:h1}}` can extract the title.
|
||||
* `{{selector:.author-name}}` can extract the author.
|
||||
|
||||
## 3. Verify Against Base
|
||||
Compare the available data from your analysis with the properties required by the user's Base (see `references/bases-workflow.md`).
|
||||
|
||||
* If the Base requires `ingredients` but the page has no Schema or clear list structure, warn the user that this field might need manual entry or a prompt variable.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Working with Obsidian Bases
|
||||
|
||||
The user maintains "Bases" in `Templates/Bases/*.base` which define the schema and properties for different types of notes (e.g., Recipes, Clippings, People).
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Identify the Category:** Determine the type of content the user wants to clip (e.g., a Recipe, a News Article, a YouTube video).
|
||||
2. **Find the Base:** Search `Templates/Bases/` for a matching `.base` file.
|
||||
* Example: For a recipe, look for `Templates/Bases/Recipes.base`.
|
||||
* Example: For a generic article, look for `Templates/Bases/Clippings.base`.
|
||||
3. **Read the Base:** Read the content of the `.base` file to understand the required properties.
|
||||
|
||||
## Interpreting .base Files
|
||||
|
||||
Base files use a YAML-like structure. Look for the `properties` section.
|
||||
|
||||
```yaml
|
||||
properties:
|
||||
file.name:
|
||||
displayName: name
|
||||
note.author:
|
||||
displayName: author
|
||||
note.type:
|
||||
displayName: type
|
||||
note.ingredients:
|
||||
displayName: ingredients
|
||||
```
|
||||
|
||||
* `note.X` corresponds to a property name `X` in the frontmatter.
|
||||
* `displayName` helps understand the intent, but the property key (e.g., `author`, `type`, `ingredients`) is what matters for the template.
|
||||
|
||||
## Mapping to Clipper Properties
|
||||
|
||||
When creating the JSON for the Web Clipper, map the Base properties to the `properties` array in the JSON.
|
||||
|
||||
| Base Property | Clipper JSON Property Name | Value Strategy |
|
||||
| :--- | :--- | :--- |
|
||||
| `note.author` | `author` | `{{author}}` or `{{schema:author.name}}` |
|
||||
| `note.source` | `source` | `{{url}}` |
|
||||
| `note.published` | `published` | `{{published}}` |
|
||||
| `note.ingredients` | `ingredients` | `{{schema:Recipe:recipeIngredient}}` |
|
||||
| `note.type` | `type` | Constant (e.g., `Recipe`) or empty |
|
||||
|
||||
**Crucial Step:** Ask the user which properties should be automatically filled, which should be hardcoded (e.g., `type: Recipe`), and which should be left empty for manual entry.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Obsidian Web Clipper Filters
|
||||
|
||||
**Official Docs:** [help.obsidian.md/web-clipper/filters](https://help.obsidian.md/web-clipper/filters)
|
||||
|
||||
Use filters to format variables: `{{variable|filter}}`.
|
||||
|
||||
## Text Formatting
|
||||
- `markdown`: Convert HTML to Markdown.
|
||||
- `strip_tags`: Remove HTML tags.
|
||||
- `trim`: Remove whitespace.
|
||||
- `upper`: Convert to uppercase.
|
||||
- `lower`: Convert to lowercase.
|
||||
- `title`: Title Case.
|
||||
- `capitalize`: Capitalize first letter.
|
||||
- `camel`: CamelCase.
|
||||
- `kebab`: kebab-case.
|
||||
- `snake`: snake_case.
|
||||
- `pascal`: PascalCase.
|
||||
- `replace:"old","new"`: Replace text.
|
||||
- `safe_name`: Make safe for filenames.
|
||||
- `blockquote`: Format as blockquote.
|
||||
- `link`: Create markdown link.
|
||||
- `wikilink`: Create [[wikilink]].
|
||||
- `list`: Format array as list.
|
||||
- `table`: Format array as table.
|
||||
- `callout`: Format as callout block.
|
||||
|
||||
## Dates
|
||||
- `date:"format"`: Format date (e.g., `YYYY-MM-DD`).
|
||||
- `date_modify:"+1 day"`: Modify date.
|
||||
- `duration`: Format duration.
|
||||
|
||||
## Numbers
|
||||
- `calc`: Perform calculations.
|
||||
- `length`: Get length of string/array.
|
||||
- `round`: Round numbers.
|
||||
|
||||
## HTML Processing
|
||||
- `remove_html`: Remove HTML tags.
|
||||
- `remove_attr`: Remove attributes.
|
||||
- `strip_attr`: Strip specific attributes.
|
||||
|
||||
## Arrays and Objects
|
||||
- `map`: Transform array items (e.g., `map:item =>> item.text`).
|
||||
- `join:"separator"`: Join array items.
|
||||
- `split:"separator"`: Split string into array.
|
||||
- `first`: First item.
|
||||
- `last`: Last item.
|
||||
- `slice:start,end`: Slice array.
|
||||
- `unique`: Unique items.
|
||||
- `template:"format"`: Format items using a template string.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Obsidian Web Clipper JSON Schema
|
||||
|
||||
The Obsidian Web Clipper imports templates via JSON files.
|
||||
|
||||
## Root Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "0.1.0",
|
||||
"name": "Template Name",
|
||||
"behavior": "create",
|
||||
"noteContentFormat": "Markdown content here...",
|
||||
"properties": [],
|
||||
"triggers": [],
|
||||
"noteNameFormat": "{{title}}",
|
||||
"path": "Inbox/"
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
* **`schemaVersion`**: Always "0.1.0".
|
||||
* **`name`**: The display name of the template in the Clipper.
|
||||
* **`behavior`**: How the note is created.
|
||||
* `create`: Create a new note.
|
||||
* `append-specific`: Append to a specific note (requires `path` to be a full file path).
|
||||
* `append-daily`: Append to the daily note.
|
||||
* **`noteContentFormat`**: The body of the note.
|
||||
* Use `\n` for newlines.
|
||||
* Can use all variables (e.g., `{{content}}`, `{{selection}}`).
|
||||
* **`noteNameFormat`**: The filename pattern (e.g., `{{date}} - {{title}}`).
|
||||
* **`path`**: The location to save the note.
|
||||
* For `create` behavior: The *folder* to save the note in (e.g., `Clippings/` or `Recipes/`).
|
||||
* For `append-specific` behavior: The *full file path* of the note to append to (e.g., `Databases/Recipes.md`).
|
||||
* **`triggers`**: Array of strings to automatically select this template.
|
||||
* **URL Patterns**: `["https://www.youtube.com/watch"]` (Simple string or Regex).
|
||||
* **Schema Types**: `["schema:Recipe"]` (Triggers if the page contains this Schema.org type).
|
||||
|
||||
## Properties
|
||||
|
||||
The `properties` array defines the YAML frontmatter of the note.
|
||||
|
||||
```json
|
||||
"properties": [
|
||||
{
|
||||
"name": "category",
|
||||
"value": "Recipes",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "published",
|
||||
"value": "{{published}}",
|
||||
"type": "datetime"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Property Types
|
||||
|
||||
* **`text`**: Simple text string.
|
||||
* **`multitext`**: List of text strings (for tags/aliases).
|
||||
* **`number`**: Numeric value.
|
||||
* **`checkbox`**: Boolean true/false.
|
||||
* **`date`**: Date string (YYYY-MM-DD).
|
||||
* **`datetime`**: Date and time string.
|
||||
|
||||
### Property Object Structure
|
||||
|
||||
* **`name`**: The key in the YAML frontmatter.
|
||||
* **`value`**: The value to populate. Can contain variables.
|
||||
* **`type`**: One of the types listed above.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Obsidian Web Clipper Variables
|
||||
|
||||
**Official Docs:** [help.obsidian.md/web-clipper/variables](https://help.obsidian.md/web-clipper/variables)
|
||||
|
||||
## Preset Variables
|
||||
Automatically extracted from the page.
|
||||
|
||||
- `{{content}}`: Main article content (markdown).
|
||||
- `{{contentHtml}}`: Main article content (HTML).
|
||||
- `{{title}}`: Page title.
|
||||
- `{{url}}`: Page URL.
|
||||
- `{{author}}`: Author name.
|
||||
- `{{date}}`: Current date.
|
||||
- `{{published}}`: Publication date (if detected).
|
||||
- `{{site}}`: Site name.
|
||||
- `{{description}}`: Meta description.
|
||||
- `{{highlights}}`: Highlighted text (if any).
|
||||
- `{{selection}}`: Selected text.
|
||||
- `{{fullHtml}}`: Full page HTML.
|
||||
- `{{favicon}}`: Favicon URL.
|
||||
- `{{image}}`: Social share image URL.
|
||||
- `{{words}}`: Word count.
|
||||
- `{{domain}}`: Domain name.
|
||||
|
||||
## Prompt Variables (AI)
|
||||
Use `{{"Your prompt here"}}` to ask the AI Interpreter to extract or summarize info.
|
||||
*Requires Interpreter to be enabled.*
|
||||
|
||||
Examples:
|
||||
- `{{"Summarize in 3 bullet points"}}`
|
||||
- `{{"Extract the ingredients list"}}`
|
||||
- `{{"Translate to English"}}`
|
||||
|
||||
## Selector Variables
|
||||
Extract content using CSS selectors.
|
||||
Syntax: `{{selector:css-selector}}` or `{{selector:css-selector?attribute}}`
|
||||
|
||||
Examples:
|
||||
- `{{selector:h1}}`: Text of H1 tag.
|
||||
- `{{selector:img.hero?src}}`: Source of image with class 'hero'.
|
||||
- `{{selector:.author}}`: Text of element with class 'author'.
|
||||
- `{{selectorHtml:body|markdown}}`: Full HTML converted to markdown.
|
||||
|
||||
## Meta Variables
|
||||
Extract data from meta tags.
|
||||
Syntax: `{{meta:name}}` or `{{meta:property}}`
|
||||
|
||||
Examples:
|
||||
- `{{meta:description}}`
|
||||
- `{{meta:og:title}}`
|
||||
|
||||
## Schema.org Variables
|
||||
Extract structured data.
|
||||
Syntax: `{{schema:Property}}` or `{{schema:@Type:Property}}`
|
||||
|
||||
Examples:
|
||||
- `{{schema:Recipe:recipeIngredient}}`
|
||||
- `{{schema:author.name}}`
|
||||
- `{{schema:Article:headline}}`
|
||||
Reference in New Issue
Block a user