Skip to content

Commit b072ade

Browse files
Merge pull request #8 from PowerShellWeb/JSON-LD-Init
JSON-LD Initial Release
2 parents 1542fd8 + c273577 commit b072ade

11 files changed

+770
-0
lines changed

.github/FUNDING.yml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: [StartAutomating]

.github/workflows/JSON-LD-Build.yml

+510
Large diffs are not rendered by default.

Build/GitHub/Jobs/JsonLD.psd1

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
@{
2+
"runs-on" = "ubuntu-latest"
3+
if = '${{ success() }}'
4+
steps = @(
5+
@{
6+
name = 'Check out repository'
7+
uses = 'actions/checkout@v2'
8+
},
9+
@{
10+
name = 'GitLogger'
11+
uses = 'GitLogging/GitLoggerAction@main'
12+
id = 'GitLogger'
13+
},
14+
@{
15+
name = 'Use PSSVG Action'
16+
uses = 'StartAutomating/PSSVG@main'
17+
id = 'PSSVG'
18+
},
19+
@{
20+
name = 'Use PipeScript Action'
21+
uses = 'StartAutomating/PipeScript@main'
22+
id = 'PipeScript'
23+
},
24+
'RunEZOut',
25+
'RunHelpOut',
26+
@{
27+
name = 'Use PSJekyll Action'
28+
uses = 'PowerShellWeb/PSJekyll@main'
29+
id = 'PSJekyll'
30+
}
31+
)
32+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@{
2+
name = 'PublishTestResults'
3+
uses = 'actions/upload-artifact@main'
4+
with = @{
5+
name = 'PesterResults'
6+
path = '**.TestResults.xml'
7+
}
8+
if = '${{always()}}'
9+
}
10+
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#requires -Module PSDevOps
2+
Import-BuildStep -SourcePath (
3+
Join-Path $PSScriptRoot 'GitHub'
4+
) -BuildSystem GitHubWorkflow
5+
6+
Push-Location ($PSScriptRoot | Split-Path)
7+
New-GitHubWorkflow -Name "JSON-LD Module Build" -On Push,
8+
PullRequest,
9+
Demand -Job TestPowerShellOnLinux,
10+
TagReleaseAndPublish, JsonLD -OutputPath .\.github\workflows\JSON-LD-Build.yml
11+
12+
Pop-Location

Commands/Get-JsonLD.ps1

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
function Get-JsonLD {
2+
<#
3+
.SYNOPSIS
4+
Gets JSON-LD data from a given URL.
5+
.DESCRIPTION
6+
Gets JSON Linked Data from a given URL.
7+
8+
This is a format used by many websites to provide structured data about their content.
9+
.EXAMPLE
10+
# Want to get information about a movie? Linked Data to the rescue!
11+
Get-JsonLD -Url https://www.imdb.com/title/tt0211915/
12+
.EXAMPLE
13+
# Want information about an article? Lots of news sites use this format.
14+
Get-JsonLD https://www.thebulwark.com/p/mahmoud-khalil-immigration-detention-first-amendment-free-speech-rights
15+
.EXAMPLE
16+
# Want to get information about a schema?
17+
jsonld https://schema.org/Movie
18+
# Get-JSONLD will output the contents of a `@Graph` object if no `@type` is found.
19+
#>
20+
[Alias('jsonLD','json-ld')]
21+
param(
22+
# The URL that may contain JSON-LD data
23+
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
24+
[Uri]
25+
$Url
26+
)
27+
28+
begin {
29+
$linkedDataRegex = [Regex]::new(@'
30+
(?<HTML_LinkedData>
31+
<script # Match <script tag
32+
\s{1,} # Then whitespace
33+
type= # Then the type= attribute (this regex will only match if it is first)
34+
[\"\'] # Double or Single Quotes
35+
application/ld\+json # The type that indicates linked data
36+
[\"\'] # Double or Single Quotes
37+
[^>]{0,} # Match anything until the end of the start tag
38+
\> # Match the end of the start tag
39+
(?<JsonContent>(?:.|\s){0,}?(?=\z|</script>)) # Anything until the end tag is JSONContent
40+
)
41+
'@, 'IgnoreCase,IgnorePatternWhitespace','00:00:00.1')
42+
}
43+
44+
process {
45+
$restResponse = Invoke-RestMethod -Uri $Url
46+
foreach ($match in $linkedDataRegex.Matches("$restResponse")) {
47+
foreach ($jsonObject in
48+
$match.Groups['JsonContent'].Value |
49+
ConvertFrom-Json
50+
) {
51+
if ($jsonObject.'@type') {
52+
$schemaType = $jsonObject.'@context',$jsonObject.'@type' -ne '' -join '/'
53+
$jsonObject.pstypenames.insert(0, $schemaType)
54+
$jsonObject
55+
} elseif ($jsonObject.'@graph') {
56+
foreach ($graphObject in $jsonObject.'@graph') {
57+
if ($graphObject.'@type') {
58+
$graphObject.pstypenames.insert(0, $graphObject.'@type')
59+
}
60+
$graphObject
61+
}
62+
} else {
63+
$jsonObject
64+
}
65+
66+
}
67+
}
68+
}
69+
}

JSON-LD.ps.psm1

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
$commandsPath = Join-Path $PSScriptRoot Commands
2+
[include('*-*')]$commandsPath
3+
4+
$myModule = $MyInvocation.MyCommand.ScriptBlock.Module
5+
$ExecutionContext.SessionState.PSVariable.Set($myModule.Name, $myModule)
6+
$myModule.pstypenames.insert(0, $myModule.Name)
7+
8+
New-PSDrive -Name $MyModule.Name -PSProvider FileSystem -Scope Global -Root $PSScriptRoot -ErrorAction Ignore
9+
10+
if ($home) {
11+
$MyModuleProfileDirectory = Join-Path ([Environment]::GetFolderPath("LocalApplicationData")) $MyModule.Name
12+
if (-not (Test-Path $MyModuleProfileDirectory)) {
13+
$null = New-Item -ItemType Directory -Path $MyModuleProfileDirectory -Force
14+
}
15+
New-PSDrive -Name "My$($MyModule.Name)" -PSProvider FileSystem -Scope Global -Root $MyModuleProfileDirectory -ErrorAction Ignore
16+
}
17+
18+
# Set a script variable of this, set to the module
19+
# (so all scripts in this scope default to the correct `$this`)
20+
$script:this = $myModule
21+
22+
#region Custom
23+
#endregion Custom
24+
25+
Export-ModuleMember -Alias * -Function * -Variable $myModule.Name
26+

JSON-LD.psd1

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@{
2+
RootModule = 'JSON-LD.psm1'
3+
ModuleVersion = '0.0.1'
4+
GUID = '4e65477c-012c-4077-87c7-3e07964636ce'
5+
Author = 'JamesBrundage'
6+
CompanyName = 'Start-Automating'
7+
Copyright = '(c) 2025 Start-Automating.'
8+
Description = 'Get JSON Linked Data with PowerShell'
9+
FunctionsToExport = 'Get-JsonLD'
10+
AliasesToExport = 'jsonLD', 'json-ld'
11+
PrivateData = @{
12+
PSData = @{
13+
# Tags applied to this module. These help with module discovery in online galleries.
14+
Tags = @('json-ld','SEO','Web','PowerShellWeb')
15+
# A URL to the license for this module.
16+
ProjectURI = 'https://github.com/PowerShellWeb/JSON-LD'
17+
LicenseURI = 'https://github.com/PowerShellWeb/JSON-LD/blob/main/LICENSE'
18+
ReleaseNotes = @'
19+
20+
> Like It? [Star It](https://github.com/PowerShellWeb/JSON-LD)
21+
> Love It? [Support It](https://github.com/sponsors/StartAutomating)
22+
23+
Get Linked Data from any page
24+
25+
## JSON-LD 0.0.1
26+
27+
* Initial Release of JSON-LD Module (#1)
28+
* `Get-JsonLD` gets linked data (#2)
29+
* `Get-JsonLD` is aliased to `jsonLD` and `json-ld`
30+
'@
31+
}
32+
}
33+
34+
}
35+

JSON-LD.psm1

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
$commandsPath = Join-Path $PSScriptRoot Commands
2+
:ToIncludeFiles foreach ($file in (Get-ChildItem -Path "$commandsPath" -Filter "*-*" -Recurse)) {
3+
if ($file.Extension -ne '.ps1') { continue } # Skip if the extension is not .ps1
4+
foreach ($exclusion in '\.[^\.]+\.ps1$') {
5+
if (-not $exclusion) { continue }
6+
if ($file.Name -match $exclusion) {
7+
continue ToIncludeFiles # Skip excluded files
8+
}
9+
}
10+
. $file.FullName
11+
}
12+
13+
$myModule = $MyInvocation.MyCommand.ScriptBlock.Module
14+
$ExecutionContext.SessionState.PSVariable.Set($myModule.Name, $myModule)
15+
$myModule.pstypenames.insert(0, $myModule.Name)
16+
17+
New-PSDrive -Name $MyModule.Name -PSProvider FileSystem -Scope Global -Root $PSScriptRoot -ErrorAction Ignore
18+
19+
if ($home) {
20+
$MyModuleProfileDirectory = Join-Path ([Environment]::GetFolderPath("LocalApplicationData")) $MyModule.Name
21+
if (-not (Test-Path $MyModuleProfileDirectory)) {
22+
$null = New-Item -ItemType Directory -Path $MyModuleProfileDirectory -Force
23+
}
24+
New-PSDrive -Name "My$($MyModule.Name)" -PSProvider FileSystem -Scope Global -Root $MyModuleProfileDirectory -ErrorAction Ignore
25+
}
26+
27+
# Set a script variable of this, set to the module
28+
# (so all scripts in this scope default to the correct `$this`)
29+
$script:this = $myModule
30+
31+
#region Custom
32+
#endregion Custom
33+
34+
Export-ModuleMember -Alias * -Function * -Variable $myModule.Name
35+
36+

JSON-LD.tests.ps1

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
describe 'JSON-LD' {
2+
context 'JSON-LD is a standard for embedding information in web pages' {
3+
it 'can get information about a movie' {
4+
$result = Get-JsonLD -Url 'https://www.imdb.com/title/tt0211915/'
5+
$result.pstypenames | Should -Not -BeNullOrEmpty
6+
$result.pstypenames | Should -Contain 'https://schema.org/Movie'
7+
8+
}
9+
it 'can get information a schema' {
10+
Get-JsonLD https://schema.org/Movie |
11+
Select-Object -ExpandProperty pstypenames -Unique |
12+
Should -Contain 'rdf:Property'
13+
}
14+
}
15+
}

README.md

+24
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,26 @@
11
# JSON-LD
2+
23
Get JSON Linked Data with PowerShell
4+
5+
Gets information stored in a page's [json-ld](https://json-ld.org/) (json linked data)
6+
7+
Many pages expose this information for search engine optimization.
8+
9+
## JSON-LD in PowerShell
10+
11+
JSON-LD is one of a number of ways you can get more information about a page.
12+
13+
This information can be useful in any number of fun and useful PowerShell scenarios
14+
15+
For example, let's get information about a movie.
16+
17+
~~~PowerShell
18+
Get-JsonLD https://www.imdb.com/title/tt0211915/
19+
~~~
20+
21+
Let's take things a step further, and get the information we can know about any movie:
22+
23+
~~~PowerShell
24+
JsonLD https://schema.org/Movie
25+
~~~
26+

0 commit comments

Comments
 (0)