Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .frontmatter/database/pinnedItemsDb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
92 changes: 92 additions & 0 deletions .frontmatter/database/taxonomyDb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"taxonomy": {
"tags": [],
"categories": [
"Announcements",
"Books",
"DevOps",
"Events",
"Graph",
"In Case You Missed It",
"News",
"PowerShell Summit",
"PowerShell for Admins",
"PowerShell for Developers",
"Scripting Games",
"Tips and Tricks",
"Tools",
"Training",
"Tutorials"
]
},
"customTaxonomy": [
{
"id": "authors",
"options": [
"Aaron Jensen",
"Adam Bertram",
"Adam Platt",
"Alex Aymonier",
"Art Beane",
"Bartek Bielawski",
"Bjorn Houben",
"Boe Prox",
"Brian Bourque",
"Carlo Mancini",
"Chris Martin",
"Cole McDonald",
"Colyn Via",
"Darren Mar-Elia",
"David Jones",
"David Wilson",
"Don Jones",
"Eli Hess",
"Enrique Puig",
"Eric Brookman (scriptingcaveman)",
"Glenn Sizemore",
"Graham Beer",
"Greg Altman",
"Greg Tate",
"Jaap Brasser",
"Jacob Benson",
"Jacob Moran",
"James Petty",
"Jeffery Hicks",
"Joel Newton",
"John Mello",
"Jonas Sommer Nielsen",
"Jonathan Medd",
"Jonathan Walz",
"June Blender",
"Keith Hill",
"Kirk Munro",
"Liam Kemp",
"Mark Kraus (markekraus)",
"Mark Roloff",
"Mark Wragg",
"Matt Laird",
"Matthew Hodgkins",
"Mike F Robbins",
"Mike Kanakos",
"Mike Roberts",
"Missy Januszko",
"Nathaniel Webb (ArtisanByteCrafter)",
"Nick Rimmer",
"Richard Siddaway",
"Robin Dadswell",
"Stephen Moore",
"Stephen Owen",
"Steve Parankewich",
"Steven Murawski",
"Sunny Chakraborty",
"Terri Donahue",
"Thomas Malkewitz",
"Thomas Rayner, MVP",
"Tim Curwick",
"Timothy Warner",
"WeiYen Tan",
"Will Anderson"
]
}
]
}
42 changes: 42 additions & 0 deletions .github/ISSUE_TEMPLATE/guest-blog-post.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,48 @@ body:
validations:
required: true

- type: input
id: description
attributes:
label: Description
description: "A 1-2 sentence summary used for SEO, social cards, and the article list."
placeholder: "Learn how to enable and customize PSReadLine predictive IntelliSense for a faster console."
validations:
required: true

- type: dropdown
id: category
attributes:
label: Category
description: "Pick the category that best fits your article."
options:
- "Announcements"
- "Books"
- "DevOps"
- "Events"
- "Graph"
- "In Case You Missed It"
- "News"
- "PowerShell Summit"
- "PowerShell for Admins"
- "PowerShell for Developers"
- "Scripting Games"
- "Tips and Tricks"
- "Tools"
- "Training"
- "Tutorials"
validations:
required: true

- type: input
id: tags
attributes:
label: Tags (optional)
description: "Comma-separated keywords, e.g. psreadline, console, productivity."
placeholder: "psreadline, console, productivity"
validations:
required: false

- type: textarea
id: summary
attributes:
Expand Down
128 changes: 128 additions & 0 deletions .github/workflows/add-article.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
name: Add Guest Article

on:
issues:
types: [labeled]

