Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "open-source",
|
||||||
|
"description": "Collection of skills for general open-source package development and maintenance",
|
||||||
|
"version": "0.0.0-2025.11.28",
|
||||||
|
"author": {
|
||||||
|
"name": "Garrick Aden-Buie (Posit, PBC)",
|
||||||
|
"email": "garrick@posit.co"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills/release-post"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# open-source
|
||||||
|
|
||||||
|
Collection of skills for general open-source package development and maintenance
|
||||||
60
plugin.lock.json
Normal file
60
plugin.lock.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:posit-dev/skills:open-source",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "ce081441bd7f0390c6dd3e116be8f633d88e7219",
|
||||||
|
"treeHash": "c5e09a6309d52e85e8671d6b2b58bbfa5a09897a380df94d09a58209e598fa37",
|
||||||
|
"generatedAt": "2025-11-28T10:27:39.596322Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "open-source",
|
||||||
|
"description": "Collection of skills for general open-source package development and maintenance"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "de17cbd0c2076d3e3ac4f98e41c6e700e6726baec90503fd3c375026021a3787"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "da888cd4dd2b7c4d10e686f0facfb9ce8b0d6b9aa25568d72cc376155580a333"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/release-post/SKILL.md",
|
||||||
|
"sha256": "77b4f5c981f5a41642c81fc1d84cc63a4e6397c6c8b24ffe0e681627ef86cd53"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/release-post/references/content-guidelines.md",
|
||||||
|
"sha256": "b4f2960a87352918abd232d86a5a7754f903842a9d8f1e578f5f6b9657a88bae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/release-post/references/shiny-formatting.md",
|
||||||
|
"sha256": "30dd05e615eb46fa7db21d20bb02739abe0a7324a524105cf62c21627ca1e014"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/release-post/references/tidyverse-formatting.md",
|
||||||
|
"sha256": "6f9d8aae3c24f9a81827b89ca3dd05f5817e2e783abdd8d02b1bbdf51f2fec10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/release-post/scripts/get_contributors.R",
|
||||||
|
"sha256": "93a03708015bf7ea7af2478004817892b5f11e65c92f934d0f73cd1481109f1b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "c5e09a6309d52e85e8671d6b2b58bbfa5a09897a380df94d09a58209e598fa37"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
285
skills/release-post/SKILL.md
Normal file
285
skills/release-post/SKILL.md
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
---
|
||||||
|
name: release-post
|
||||||
|
description: >
|
||||||
|
Create professional package release blog posts following Tidyverse or Shiny blog conventions.
|
||||||
|
Use when the user needs to: (1) Write a release announcement blog post for an R or Python package
|
||||||
|
for tidyverse.org or shiny.posit.co, (2) Transform NEWS/changelog content into blog format,
|
||||||
|
(3) Generate acknowledgments sections with contributor lists, (4) Format posts following specific
|
||||||
|
blog platform requirements. Supports both Tidyverse (hugodown) and Shiny (Quarto) blog formats with
|
||||||
|
automated contributor fetching and comprehensive style guidance.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Package Release Post
|
||||||
|
|
||||||
|
Create professional R/Python package release blog posts following Tidyverse or Shiny blog conventions.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Identify the blog platform**: Tidyverse (tidyverse.org) or Shiny (shiny.posit.co)
|
||||||
|
2. Verify NEWS.md or changelog exists for the package
|
||||||
|
3. Gather package info: name, version, repository (e.g., "tidyverse/dplyr")
|
||||||
|
4. Follow the workflow below
|
||||||
|
5. Use `scripts/get_contributors.R` to generate acknowledgments
|
||||||
|
6. Reference the appropriate formatting guide for final polish
|
||||||
|
|
||||||
|
## Platform Selection
|
||||||
|
|
||||||
|
This skill supports two blog platforms with different formatting requirements:
|
||||||
|
|
||||||
|
- **Tidyverse blog** (tidyverse.org)
|
||||||
|
- Uses hugodown
|
||||||
|
- R packages primarily
|
||||||
|
- More rigid structure and conventions
|
||||||
|
- See `references/tidyverse-formatting.md`
|
||||||
|
|
||||||
|
- **Shiny blog** (shiny.posit.co)
|
||||||
|
- Uses Quarto
|
||||||
|
- R and Python packages
|
||||||
|
- More flexible, feature-focused structure
|
||||||
|
- See `references/shiny-formatting.md`
|
||||||
|
|
||||||
|
**First, determine which platform the post is for**, then follow the general workflow and apply platform-specific formatting.
|
||||||
|
|
||||||
|
## General Workflow
|
||||||
|
|
||||||
|
These steps apply to both platforms. Content guidelines are based on Tidyverse best practices but adapt them as needed for Shiny posts.
|
||||||
|
|
||||||
|
### Step 1: Gather Information
|
||||||
|
|
||||||
|
Collect required information:
|
||||||
|
|
||||||
|
- **Platform**: Tidyverse or Shiny blog?
|
||||||
|
- **Package name and version**: e.g., "dplyr 1.2.0" or "shiny 1.9.0"
|
||||||
|
- **Repository**: GitHub repo in "owner/repo" format
|
||||||
|
- **Package language**: R or Python
|
||||||
|
- **NEWS content**: Read the package's NEWS.md, CHANGELOG, or NEWS
|
||||||
|
- **Package description**: One-sentence core purpose
|
||||||
|
- **Previous release tag**: For contributor fetching (optional)
|
||||||
|
- **Featured image**: For frontmatter (optional but recommended)
|
||||||
|
|
||||||
|
### Step 2: Structure the Post
|
||||||
|
|
||||||
|
Create the post outline following this order:
|
||||||
|
|
||||||
|
1. **Frontmatter**: Platform-specific YAML (see formatting references)
|
||||||
|
|
||||||
|
2. **Title and Opening**:
|
||||||
|
- Title: Package name and version
|
||||||
|
- Opening: Announcement with one-sentence package description
|
||||||
|
- Installation: Code block with installation command
|
||||||
|
- Overview: Brief summary with link to full release notes
|
||||||
|
|
||||||
|
3. **Main Content** (choose appropriate sections):
|
||||||
|
- **Migration guide** (if breaking changes) - Always first when present
|
||||||
|
- **Lifecycle changes** (deprecations, soft-deprecations, defunct)
|
||||||
|
- **Feature sections** (one per major feature, descriptive headings)
|
||||||
|
- **Minor improvements** (bulleted list)
|
||||||
|
|
||||||
|
4. **Acknowledgements** (when appropriate):
|
||||||
|
- Use `scripts/get_contributors.R`
|
||||||
|
- Format: "A big thank you to all the folks who helped make this release happen:"
|
||||||
|
- Comma-separated GitHub links
|
||||||
|
|
||||||
|
### Step 3: Apply Content Guidelines
|
||||||
|
|
||||||
|
Follow the best practices in `references/content-guidelines.md`:
|
||||||
|
|
||||||
|
- **Opening style**: "We're [random adjective expressing excitement] to announce the release of..."
|
||||||
|
- **Section organization**: Migration → Lifecycle → Features → Improvements → Acknowledgements
|
||||||
|
- **Tone**: Conversational, professional, enthusiastic but authentic
|
||||||
|
- **Technical precision**: Use exact function names in backticks
|
||||||
|
- **Focus on benefits**: Explain "why" not just "what"
|
||||||
|
- **Code examples**: Realistic, well-commented, properly formatted
|
||||||
|
|
||||||
|
### Step 4: Transform NEWS Content
|
||||||
|
|
||||||
|
Convert NEWS.md bullets to blog-friendly content:
|
||||||
|
|
||||||
|
- **Research features thoroughly**: Don't just copy NEWS bullets—read function docs, check PRs, understand the context
|
||||||
|
- **Expand context**: Why changes matter, not just what changed
|
||||||
|
- **Add complete code examples**: Show realistic usage with full workflows, not just function signatures
|
||||||
|
- **Explain concepts first**: For unfamiliar features, explain what they are and how they work before showing code
|
||||||
|
- **Group thematically**: Combine related NEWS items into coherent sections
|
||||||
|
- **Use conversational tone**: Transform terse bullets into prose
|
||||||
|
- **Link documentation**: Add relevant links to docs and resources
|
||||||
|
- **Highlight breaking changes**: Make migration paths clear
|
||||||
|
- **Multi-language parity** (Shiny only): For R+Python packages on the Shiny blog, ensure all examples show both languages in tabsets
|
||||||
|
|
||||||
|
### Step 5: Apply Platform-Specific Formatting
|
||||||
|
|
||||||
|
**For Tidyverse posts**, read `references/tidyverse-formatting.md` and apply:
|
||||||
|
- hugodown frontmatter with `slug`, `photo.url`, `photo.author`
|
||||||
|
- Specific slug format: `packagename-x-y-z` (hyphens replace dots)
|
||||||
|
- R code blocks with `r` language identifier
|
||||||
|
- Acknowledgements always included as final section
|
||||||
|
|
||||||
|
**For Shiny posts**, read `references/shiny-formatting.md` and apply:
|
||||||
|
- Quarto frontmatter with YAML anchors for social media
|
||||||
|
- Flexible title formatting
|
||||||
|
- Use tabsets for Python/R or Express/Core variations
|
||||||
|
- Platform-specific code block attributes
|
||||||
|
- Acknowledgements optional, varies by post type
|
||||||
|
- May use lead paragraphs, callouts, embedded media
|
||||||
|
|
||||||
|
### Step 6: Generate Acknowledgements
|
||||||
|
|
||||||
|
Run the contributor script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Rscript scripts/get_contributors.R "owner/repo"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or with a specific starting tag for the previous version (or tag used for last release post):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Rscript scripts/get_contributors.R "owner/repo" "v1.0.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the markdown output into the Acknowledgements section.
|
||||||
|
|
||||||
|
### Step 7: Review and Polish
|
||||||
|
|
||||||
|
Platform-agnostic checklist:
|
||||||
|
|
||||||
|
- [ ] Frontmatter complete with all required fields
|
||||||
|
- [ ] Opening clearly states package purpose
|
||||||
|
- [ ] Installation code block present (both languages if applicable)
|
||||||
|
- [ ] Sections organized logically
|
||||||
|
- [ ] Code examples use proper syntax highlighting
|
||||||
|
- [ ] Function names in backticks with parentheses: `` `function()` ``
|
||||||
|
- [ ] Package names are not backticked or otherwise styled
|
||||||
|
- [ ] Tone is conversational but not marketing-speak
|
||||||
|
- [ ] No superlatives ("powerful", "rich", "seamless", etc.)
|
||||||
|
- [ ] Features explained with context, not just listed
|
||||||
|
- [ ] Concepts explained before showing code
|
||||||
|
- [ ] All examples show R and Python variants (if applicable)
|
||||||
|
- [ ] Links to full release notes included
|
||||||
|
|
||||||
|
Platform-specific checklist:
|
||||||
|
|
||||||
|
**Tidyverse:**
|
||||||
|
- [ ] Slug format: `package-x-y-z` (hyphens, not dots)
|
||||||
|
- [ ] Photo URL and author included
|
||||||
|
- [ ] Acknowledgements section is final section
|
||||||
|
- [ ] All contributors listed alphabetically
|
||||||
|
|
||||||
|
**Shiny:**
|
||||||
|
- [ ] YAML anchors used for description (`&desc`, `*desc`)
|
||||||
|
- [ ] Social media cards configured (`open-graph`, `twitter-card`)
|
||||||
|
- [ ] Appropriate filters specified if using tabsets/shinylive
|
||||||
|
- [ ] Tabsets used for showing paired variants (Python/R, Express/Core)
|
||||||
|
- [ ] Multi-language tabsets used consistently (for R+Python packages only)
|
||||||
|
|
||||||
|
## Reference Documentation
|
||||||
|
|
||||||
|
Load these as needed for detailed guidance:
|
||||||
|
|
||||||
|
### Content Guidelines
|
||||||
|
**`references/content-guidelines.md`** - General best practices for all release posts:
|
||||||
|
- Post structure and organization
|
||||||
|
- Opening style and tone
|
||||||
|
- Section hierarchy and organization
|
||||||
|
- Code examples and formatting
|
||||||
|
- Before/after patterns
|
||||||
|
- Acknowledgments conventions
|
||||||
|
|
||||||
|
### Platform-Specific Formatting
|
||||||
|
|
||||||
|
**`references/tidyverse-formatting.md`** - Tidyverse blog requirements:
|
||||||
|
- hugodown frontmatter structure
|
||||||
|
- Slug and title conventions
|
||||||
|
- Photo attribution
|
||||||
|
- Code block formatting
|
||||||
|
- Lifecycle section structure
|
||||||
|
- Acknowledgements format
|
||||||
|
|
||||||
|
**`references/shiny-formatting.md`** - Shiny blog requirements:
|
||||||
|
- Quarto frontmatter with YAML anchors
|
||||||
|
- Social media card configuration
|
||||||
|
- Lead paragraphs and callouts
|
||||||
|
- Tabsets for variants
|
||||||
|
- Line highlighting and annotations
|
||||||
|
- Video embedding
|
||||||
|
- Flexible acknowledgements
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- **`scripts/get_contributors.R`**: Fetch formatted contributor list using `usethis::use_tidy_thanks()`
|
||||||
|
- **`references/content-guidelines.md`**: General content best practices (platform-agnostic)
|
||||||
|
- **`references/tidyverse-formatting.md`**: Tidyverse-specific formatting requirements
|
||||||
|
- **`references/shiny-formatting.md`**: Shiny-specific formatting requirements
|
||||||
|
|
||||||
|
## Platform-Specific Quick Reference
|
||||||
|
|
||||||
|
### Tidyverse Post Template
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
---
|
||||||
|
output: hugodown::hugo_document
|
||||||
|
slug: package-x-y-z
|
||||||
|
title: package x.y.z
|
||||||
|
date: YYYY-MM-DD
|
||||||
|
author: Your Name
|
||||||
|
description: >
|
||||||
|
Brief description
|
||||||
|
photo:
|
||||||
|
url: https://unsplash.com/photos/id
|
||||||
|
author: Photographer Name
|
||||||
|
categories: [package]
|
||||||
|
tags: [package]
|
||||||
|
---
|
||||||
|
|
||||||
|
# package x.y.z
|
||||||
|
|
||||||
|
We're pleased to announce the release of package x.y.z...
|
||||||
|
|
||||||
|
```r
|
||||||
|
install.packages("package")
|
||||||
|
```
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
A big thank you to all the folks who helped make this release happen:
|
||||||
|
|
||||||
|
[Contributors from get_contributors.R]
|
||||||
|
````
|
||||||
|
|
||||||
|
### Shiny Post Template
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
---
|
||||||
|
title: Package Name x.y.z
|
||||||
|
description: &desc |
|
||||||
|
Brief description of the release.
|
||||||
|
author: "Your Name"
|
||||||
|
date: "YYYY-MM-DD"
|
||||||
|
|
||||||
|
image: feature.png
|
||||||
|
|
||||||
|
open-graph:
|
||||||
|
image: feature.png
|
||||||
|
description: *desc
|
||||||
|
twitter-card:
|
||||||
|
image: feature.png
|
||||||
|
description: *desc
|
||||||
|
---
|
||||||
|
|
||||||
|
# package x.y.z
|
||||||
|
|
||||||
|
We're excited to announce package x.y.z...
|
||||||
|
|
||||||
|
[Installation for Python or R]
|
||||||
|
|
||||||
|
...
|
||||||
|
````
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- **Breaking changes first**: Put migration guides before features
|
||||||
|
- **Highlight the wins**: Lead with the most exciting features
|
||||||
|
- **Show don't tell**: Use code examples liberally
|
||||||
|
- **Link generously**: Help readers find more information
|
||||||
|
- **Keep it conversational**: Write like you're explaining to a colleague
|
||||||
|
- **Be authentic**: Enthusiasm should feel genuine, not marketing-speak
|
||||||
409
skills/release-post/references/content-guidelines.md
Normal file
409
skills/release-post/references/content-guidelines.md
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
# Content Guidelines for Release Posts
|
||||||
|
|
||||||
|
General best practices for release post content, regardless of blog platform. These guidelines are based primarily on Tidyverse blog conventions, which provide a principled approach to announcing package updates.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
1. [Post Structure](#post-structure)
|
||||||
|
2. [Opening Style](#opening-style)
|
||||||
|
3. [Section Organization](#section-organization)
|
||||||
|
4. [Tone and Voice](#tone-and-voice)
|
||||||
|
5. [Code Examples](#code-examples)
|
||||||
|
6. [Acknowledgments](#acknowledgments)
|
||||||
|
|
||||||
|
## Post Structure
|
||||||
|
|
||||||
|
Standard structure for release posts:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[Frontmatter - see formatting guides]
|
||||||
|
|
||||||
|
# Package Version
|
||||||
|
|
||||||
|
[Opening paragraph with package description]
|
||||||
|
|
||||||
|
[Installation instructions]
|
||||||
|
|
||||||
|
[Overview paragraph about the release]
|
||||||
|
|
||||||
|
## Major Feature 1
|
||||||
|
[Content...]
|
||||||
|
|
||||||
|
## Major Feature 2
|
||||||
|
[Content...]
|
||||||
|
|
||||||
|
## Minor improvements
|
||||||
|
[Bulleted list...]
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
[Contributor list]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Opening Style
|
||||||
|
|
||||||
|
### Opening Paragraph Pattern
|
||||||
|
|
||||||
|
Start with an announcement that establishes the package's core purpose:
|
||||||
|
|
||||||
|
> "We're [pleased/chuffed/stoked/thrilled/delighted/excited/...] to announce the release of [package] [version]. [Package] [core purpose description in one sentence]."
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- "We're chuffed to announce the release of testthat 3.3.0. testthat makes it easy to turn your existing informal tests into formal, automated tests"
|
||||||
|
- "We're pleased to announce the release of pkgdown 2.2.0. pkgdown is designed to make it quick and easy to build a beautiful and accessible website"
|
||||||
|
- "We're excited to announce the new Shiny extension for VS Code!"
|
||||||
|
|
||||||
|
**Vocabulary variations:**
|
||||||
|
- Choose an upbeat and random adjective with connotations of excitement.
|
||||||
|
- Be interesting and bold, but above all positive and fun.
|
||||||
|
|
||||||
|
### Installation Instructions
|
||||||
|
|
||||||
|
Follow the opening with installation instructions as a code block:
|
||||||
|
|
||||||
|
**R packages:**
|
||||||
|
```r
|
||||||
|
install.packages("packagename")
|
||||||
|
```
|
||||||
|
|
||||||
|
For multiple packages:
|
||||||
|
```r
|
||||||
|
install.packages(c("shiny", "bslib"))
|
||||||
|
```
|
||||||
|
|
||||||
|
**Python packages:**
|
||||||
|
```bash
|
||||||
|
pip install packagename
|
||||||
|
```
|
||||||
|
|
||||||
|
With extras:
|
||||||
|
```bash
|
||||||
|
pip install "packagename[extra]"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Overview Paragraph
|
||||||
|
|
||||||
|
Brief overview of the release following installation:
|
||||||
|
|
||||||
|
- Link to full release notes when available
|
||||||
|
- Highlight focus areas: "This release focuses on [key themes]"
|
||||||
|
- Set expectations: "This is a [major/minor] release with [X main features]"
|
||||||
|
- Acknowledge breaking changes: "This release includes a number of new features... Some of these changes may require you to update your existing code"
|
||||||
|
|
||||||
|
## Section Organization
|
||||||
|
|
||||||
|
### Standard Section Hierarchy
|
||||||
|
|
||||||
|
Organize content in this order:
|
||||||
|
|
||||||
|
1. **Migration guide** (if breaking changes)
|
||||||
|
- Put this first when there are breaking changes
|
||||||
|
- Use clear before/after examples
|
||||||
|
- Explain the rationale for changes
|
||||||
|
|
||||||
|
2. **Lifecycle changes** (if applicable but not breaking)
|
||||||
|
- Soft deprecations
|
||||||
|
- Deprecations
|
||||||
|
- Defunct (removed) functions
|
||||||
|
- Non-breaking behavioral changes
|
||||||
|
|
||||||
|
3. **Major new features** (primary content)
|
||||||
|
- One section per major feature or theme
|
||||||
|
- Use descriptive headings
|
||||||
|
- Lead with what the feature does and why it matters
|
||||||
|
- Include examples
|
||||||
|
|
||||||
|
4. **Minor improvements** or **Other new features**
|
||||||
|
- Bulleted list of smaller enhancements
|
||||||
|
- Brief explanations
|
||||||
|
- Can group related items
|
||||||
|
|
||||||
|
5. **Acknowledgements** (always final)
|
||||||
|
- Thank contributors
|
||||||
|
- List all contributors with GitHub links
|
||||||
|
|
||||||
|
### Section Heading Style
|
||||||
|
|
||||||
|
- Use sentence case: "Lifecycle changes" not "Lifecycle Changes"
|
||||||
|
- Be descriptive: "Easier `in_parallel()`" not just "New feature"
|
||||||
|
- Include function names in backticks when relevant
|
||||||
|
- Make headings scannable and informative
|
||||||
|
|
||||||
|
### Content Organization Within Sections
|
||||||
|
|
||||||
|
**For migration guides:**
|
||||||
|
```markdown
|
||||||
|
## Migrating to vX.Y.Z
|
||||||
|
|
||||||
|
### Setting the app theme
|
||||||
|
|
||||||
|
Prior to vX.Y.Z, you could...
|
||||||
|
|
||||||
|
[Before example]
|
||||||
|
|
||||||
|
**With packagename vX.Y.Z,** you now need to...
|
||||||
|
|
||||||
|
[After example]
|
||||||
|
|
||||||
|
Read about [the feature](#feature) below to learn why this change was needed.
|
||||||
|
```
|
||||||
|
|
||||||
|
**For lifecycle changes:**
|
||||||
|
```markdown
|
||||||
|
## Lifecycle changes
|
||||||
|
|
||||||
|
* **Fully removed** after 5+ years of deprecation:
|
||||||
|
* `function1()` - use `replacement1()` instead
|
||||||
|
* `function2()` - use `replacement2()` instead
|
||||||
|
|
||||||
|
* **Newly deprecated** (soft-deprecation):
|
||||||
|
* `function3()` is superseded by `function4()`
|
||||||
|
* `function5()` is no longer recommended
|
||||||
|
|
||||||
|
* **Breaking changes**:
|
||||||
|
* Brief description of the change and impact
|
||||||
|
```
|
||||||
|
|
||||||
|
**For feature sections:**
|
||||||
|
- Lead with a clear description of what the feature does
|
||||||
|
- Provide context on why it's useful or what problem it solves
|
||||||
|
- Include code examples showing usage
|
||||||
|
- Explain configuration options if relevant
|
||||||
|
- Link to relevant documentation
|
||||||
|
|
||||||
|
### Deep Dives on Features
|
||||||
|
|
||||||
|
Don't just list features from NEWS—research them and provide comprehensive explanations:
|
||||||
|
|
||||||
|
**Transform NEWS bullets into complete sections:**
|
||||||
|
|
||||||
|
1. **Research the feature**:
|
||||||
|
- Read function documentation
|
||||||
|
- Check related PRs and issues for context
|
||||||
|
- Understand the motivation and use cases
|
||||||
|
|
||||||
|
2. **Add complete code examples**:
|
||||||
|
- Show realistic usage, not just function signatures
|
||||||
|
- Include comments explaining what's happening
|
||||||
|
- Demonstrate the full workflow, not just isolated calls
|
||||||
|
|
||||||
|
3. **Explain the context**:
|
||||||
|
- Why was this feature added?
|
||||||
|
- What problem does it solve?
|
||||||
|
- What are the practical use cases?
|
||||||
|
- How does it fit into typical workflows?
|
||||||
|
|
||||||
|
4. **Show use cases and applications**:
|
||||||
|
- Provide examples of when users would need this
|
||||||
|
- Explain different configuration options
|
||||||
|
- Show how features work together
|
||||||
|
|
||||||
|
**Example transformation:**
|
||||||
|
|
||||||
|
❌ **NEWS bullet approach:**
|
||||||
|
```markdown
|
||||||
|
## Bookmarking
|
||||||
|
- Added `chat_restore()` for bookmarking support (#82)
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ **Deep dive approach:**
|
||||||
|
```markdown
|
||||||
|
### Bookmarking support
|
||||||
|
|
||||||
|
shinychat now supports Shiny's bookmarking feature for saving and restoring chat sessions.
|
||||||
|
The new `chat_restore()` function saves the chat client state and restores the message history:
|
||||||
|
|
||||||
|
[Complete code example showing actual usage]
|
||||||
|
|
||||||
|
By default, `chat_restore()` automatically updates the bookmark when users submit messages
|
||||||
|
and when the LLM completes its response. This means users can refresh the page or share a
|
||||||
|
URL and pick up right where they left off.
|
||||||
|
|
||||||
|
For apps with large chat histories, you can use `enableBookmarking = "server"` to store
|
||||||
|
state server-side without URL size limitations.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Research sources:**
|
||||||
|
- Use `r-btw` tools to read R function documentation
|
||||||
|
- Read GitHub PRs/issues linked in NEWS
|
||||||
|
- Check package vignettes and articles
|
||||||
|
- Look at example apps in the repository
|
||||||
|
|
||||||
|
**For improvements:**
|
||||||
|
```markdown
|
||||||
|
## Minor improvements
|
||||||
|
|
||||||
|
* Brief description of improvement with function name in backticks
|
||||||
|
* Another improvement with relevant technical details
|
||||||
|
* Performance gains quantified when possible (e.g., "2x faster")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tone and Voice
|
||||||
|
|
||||||
|
### Writing Style
|
||||||
|
|
||||||
|
- **Conversational but professional**: "We're excited to announce" rather than "It is announced"
|
||||||
|
- **Inclusive**: Use "we" and "you" rather than passive voice
|
||||||
|
- **Enthusiastic but authentic**: Avoid over-the-top marketing language
|
||||||
|
- **Technical precision**: Use exact function names, parameter names, and technical terms
|
||||||
|
- **Focus on benefits**: Explain the "why" not just the "what"
|
||||||
|
|
||||||
|
### Avoiding Marketing Speak
|
||||||
|
|
||||||
|
Release posts should be friendly and instructional, not advertising. Watch for and remove:
|
||||||
|
|
||||||
|
**Superlatives and promotional adjectives:**
|
||||||
|
- ❌ "powerful set of features", "rich, interactive displays", "beautiful interface"
|
||||||
|
- ✅ "set of features", "interactive displays", "interface"
|
||||||
|
|
||||||
|
**Exaggerated benefit claims:**
|
||||||
|
- ❌ "handles all the complexity of persisting state"
|
||||||
|
- ✅ "saves the chat client state and restores the message history"
|
||||||
|
|
||||||
|
**Generic enthusiasm:**
|
||||||
|
- ❌ "opens up exciting possibilities for building transparent, user-friendly AI applications"
|
||||||
|
- ✅ Direct description of what the feature does
|
||||||
|
|
||||||
|
**Over-hyped capability statements:**
|
||||||
|
- ❌ "give you fine-grained control over every aspect"
|
||||||
|
- ✅ "lets you control the chat interface"
|
||||||
|
|
||||||
|
**Tone review checklist:**
|
||||||
|
- [ ] Remove words like "powerful", "robust", "seamless", "elegant", "revolutionary"
|
||||||
|
- [ ] Replace "makes it easy to" with direct descriptions of functionality
|
||||||
|
- [ ] Prefer descriptive statements focusing on what the function does
|
||||||
|
- [ ] Avoid overuse of phrases that sound like product marketing ("best-in-class", "production-ready")
|
||||||
|
|
||||||
|
|
||||||
|
### Common Phrases
|
||||||
|
|
||||||
|
- "We're [emotion] to announce..."
|
||||||
|
- "A big thank you to all the folks who helped make this release happen"
|
||||||
|
- "You can see a full list of changes in the release notes"
|
||||||
|
- "This makes it easier to..."
|
||||||
|
- "We've improved..."
|
||||||
|
- "This release focuses on..."
|
||||||
|
- "Prior to vX.Y.Z, you had to..."
|
||||||
|
- "With this release, you can now..."
|
||||||
|
|
||||||
|
### Technical Voice
|
||||||
|
|
||||||
|
- Use backticks for all code elements: `` `function()` ``, `` `argument` ``, `` `"value"` ``
|
||||||
|
- Link to relevant documentation when helpful
|
||||||
|
- Be specific about behavior: "returns `NULL`" not "returns nothing"
|
||||||
|
- Explain technical decisions when they impact users
|
||||||
|
- Acknowledge tradeoffs when present
|
||||||
|
|
||||||
|
## Code Examples
|
||||||
|
|
||||||
|
### Explain Concepts Before Code
|
||||||
|
|
||||||
|
For features that introduce new or unfamiliar concepts, explain the concept first before showing code:
|
||||||
|
|
||||||
|
**Pattern: Concept → How it works → Why it matters → Code**
|
||||||
|
|
||||||
|
1. **What is the feature/concept?** (1-2 sentences)
|
||||||
|
2. **How does it work?** (Especially non-obvious aspects)
|
||||||
|
3. **Why does it matter?** (Practical implications)
|
||||||
|
4. **Show the code** (With examples)
|
||||||
|
|
||||||
|
**Key principles:**
|
||||||
|
- Assume readers may not be familiar with the concept
|
||||||
|
- Explain non-obvious aspects clearly
|
||||||
|
- Connect concepts to practical outcomes
|
||||||
|
- Use plain language before technical language
|
||||||
|
|
||||||
|
### Inline Code
|
||||||
|
|
||||||
|
- Function names: `` `map_chr()` ``
|
||||||
|
- Arguments: `` `na.rm = TRUE` ``
|
||||||
|
- Values: `` `NULL` ``, `` `TRUE` ``, `` `"string"` ``
|
||||||
|
- File paths: `` `app.py` ``
|
||||||
|
|
||||||
|
### Code Block Principles
|
||||||
|
|
||||||
|
- Use realistic but simple examples
|
||||||
|
- Include expected output when relevant
|
||||||
|
- Show error messages for examples of better error handling
|
||||||
|
- Format multi-line function calls with proper indentation
|
||||||
|
- Add comments for clarity when needed: `# This does X`
|
||||||
|
- Keep examples focused on the feature being demonstrated
|
||||||
|
|
||||||
|
### Before/After Examples
|
||||||
|
|
||||||
|
When showing improvements, use clear before/after structure:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Previously, you had to write:
|
||||||
|
|
||||||
|
[Code block showing old approach]
|
||||||
|
|
||||||
|
Now you can write:
|
||||||
|
|
||||||
|
[Code block showing new approach]
|
||||||
|
```
|
||||||
|
|
||||||
|
Or for migration guides:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
**Before:**
|
||||||
|
|
||||||
|
[Old code]
|
||||||
|
|
||||||
|
**After:**
|
||||||
|
|
||||||
|
[New code]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
### When to Include
|
||||||
|
|
||||||
|
- **Always include** for package releases with external contributors
|
||||||
|
- Optional for internal tooling announcements
|
||||||
|
- Include at the end as the final section
|
||||||
|
|
||||||
|
### Section Format
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
A big thank you to all [the folks/everyone] who [helped make this release happen/contributed to this release]:
|
||||||
|
|
||||||
|
[@username1](https://github.com/username1), [@username2](https://github.com/username2), ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fetching Contributors
|
||||||
|
|
||||||
|
Use `usethis::use_tidy_thanks()` in R:
|
||||||
|
|
||||||
|
```r
|
||||||
|
# From last release to current
|
||||||
|
usethis::use_tidy_thanks("owner/repo")
|
||||||
|
|
||||||
|
# From specific tag/SHA
|
||||||
|
usethis::use_tidy_thanks("owner/repo", from = "v1.0.0")
|
||||||
|
```
|
||||||
|
|
||||||
|
This generates properly formatted markdown for the contributor list that can be included verbatim.
|
||||||
|
|
||||||
|
## Transforming NEWS to Blog Content
|
||||||
|
|
||||||
|
When converting NEWS.md entries to blog post format:
|
||||||
|
|
||||||
|
1. **Expand context**: Technical bullets become paragraphs explaining why changes matter
|
||||||
|
2. **Add examples**: Include code demonstrating new features or changes
|
||||||
|
3. **Group thematically**: Combine scattered NEWS items into coherent sections
|
||||||
|
4. **Use conversational tone**: Transform terse bullets into readable prose
|
||||||
|
5. **Link proactively**: Add links to relevant documentation and resources
|
||||||
|
6. **Focus on user impact**: Explain how changes affect typical usage
|
||||||
|
7. **Highlight breaking changes**: Make migration paths clear and prominent
|
||||||
|
|
||||||
|
## Release Notes Link
|
||||||
|
|
||||||
|
Always include a link to full release notes:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
You can see a full list of changes in the [release notes](url).
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows readers to find exhaustive details while keeping the blog post focused and readable.
|
||||||
606
skills/release-post/references/shiny-formatting.md
Normal file
606
skills/release-post/references/shiny-formatting.md
Normal file
@@ -0,0 +1,606 @@
|
|||||||
|
# Shiny Blog Formatting Conventions
|
||||||
|
|
||||||
|
Shiny-specific formatting requirements for blog posts on shiny.posit.co. These conventions are for the Quarto-based Shiny blog.
|
||||||
|
|
||||||
|
## Frontmatter Format
|
||||||
|
|
||||||
|
Shiny blog posts use Quarto YAML frontmatter with this structure:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: Package Name Version
|
||||||
|
description: &desc |
|
||||||
|
Brief description of the package and release.
|
||||||
|
author: "Author Name"
|
||||||
|
date: "YYYY-MM-DD"
|
||||||
|
|
||||||
|
image: &img feature.png
|
||||||
|
|
||||||
|
open-graph:
|
||||||
|
image: *img
|
||||||
|
description: *desc
|
||||||
|
twitter-card:
|
||||||
|
image: *img
|
||||||
|
description: *desc
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required Fields
|
||||||
|
|
||||||
|
- **`title`**: Display title (no specific format required, flexible)
|
||||||
|
- Can be: `"packagename version"`, `"Package Name x.y.z"`, or descriptive
|
||||||
|
- Examples:
|
||||||
|
- `"shinyswatch 0.7.0"`
|
||||||
|
- `"Reintroducing the Shiny Extension for VS Code"`
|
||||||
|
- `"Branded theming for Shiny for Python apps"`
|
||||||
|
- **`description`**: Brief summary with YAML anchor for reuse
|
||||||
|
- Use `&desc` anchor and `|` for multi-line
|
||||||
|
- Reuse in social media cards with `*desc`
|
||||||
|
- **`author`**: Author name in quotes (can be single string or array)
|
||||||
|
- Single: `"Garrick Aden-Buie"`
|
||||||
|
- Multiple: `["Author One", "Author Two"]`
|
||||||
|
- **`date`**: ISO format in quotes `"YYYY-MM-DD"`
|
||||||
|
- **`image`**: Path to featured image (relative to post directory)
|
||||||
|
|
||||||
|
### Social Media Cards
|
||||||
|
|
||||||
|
Use YAML anchors to avoid repeating the description:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
description: &desc |
|
||||||
|
Your description here that will be reused.
|
||||||
|
|
||||||
|
open-graph:
|
||||||
|
description: *desc
|
||||||
|
twitter-card:
|
||||||
|
description: *desc
|
||||||
|
```
|
||||||
|
|
||||||
|
The `&desc` creates an anchor, and `*desc` references it.
|
||||||
|
|
||||||
|
### Optional But Common Fields
|
||||||
|
|
||||||
|
- **`filters`**: Quarto filters to use
|
||||||
|
- `shinylive` - For embedding Shinylive apps
|
||||||
|
- `line-highlight` - For highlighting specific lines
|
||||||
|
- **`engine`**: Quarto engine (`knitr`, `markdown`, `jupyter`)
|
||||||
|
- **`freeze`**: Set to `true` if the post includes *any* computational output
|
||||||
|
- **`format`**: HTML format options
|
||||||
|
- `code-link: true` - Enable code linking
|
||||||
|
- `anchor-sections: true` - Enable section anchors
|
||||||
|
- `reference-location: document` or `section` - Where to place footnotes
|
||||||
|
- **`code-annotations`**: Set to `hover` for hover annotations
|
||||||
|
- **`editor`**: Editor options like `render-on-save: true`
|
||||||
|
|
||||||
|
### Image Options
|
||||||
|
|
||||||
|
Additional image control fields:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
image: feature.svg
|
||||||
|
imagealt: "Alternative text for image"
|
||||||
|
image-header-disable: true # Don't show image in header
|
||||||
|
```
|
||||||
|
|
||||||
|
### What's NOT Included
|
||||||
|
|
||||||
|
Unlike Tidyverse posts, Shiny posts do **not** include:
|
||||||
|
|
||||||
|
- `output: hugodown::hugo_document`
|
||||||
|
- `slug` (filename determines URL)
|
||||||
|
- `photo.url` and `photo.author` (different image structure)
|
||||||
|
- Consistent `categories` field (optional, varies by post)
|
||||||
|
|
||||||
|
## Title Format
|
||||||
|
|
||||||
|
The main title can be flexible:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# packagename version
|
||||||
|
```
|
||||||
|
|
||||||
|
Or more descriptive:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Reintroducing the Shiny Extension for VS Code
|
||||||
|
```
|
||||||
|
|
||||||
|
There's less rigid formatting for titles in Shiny posts.
|
||||||
|
|
||||||
|
## Lead Paragraphs
|
||||||
|
|
||||||
|
Shiny posts may use a lead paragraph div for emphasis:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: lead
|
||||||
|
**We're excited to announce the new Shiny extension for VS Code!**
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a larger, emphasized opening paragraph.
|
||||||
|
|
||||||
|
## Code Formatting
|
||||||
|
|
||||||
|
### For Python Packages
|
||||||
|
|
||||||
|
Use bash code blocks for installation:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```bash
|
||||||
|
pip install packagename
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
With extras:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```bash
|
||||||
|
pip install "packagename[extra]"
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
### For R Packages
|
||||||
|
|
||||||
|
Use R code blocks:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```r
|
||||||
|
install.packages("packagename")
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
For multiple packages:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```r
|
||||||
|
install.packages(c("shiny", "bslib"))
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
### Code Block Attributes
|
||||||
|
|
||||||
|
Shiny posts use Quarto code block attributes:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```{.python filename="app.py"}
|
||||||
|
from shiny import App
|
||||||
|
|
||||||
|
# code here
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```{r install-bslib}
|
||||||
|
#| eval: false
|
||||||
|
install.packages("bslib")
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
### Line Highlighting
|
||||||
|
|
||||||
|
Use `# <<` comments to highlight lines (requires `line-highlight` filter):
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```{.python filename="app.py"}
|
||||||
|
from shiny.express import ui
|
||||||
|
import shinyswatch
|
||||||
|
|
||||||
|
ui.page_opts(theme=shinyswatch.theme.darkly) # <<
|
||||||
|
|
||||||
|
# rest of code...
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
### Code Annotations
|
||||||
|
|
||||||
|
With `code-annotations: hover` in frontmatter, you can add annotations:
|
||||||
|
|
||||||
|
```python
|
||||||
|
result = some_function() # <1>
|
||||||
|
```
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
1. This annotation explains the line above
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tabsets for Multiple Variants
|
||||||
|
|
||||||
|
Shiny posts frequently use tabsets to show Express vs Core mode or Python vs R:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
::: {.panel-tabset .shiny-mode-tabset group="shiny-app-mode"}
|
||||||
|
#### Express
|
||||||
|
|
||||||
|
```{.python filename="app.py"}
|
||||||
|
from shiny.express import ui
|
||||||
|
# Express code
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Core
|
||||||
|
|
||||||
|
```{.python filename="app.py"}
|
||||||
|
from shiny import ui
|
||||||
|
# Core code
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
````
|
||||||
|
|
||||||
|
### Nested Tabsets
|
||||||
|
|
||||||
|
You can nest tabsets for Before/After within Express/Core:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
::: {.panel-tabset group="shiny-app-mode"}
|
||||||
|
#### Express
|
||||||
|
|
||||||
|
::: {.panel-tabset}
|
||||||
|
##### Before
|
||||||
|
|
||||||
|
```python
|
||||||
|
# old code
|
||||||
|
```
|
||||||
|
|
||||||
|
##### After
|
||||||
|
|
||||||
|
```python
|
||||||
|
# new code
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Core
|
||||||
|
|
||||||
|
::: {.panel-tabset}
|
||||||
|
##### Before
|
||||||
|
|
||||||
|
```python
|
||||||
|
# old code
|
||||||
|
```
|
||||||
|
|
||||||
|
##### After
|
||||||
|
|
||||||
|
```python
|
||||||
|
# new code
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
:::
|
||||||
|
````
|
||||||
|
|
||||||
|
## Callouts
|
||||||
|
|
||||||
|
Quarto callouts for notes, tips, warnings:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: {.callout-tip title="Writing brand.yml with the help of an LLM"}
|
||||||
|
We know that writing YAML isn't everyone's cup of tea!
|
||||||
|
...
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
Types: `note`, `tip`, `warning`, `caution`, `important`
|
||||||
|
|
||||||
|
## Embedded Media
|
||||||
|
|
||||||
|
### Videos
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
::: column-page
|
||||||
|
```{=html}
|
||||||
|
<video controls>
|
||||||
|
<source src="videos/demo.webm" type="video/webm">
|
||||||
|
<source src="videos/demo.mp4" type="video/mp4">
|
||||||
|
</video>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
````
|
||||||
|
|
||||||
|
### Images with Attributes
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
{.shadow}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or with more attributes:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
{fig-alt="Detailed alt text" fig-align="center" width="100%"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Shinylive Examples
|
||||||
|
|
||||||
|
With the `shinylive` filter, you can embed live examples:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```{shinylive-python}
|
||||||
|
#| standalone: true
|
||||||
|
#| components: [editor, viewer]
|
||||||
|
|
||||||
|
## file: app.py
|
||||||
|
from shiny.express import input, render, ui
|
||||||
|
|
||||||
|
# App code here
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
Or link to examples:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
We've added a [complete branded theming example](https://shinylive.io/py/examples/#branded-theming) to shinylive.io.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Acknowledgements Section
|
||||||
|
|
||||||
|
Less consistent in Shiny posts. When present, variations include:
|
||||||
|
|
||||||
|
### Variation 1: Simple Thanks
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Thanks!
|
||||||
|
|
||||||
|
Thank you for trying out the Shiny extension for VS Code!
|
||||||
|
If you find it helpful, please rate the extension on [the marketplace][Shiny extension].
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variation 2: Multiple Package Releases
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Release notes
|
||||||
|
|
||||||
|
**Big shout out to everyone involved!** 💙
|
||||||
|
We'd want to extend a huge thank you to everyone who contributed pull requests, bug reports and feature requests.
|
||||||
|
|
||||||
|
#### bslib [v0.7.0](https://rstudio.github.io/bslib/news/index.html#bslib-070)
|
||||||
|
|
||||||
|
[List of contributors]
|
||||||
|
|
||||||
|
#### shiny [v1.8.1](https://shiny.posit.co/r/reference/shiny/1.8.1/upgrade.html)
|
||||||
|
|
||||||
|
[List of contributors]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variation 3: Omitted
|
||||||
|
|
||||||
|
Some Shiny posts don't include acknowledgements, especially for announcements of tools rather than package releases.
|
||||||
|
|
||||||
|
### When Acknowledgements Are Included
|
||||||
|
|
||||||
|
Use similar format to Tidyverse:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
We'd like to thank everyone who contributed to this release:
|
||||||
|
|
||||||
|
[@user1](https://github.com/user1), [@user2](https://github.com/user2), and [@user3](https://github.com/user3).
|
||||||
|
```
|
||||||
|
|
||||||
|
Or just reference the generator in code:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
```{r}
|
||||||
|
#| echo: false
|
||||||
|
#| eval: false
|
||||||
|
usethis::use_tidy_thanks("rstudio/bslib", from = "v0.6.1")
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
## CSS Customization
|
||||||
|
|
||||||
|
Shiny posts may include custom CSS in HTML blocks:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```{=html}
|
||||||
|
<style>
|
||||||
|
img { border-radius: 8px; }
|
||||||
|
video {
|
||||||
|
max-width: 100%;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
## Column Layouts
|
||||||
|
|
||||||
|
Use Quarto's column classes for wider content:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: column-page
|
||||||
|
[Wide content here]
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: column-body-outset
|
||||||
|
[Slightly wider content]
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
## Footnotes
|
||||||
|
|
||||||
|
Use standard markdown footnotes:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Text with a footnote[^footnote-key].
|
||||||
|
|
||||||
|
[^footnote-key]: This is the footnote text.
|
||||||
|
```
|
||||||
|
|
||||||
|
With `reference-location: document` or `section` in frontmatter to control placement.
|
||||||
|
|
||||||
|
## Links and References
|
||||||
|
|
||||||
|
Define link references at the top or bottom of the file:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[brand.yml]: https://posit-dev.github.io/brand-yml
|
||||||
|
[quarto]: https://quarto.org
|
||||||
|
[shiny]: https://shiny.posit.co
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use them inline:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
We're excited about [brand.yml] support!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multi-Language Support (R and Python)
|
||||||
|
|
||||||
|
The Shiny blog often covers packages released for both R and Python (e.g., shiny, shinychat). Unlike Tidyverse posts which are language-specific, Shiny posts should show examples in both languages using Quarto tabsets.
|
||||||
|
|
||||||
|
### Use Tabsets Consistently
|
||||||
|
|
||||||
|
Every code example should include both R and Python variants using Quarto tabsets:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: {.panel-tabset group="language"}
|
||||||
|
## R
|
||||||
|
|
||||||
|
```r
|
||||||
|
# R code here
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Python code here
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
**Guidelines:**
|
||||||
|
- Use `group="language"` to sync all language tabsets on the page
|
||||||
|
- Provide equivalent functionality in both languages
|
||||||
|
- Don't show R-only or Python-only examples unless the feature is language-specific
|
||||||
|
- Keep examples parallel—if the R example shows 5 lines, the Python example should be similar
|
||||||
|
|
||||||
|
### Installation Instructions
|
||||||
|
|
||||||
|
Always show installation for both languages at the start of the post:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: {.panel-tabset group="language"}
|
||||||
|
## R
|
||||||
|
|
||||||
|
```r
|
||||||
|
install.packages("packagename")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install packagename
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### Language-Specific Features
|
||||||
|
|
||||||
|
When features differ between languages, be explicit about the differences:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: {.panel-tabset group="language"}
|
||||||
|
## R
|
||||||
|
|
||||||
|
In R, use `tool_annotations()` to customize display:
|
||||||
|
|
||||||
|
```r
|
||||||
|
tool_annotations(title = "My Tool", icon = bsicons::bs_icon("star"))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python
|
||||||
|
|
||||||
|
In Python, use the `._display` attribute:
|
||||||
|
|
||||||
|
```python
|
||||||
|
my_tool._display = {"title": "My Tool", "icon": "star"}
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### Version Information
|
||||||
|
|
||||||
|
Package versions often differ between R and Python. Be explicit:
|
||||||
|
|
||||||
|
- "Available in shinychat for R (v0.3.0) and shinychat for Python (v0.2.0 or later)"
|
||||||
|
- Link to both language-specific documentation
|
||||||
|
- Include separate release notes links:
|
||||||
|
```markdown
|
||||||
|
You can see the full list of changes in the [R release notes](url) and [Python release notes](url).
|
||||||
|
```
|
||||||
|
|
||||||
|
### When to Use Multi-Language Tabsets
|
||||||
|
|
||||||
|
- **Always use** for packages that have both R and Python versions (shiny, shinychat, querychat, etc.)
|
||||||
|
- **Don't use** for Python-only packages (shinyswatch) or R-only packages
|
||||||
|
- **Don't use** for Tidyverse blog posts (which are built with hugodown/Hugo, not Quarto)
|
||||||
|
|
||||||
|
## Example Complete Frontmatter
|
||||||
|
|
||||||
|
### Python Package
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: shinyswatch 0.7.0
|
||||||
|
description: &desc Customizable shinyswatch themes and an improved theme picker round out shinyswatch v0.7.0.
|
||||||
|
author: "Garrick Aden-Buie"
|
||||||
|
date: "2024-07-19"
|
||||||
|
|
||||||
|
image: feature.jpg
|
||||||
|
|
||||||
|
open-graph:
|
||||||
|
image: feature.jpg
|
||||||
|
description: *desc
|
||||||
|
twitter-card:
|
||||||
|
image: feature.png
|
||||||
|
description: *desc
|
||||||
|
|
||||||
|
filters:
|
||||||
|
- line-highlight
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
### R Package with Full Options
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: "Shiny for R updates: Extended tasks, JavaScript errors, and many bslib improvements"
|
||||||
|
description: &desc |
|
||||||
|
An overview of recent Shiny for R updates, including extended tasks, JavaScript errors, and many bslib improvements.
|
||||||
|
author:
|
||||||
|
- Carson Sievert
|
||||||
|
date: "2024-03-27"
|
||||||
|
|
||||||
|
image: feature.png
|
||||||
|
|
||||||
|
open-graph:
|
||||||
|
image: feature.png
|
||||||
|
description: *desc
|
||||||
|
twitter-card:
|
||||||
|
image: feature.png
|
||||||
|
description: *desc
|
||||||
|
|
||||||
|
editor:
|
||||||
|
render-on-save: true
|
||||||
|
|
||||||
|
engine: knitr
|
||||||
|
|
||||||
|
filters:
|
||||||
|
- shinylive
|
||||||
|
|
||||||
|
freeze: true
|
||||||
|
|
||||||
|
format:
|
||||||
|
html:
|
||||||
|
code-link: true
|
||||||
|
anchor-sections: true
|
||||||
|
reference-location: section
|
||||||
|
|
||||||
|
code-annotations: hover
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples of Well-Formatted Posts
|
||||||
|
|
||||||
|
Reference these posts for formatting examples:
|
||||||
|
- [shinyswatch 0.7.0](https://shiny.posit.co/blog/posts/shinyswatch-0.7.0/)
|
||||||
|
- [Shiny Extension for VS Code 1.0.0](https://shiny.posit.co/blog/posts/shiny-vscode-1.0.0/)
|
||||||
|
- [Shiny for R 1.8.1](https://shiny.posit.co/blog/posts/shiny-r-1.8.1/)
|
||||||
|
- [Branded theming for Shiny for Python](https://shiny.posit.co/blog/posts/shiny-python-1.2-brand-yml/)
|
||||||
275
skills/release-post/references/tidyverse-formatting.md
Normal file
275
skills/release-post/references/tidyverse-formatting.md
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
# Tidyverse Blog Formatting Conventions
|
||||||
|
|
||||||
|
Tidyverse-specific formatting requirements for blog posts on tidyverse.org. These conventions are for the hugodown-based Tidyverse blog.
|
||||||
|
|
||||||
|
## Workflow for tidyverse.org Blog
|
||||||
|
|
||||||
|
When creating a blog post for the official `tidyverse/tidyverse.org` repository, follow these steps:
|
||||||
|
|
||||||
|
1. **Install hugodown** (if not already installed):
|
||||||
|
```r
|
||||||
|
pak::pkg_install("r-lib/hugodown")
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Create a new post**:
|
||||||
|
```r
|
||||||
|
hugodown::use_tidy_post("short-name")
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates `content/blog/short-name/` containing an `index.Rmd` file.
|
||||||
|
|
||||||
|
Common patterns for `"short-name"`:
|
||||||
|
- Package release: `lifecycle-1-0-0`, `parsnip-0-1-2`
|
||||||
|
- Package release with specific topic: `dplyr-1-0-0-rowwise`, `parsnip-adjacent`, `dplyr-1-0-4-if-any`
|
||||||
|
- Topic only: `self-cleaning-test-fixtures`, `taking-control-of-plot-scaling`
|
||||||
|
|
||||||
|
3. **Write and knit**:
|
||||||
|
- Edit the generated `index.Rmd` file
|
||||||
|
- Knit `index.Rmd` to generate `index.md`
|
||||||
|
- Note: `.Rmd` files are only rendered when you explicitly knit them
|
||||||
|
|
||||||
|
4. **Preview the site**:
|
||||||
|
```r
|
||||||
|
hugodown::hugo_start()
|
||||||
|
```
|
||||||
|
This runs once per session and continues in the background to turn `.md` into `.html`.
|
||||||
|
|
||||||
|
5. **Check for outdated files** (if concerned):
|
||||||
|
```r
|
||||||
|
hugodown::site_outdated()
|
||||||
|
```
|
||||||
|
Lists all `.Rmd`s that need to be re-rendered.
|
||||||
|
|
||||||
|
6. **Add a photo**:
|
||||||
|
Every blog post must be accompanied by a photo. If you don't have one in mind, try:
|
||||||
|
- <https://unsplash.com>
|
||||||
|
- <https://pexels.com>
|
||||||
|
- Jenny Bryan's [free photo](https://github.com/jennybc/free-photos) link collection
|
||||||
|
|
||||||
|
7. **Submit PR**:
|
||||||
|
- Every PR gets an automatic live preview via Netlify
|
||||||
|
- Once merged, the preview becomes the live site
|
||||||
|
|
||||||
|
### Important Notes
|
||||||
|
|
||||||
|
- The site uses **hugodown** (not blogdown), which separates building into two steps:
|
||||||
|
- hugodown generates `.md` from `.Rmd`
|
||||||
|
- hugo generates `.html` from `.md`
|
||||||
|
- Use `.Rmd` files (not `.Rmarkdown`)
|
||||||
|
- Output should be `output: hugodown::hugo_document`
|
||||||
|
- If updating an old post to use hugodown:
|
||||||
|
- Rename from `.Rmarkdown` to `.Rmd`
|
||||||
|
- Delete the `.markdown` file
|
||||||
|
- Set `output: hugodown::hugo_document` in YAML metadata
|
||||||
|
|
||||||
|
### For Additional Context
|
||||||
|
|
||||||
|
If you need more details about the workflow or encounter issues, consult the `README.md` in the `tidyverse/tidyverse.org` repository.
|
||||||
|
|
||||||
|
## Frontmatter Format
|
||||||
|
|
||||||
|
Tidyverse blog posts use YAML frontmatter with this structure:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
output: hugodown::hugo_document
|
||||||
|
slug: package-name-version
|
||||||
|
title: package-name version
|
||||||
|
date: YYYY-MM-DD
|
||||||
|
author: Author Name
|
||||||
|
description: >
|
||||||
|
Brief description of the package and release
|
||||||
|
photo:
|
||||||
|
url: https://unsplash.com/photos/photo-id
|
||||||
|
author: Photographer Name
|
||||||
|
categories: [package-name]
|
||||||
|
tags: [package-name, category]
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required Fields
|
||||||
|
|
||||||
|
- **`output`**: Always `hugodown::hugo_document`
|
||||||
|
- **`slug`**: URL slug using hyphens
|
||||||
|
- Format: `packagename-x-y-z` (e.g., `ellmer-0-4-0`)
|
||||||
|
- Replace dots with hyphens in version numbers
|
||||||
|
- **`title`**: Display title with spaces
|
||||||
|
- Format: `packagename x.y.z` (e.g., `ellmer 0.4.0`)
|
||||||
|
- **`date`**: ISO format `YYYY-MM-DD`
|
||||||
|
- **`author`**: Full name of primary author
|
||||||
|
- **`description`**: Brief summary (can use `>` for multi-line)
|
||||||
|
- **`photo`**: Featured image with attribution
|
||||||
|
- `url`: Full URL to image (often Unsplash)
|
||||||
|
- `author`: Photographer name for attribution
|
||||||
|
- **`categories`**: Array with package name
|
||||||
|
- **`tags`**: Array with package name and related tags
|
||||||
|
|
||||||
|
### Slug vs Title Convention
|
||||||
|
|
||||||
|
The slug is used in URLs and must be URL-safe:
|
||||||
|
- Slug: `purrr-1-2-0` (hyphens, no dots)
|
||||||
|
- Title: `purrr 1.2.0` (space, dots in version)
|
||||||
|
|
||||||
|
### Image Attribution
|
||||||
|
|
||||||
|
Featured images are typically from Unsplash with proper photographer attribution:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
photo:
|
||||||
|
url: https://unsplash.com/photos/abc123
|
||||||
|
author: John Doe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Title Format
|
||||||
|
|
||||||
|
The main title uses a simple format with space between package name and version:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# packagename 1.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
No "released" or "version" prefix. Just the package name and version number.
|
||||||
|
|
||||||
|
## Code Formatting
|
||||||
|
|
||||||
|
### Language Identifiers
|
||||||
|
|
||||||
|
Use triple backticks with `r` language identifier for R code:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```r
|
||||||
|
library(packagename)
|
||||||
|
|
||||||
|
result <- function_name(
|
||||||
|
arg1 = "value",
|
||||||
|
arg2 = TRUE
|
||||||
|
)
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
For installation:
|
||||||
|
````markdown
|
||||||
|
```r
|
||||||
|
install.packages("packagename")
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
### Inline Code Elements
|
||||||
|
|
||||||
|
- Function names: `` `function()` ``
|
||||||
|
- Packages: `` `{packagename}` `` when emphasizing it's a package
|
||||||
|
- Arguments: `` `arg = value` ``
|
||||||
|
- Values: `` `NULL` ``, `` `TRUE` ``, `` `"string"` ``
|
||||||
|
|
||||||
|
### Function Links
|
||||||
|
|
||||||
|
When linking to function documentation, use markdown links:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[`function_name()`](https://url-to-docs)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Section Structure
|
||||||
|
|
||||||
|
### Lifecycle Section Format
|
||||||
|
|
||||||
|
When including lifecycle changes, use this structure:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Lifecycle changes
|
||||||
|
|
||||||
|
* **Fully removed** after 5+ years of deprecation:
|
||||||
|
* `function1()` - use `replacement1()` instead
|
||||||
|
* `function2()` - use `replacement2()` instead
|
||||||
|
|
||||||
|
* **Newly deprecated** (soft-deprecation):
|
||||||
|
* `function3()` is superseded by `function4()`
|
||||||
|
* `function5()` is no longer recommended
|
||||||
|
|
||||||
|
* **Breaking changes**:
|
||||||
|
* Description of what changed and why
|
||||||
|
```
|
||||||
|
|
||||||
|
Use bold for the lifecycle stage labels.
|
||||||
|
|
||||||
|
### Feature Sections
|
||||||
|
|
||||||
|
Use sentence case in headings:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Easier `in_parallel()`
|
||||||
|
|
||||||
|
[Description of the feature...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Include function names in backticks when they're part of the heading.
|
||||||
|
|
||||||
|
## Acknowledgements Section
|
||||||
|
|
||||||
|
Always include as the final section:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
A big thank you to all the folks who helped make this release happen:
|
||||||
|
|
||||||
|
[@username1](https://github.com/username1), [@username2](https://github.com/username2), [@username3](https://github.com/username3), and [@username4](https://github.com/username4).
|
||||||
|
```
|
||||||
|
|
||||||
|
### Formatting Rules
|
||||||
|
|
||||||
|
- Single paragraph format (not bulleted list)
|
||||||
|
- GitHub handles as markdown links
|
||||||
|
- Alphabetical order
|
||||||
|
- Comma-separated with "and" before the last name
|
||||||
|
- Period at the end
|
||||||
|
|
||||||
|
### Generating the List
|
||||||
|
|
||||||
|
Use `usethis::use_tidy_thanks()`:
|
||||||
|
|
||||||
|
```r
|
||||||
|
# Fetch contributors since last release
|
||||||
|
usethis::use_tidy_thanks("tidyverse/packagename")
|
||||||
|
|
||||||
|
# Or from specific tag
|
||||||
|
usethis::use_tidy_thanks("tidyverse/packagename", from = "v1.0.0")
|
||||||
|
```
|
||||||
|
|
||||||
|
This function outputs properly formatted markdown that can be copied directly into the blog post.
|
||||||
|
|
||||||
|
## Release Notes Link
|
||||||
|
|
||||||
|
Include a link to the full release notes (typically on pkgdown site):
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
You can see a full list of changes in the [release notes](https://packagename.tidyverse.org/news/).
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example Complete Frontmatter
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
output: hugodown::hugo_document
|
||||||
|
slug: purrr-1-2-0
|
||||||
|
title: purrr 1.2.0
|
||||||
|
date: 2025-11-04
|
||||||
|
author: Hadley Wickham
|
||||||
|
description: >
|
||||||
|
purrr 1.2.0 includes deprecations and minor enhancements to
|
||||||
|
functional programming tools in R.
|
||||||
|
photo:
|
||||||
|
url: https://unsplash.com/photos/xyz789
|
||||||
|
author: Jane Photographer
|
||||||
|
categories: [purrr]
|
||||||
|
tags: [purrr, tidyverse]
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples of Well-Formatted Posts
|
||||||
|
|
||||||
|
Reference these posts for formatting examples:
|
||||||
|
- [pkgdown 2.2.0](https://www.tidyverse.org/blog/2025/11/pkgdown-2-2-0/)
|
||||||
|
- [testthat 3.3.0](https://www.tidyverse.org/blog/2025/11/testthat-3-3-0/)
|
||||||
|
- [purrr 1.2.0](https://www.tidyverse.org/blog/2025/11/purrr-1-2-0/)
|
||||||
|
- [ellmer 0.4.0](https://www.tidyverse.org/blog/2025/11/ellmer-0-4-0/)
|
||||||
48
skills/release-post/scripts/get_contributors.R
Normal file
48
skills/release-post/scripts/get_contributors.R
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env Rscript
|
||||||
|
# Fetch contributors for a package release using usethis::use_tidy_thanks()
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# Rscript get_contributors.R <repo> [<from>]
|
||||||
|
#
|
||||||
|
# Arguments:
|
||||||
|
# repo: GitHub repository in "owner/repo" format (e.g., "tidyverse/dplyr")
|
||||||
|
# from: Optional git ref (tag/SHA) to use as the starting point
|
||||||
|
# If omitted, uses the previous release
|
||||||
|
#
|
||||||
|
# Output:
|
||||||
|
# Markdown-formatted list of contributors suitable for blog post acknowledgments
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# Rscript get_contributors.R "tidyverse/dplyr"
|
||||||
|
# Rscript get_contributors.R "tidyverse/dplyr" "v1.0.0"
|
||||||
|
|
||||||
|
args <- commandArgs(trailingOnly = TRUE)
|
||||||
|
|
||||||
|
if (length(args) == 0) {
|
||||||
|
cat("Error: Repository argument required\n")
|
||||||
|
cat("Usage: Rscript get_contributors.R <repo> [<from>]\n")
|
||||||
|
cat("Example: Rscript get_contributors.R 'tidyverse/dplyr'\n")
|
||||||
|
quit(status = 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo <- args[1]
|
||||||
|
from <- if (length(args) >= 2) args[2] else NULL
|
||||||
|
|
||||||
|
# Check if usethis is installed
|
||||||
|
if (!requireNamespace("usethis", quietly = TRUE)) {
|
||||||
|
cat("Error: usethis package is not installed\n")
|
||||||
|
cat("Install it with: install.packages('usethis')\n")
|
||||||
|
quit(status = 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch contributors
|
||||||
|
cat("Fetching contributors for", repo, "...\n\n")
|
||||||
|
|
||||||
|
if (is.null(from)) {
|
||||||
|
contributors <- usethis::use_tidy_thanks(repo)
|
||||||
|
} else {
|
||||||
|
contributors <- usethis::use_tidy_thanks(repo, from = from)
|
||||||
|
}
|
||||||
|
|
||||||
|
# The function prints the result to console
|
||||||
|
# No additional output needed
|
||||||
Reference in New Issue
Block a user