jobs:
add-article:
if: |
github.event.label.name == 'approved' &&
contains(github.event.issue.labels.*.name, 'article')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Parse issue and create article content file
id: parse
env:
ISSUE_BODY: ${{ github.event.issue.body }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
python3 - <<'PYEOF'
import os, re, datetime, yaml

# Normalize line endings — issue bodies can contain CRLF.
body = os.environ['ISSUE_BODY'].replace('\r\n', '\n').replace('\r', '\n')

def strip_html(s):
# Strip raw HTML from scalar front matter values (matches add-event.yml).
return re.sub(r'<[^>]+>', '', s).strip()

def field(label):
m = re.search(rf'### {re.escape(label)}\s+(.+?)(?=\n###|\Z)', body, re.DOTALL)
if not m:
return ''
val = m.group(1).strip()
return '' if val in ('_No response_', '') else val

title = strip_html(field('Article Title'))
author = strip_html(field('Author Name'))
description = strip_html(field('Description'))
category = strip_html(field('Category'))
tags_raw = strip_html(field('Tags (optional)'))
content = field('Article Content (Markdown)')

# The Article Content field is rendered as a ```markdown fenced block — unwrap it,
# tolerating surrounding whitespace/blank lines around the fences.
content = re.sub(r'^\s*```[a-zA-Z]*[ \t]*\n', '', content)
content = re.sub(r'\n```[ \t]*\s*$', '', content).strip()

if not title:
raise SystemExit('No article title found; aborting.')
if not content:
# A pitch with no draft — nothing to publish yet.
print('No article content provided (pitch only); skipping file creation.')
with open(os.environ['GITHUB_OUTPUT'], 'a') as out:
out.write('skip=true\n')
raise SystemExit(0)

tags = [t.strip() for t in re.split(r'[,\n]', tags_raw) if t.strip()]

today = datetime.datetime.now(datetime.timezone.utc)
date_str = today.strftime('%Y-%m-%dT%H:%M:%S+00:00')

slug = re.sub(r'[^a-z0-9]+', '-', title.lower()).strip('-')
if not slug:
# Title was only punctuation / non-ASCII — fall back to the issue number.
slug = f"article-{os.environ['ISSUE_NUMBER']}"
filename = f"{today.strftime('%Y-%m-%d')}-{slug}.md"

fm = {
'title': title,
'author': author,
'authors': [author] if author else [],
'date': date_str,
'description': description,
}
if category:
fm['categories'] = [category]
if tags:
fm['tags'] = tags

front = yaml.safe_dump(fm, default_flow_style=False, allow_unicode=True, sort_keys=False)
document = '---\n' + front + '---\n\n' + content + '\n'

filepath = f'content/articles/{filename}'
os.makedirs('content/articles', exist_ok=True)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(document)

with open(os.environ['GITHUB_OUTPUT'], 'a') as out:
out.write(f'skip=false\n')
out.write(f'slug={slug}\n')
out.write(f'filepath={filepath}\n')
out.write(f'article_title={title}\n')

print(f'Created {filepath}')
PYEOF

- name: Open PR
if: steps.parse.outputs.skip == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLUG: ${{ steps.parse.outputs.slug }}
FILEPATH: ${{ steps.parse.outputs.filepath }}
ARTICLE_TITLE: ${{ steps.parse.outputs.article_title }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
BRANCH="article/issue-${ISSUE_NUMBER}-${SLUG}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "$BRANCH"
git add "$FILEPATH"
git commit -m "Add article: ${ARTICLE_TITLE} (closes #${ISSUE_NUMBER})"
git push origin "$BRANCH"
gh pr create \
--title "Add article: ${ARTICLE_TITLE}" \
--body "Closes #${ISSUE_NUMBER}

Auto-generated from guest blog post submission. Please review front matter and content before merging." \
--base main \
--head "$BRANCH"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
public/

# Local Netlify folder
.netlify
7 changes: 7 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"recommendations": [
"eliostruyf.vscode-front-matter",
"davidanson.vscode-markdownlint",
"yzhang.markdown-all-in-one"
]
}
Comment thread
Copilot marked this conversation as resolved.
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ If you're not comfortable with Git, you can pitch or submit your article through
```yaml
---
title: "Your Article Title"
description: "A 1-2 sentence summary used for SEO, social cards, and the article list."
author: Your Name
authors:
- Your Name
Expand All @@ -41,6 +42,11 @@ If you're not comfortable with Git, you can pitch or submit your article through
Your article content in Markdown goes here.
```

> Tip: If you have the [Front Matter CMS](https://frontmatter.codes/) extension
> installed in VS Code, run **"Create content"** in the `content/articles`
> folder — it scaffolds the file name (`YYYY-MM-DD-slug.md`) and all of the
> front matter fields above for you.

5. Submit a pull request with a brief description of your article

### Writing Tips
Expand Down
11 changes: 11 additions & 0 deletions archetypes/articles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
description: ""
author: ""
authors:
- ""
date: '{{ .Date }}'
categories: []
tags: []
draft: true
---
8 changes: 8 additions & 0 deletions archetypes/authors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
description: ""
layout: "authors"
website: ""
twitter: ""
github: ""
---
8 changes: 8 additions & 0 deletions archetypes/calendar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
startDate: '{{ .Date | dateFormat "2006-01-02" }}'
endDate: ""
where: ""
externalUrl: ""
virtual: false
---
10 changes: 5 additions & 5 deletions archetypes/default.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
+++
date = '{{ .Date }}'
draft = true
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
+++
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
draft: true
---
10 changes: 10 additions & 0 deletions archetypes/podcast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
description: ""
author: ""
authors:
- ""
date: '{{ .Date }}'
podcast_url: ""
draft: true
---
Loading
Loading