chore: import upstream snapshot with attribution
tools_continuous_delivery / Private PyPI non-main branch release (push) Has been skipped
tools_continuous_delivery / Private PyPI main branch release (push) Failing after 2m42s
Publish Promptflow Doc / Build (push) Has been cancelled
Publish Promptflow Doc / Deploy (push) Has been cancelled
Flake8 Lint / flake8 (push) Has been cancelled
Spell check CI / Spell_Check (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:52 +08:00
commit e768098d0e
4004 changed files with 2804145 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
.title {
font-weight:700;
}
.sd-card-header {
font-weight:700;
font-size: 16px;
}
.bd-page-width {
max-width: 100rem;
}
.bd-sidebar-primary {
flex: 0 0 20%;
}
.bd-main .bd-content .bd-article-container {
max-width: 70em;
}
/* Background color for feature announcement */
html[data-theme="light"] {
--header-announcement-color: #3278e5;
}
html[data-theme="dark"] {
--header-announcement-color: #67d6ed;
}
.bd-header-announcement {
background: var(--header-announcement-color);
}
/* Background color for feature announcement */
/* Background color for warning announcement */
/*html[data-theme="light"] {*/
/* --header-announcement-color: #fff070;*/
/*}*/
/*html[data-theme="dark"] {*/
/* --header-announcement-color: #4d4d00;*/
/*}*/
/*.bd-header-announcement {*/
/* background: var(--header-announcement-color);*/
/*}*/
/* Background color for warning announcement */
/* (A) LIGHTBOX BACKGROUND */
#lightbox {
/* (A1) COVERS FULLSCREEN */
position: fixed; z-index: 1060;
top: 0; left: 0;
width: 100%; height: 100%;
/* (A2) BACKGROUND */
background: rgba(0, 0, 0, 0.5);
/* (A3) CENTER IMAGE ON SCREEN */
display: flex;
align-items: center;
align-items: center;
/* (A4) HIDDEN BY DEFAULT */
visibility: hidden;
opacity: 0;
/* (A5) SHOW/HIDE ANIMATION */
transition: opacity ease 0.4s;
}
/* (A6) TOGGLE VISIBILITY */
#lightbox.show {
visibility: visible;
opacity: 1;
}
/* (B) LIGHTBOX IMAGE */
#lightbox img {
/* (B1) DIMENSIONS */
width: 100%;
height: 100%;
/* (B2) IMAGE FIT */
/* contain | cover | fill | scale-down */
object-fit: contain;
}
.avatar {
border-radius: 50%;
width: 30px;
height: 30px;
}
+61
View File
@@ -0,0 +1,61 @@
// Get the head element
let head = document.getElementsByTagName("head")[0];
// Create the script element
let script = document.createElement("script");
script.async = true;
script.src = "https://www.googletagmanager.com/gtag/js?id=G-KZXK5PFBZY";
// Create another script element for the gtag code
let script2 = document.createElement("script");
script2.innerHTML = ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-KZXK5PFBZY'); `;
// Insert the script elements after the head element
head.insertAdjacentElement("afterbegin", script2);
head.insertAdjacentElement("afterbegin", script);
// This is used to zoom in images when clicked on
window.onload = () => {
if (document.getElementById("lightbox") === null){
// Append lightbox div to each page
let div = document.createElement('div');
div.innerHTML = '<div id="lightbox"></div>';
document.body.appendChild(div);
}
// (A) GET LIGHTBOX & ALL .ZOOMD IMAGES
let all = document.getElementsByClassName("bd-article")[0].getElementsByTagName("img"),
lightbox = document.getElementById("lightbox");
// (B) CLICK TO SHOW IMAGE IN LIGHTBOX
// * SIMPLY CLONE INTO LIGHTBOX & SHOW
if (all.length>0) { for (let i of all) {
// skip if class contains avatar or img_ev3q(Open on github button)
if (i.classList.contains("avatar") || i.classList.contains("img_ev3q")) {
continue;
}
i.onclick = () => {
let clone = i.cloneNode();
clone.className = "";
lightbox.innerHTML = "";
lightbox.appendChild(clone);
lightbox.className = "show";
};
}}
// (C) CLICK TO CLOSE LIGHTBOX
lightbox.onclick = () => {
lightbox.className = "";
};
};
if (window.location.pathname === "/promptflow/" || window.location.pathname === "/promptflow/index.html") {
// This is used to control homepage background
let observer = new MutationObserver(function(mutations) {
const dark = document.documentElement.dataset.theme == 'dark';
document.body.style.backgroundSize = "100%";
document.body.style.backgroundPositionY = "bottom";
document.body.style.backgroundRepeat = "no-repeat"
})
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['data-theme']});
}
+47
View File
@@ -0,0 +1,47 @@
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_699_15212)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M237 39.0408V461.693C237 469.397 228.655 474.208 221.988 470.346L151.918 429.764C130.306 417.247 117 394.164 117 369.19V148.892C117 123.917 130.306 100.834 151.918 88.3177L237 39.0408Z" fill="url(#paint0_linear_699_15212)"/>
<path d="M395.075 127.51L237 39V167.541L283.451 192.041L395.075 127.51Z" fill="url(#paint1_linear_699_15212)"/>
<path d="M395.075 127.51L237 39V167.541L283.451 192.041L395.075 127.51Z" fill="url(#paint2_linear_699_15212)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M255.5 231.426C255.5 217.184 263.073 204.017 275.382 196.854L395 127.248V216.101C395 241.03 381.742 264.078 360.193 276.611L270.528 328.76C263.861 332.637 255.5 327.828 255.5 320.116L255.5 231.426Z" fill="url(#paint3_linear_699_15212)"/>
</g>
<defs>
<linearGradient id="paint0_linear_699_15212" x1="196.286" y1="183.041" x2="270.786" y2="92.5087" gradientUnits="userSpaceOnUse">
<stop stop-color="#3272ED"/>
<stop offset="1" stop-color="#AF7BD6"/>
</linearGradient>
<linearGradient id="paint1_linear_699_15212" x1="457.98" y1="131.313" x2="260.351" y2="133.014" gradientUnits="userSpaceOnUse">
<stop stop-color="#DA7ED0"/>
<stop offset="0.05" stop-color="#B77BD4"/>
<stop offset="0.11" stop-color="#9079DA"/>
<stop offset="0.18" stop-color="#6E77DF"/>
<stop offset="0.25" stop-color="#5175E3"/>
<stop offset="0.33" stop-color="#3973E7"/>
<stop offset="0.42" stop-color="#2772E9"/>
<stop offset="0.54" stop-color="#1A71EB"/>
<stop offset="0.813361" stop-color="#1371EC"/>
<stop offset="1" stop-color="#064495"/>
</linearGradient>
<linearGradient id="paint2_linear_699_15212" x1="210.18" y1="4.19164" x2="307.181" y2="175.949" gradientUnits="userSpaceOnUse">
<stop stop-color="#712575"/>
<stop offset="0.09" stop-color="#9A2884"/>
<stop offset="0.18" stop-color="#BF2C92"/>
<stop offset="0.27" stop-color="#DA2E9C"/>
<stop offset="0.34" stop-color="#EB30A2"/>
<stop offset="0.4" stop-color="#F131A5"/>
<stop offset="0.5" stop-color="#EC30A3"/>
<stop offset="0.61" stop-color="#DF2F9E"/>
<stop offset="0.72" stop-color="#C92D96"/>
<stop offset="0.83" stop-color="#AA2A8A"/>
<stop offset="0.95" stop-color="#83267C"/>
<stop offset="1" stop-color="#712575"/>
</linearGradient>
<linearGradient id="paint3_linear_699_15212" x1="308" y1="260.041" x2="307.043" y2="133.204" gradientUnits="userSpaceOnUse">
<stop stop-color="#1D5CD6"/>
<stop offset="1" stop-color="#787BE5"/>
</linearGradient>
<clipPath id="clip0_699_15212">
<rect width="512" height="512" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

@@ -0,0 +1,57 @@
{%- macro automodule(modname, options) -%}
.. automodule:: {{ modname }}
{%- for option in options %}
:{{ option }}:
{%- endfor %}
{%- endmacro %}
{%- macro toctree(docnames) -%}
.. toctree::
:maxdepth: {{ maxdepth }}
{% for docname in docnames %}
{{ docname }}
{%- endfor %}
{%- endmacro %}
{%- if is_namespace %}
{{- [pkgname, "namespace"] | join(" ") | e | heading }}
{% else %}
{{- [pkgname, "module"] | join(" ") | e | heading }}
{% endif %}
{%- if is_namespace %}
.. py:module:: {{ pkgname }}
{% endif %}
{%- if modulefirst and not is_namespace %}
{{ automodule(pkgname, automodule_options) }}
{% endif %}
{%- if subpackages %}
Subpackages
-----------
{{ toctree(subpackages) }}
{% endif %}
{%- if submodules %}
Submodules
----------
{% if separatemodules %}
{{ toctree(submodules) }}
{% else %}
{%- for submodule in submodules %}
{% if show_headings %}
{{- [submodule, "module"] | join(" ") | e | heading(2) }}
{% endif %}
{{ automodule(submodule, automodule_options) }}
{% endfor %}
{%- endif %}
{%- endif %}
{%- if not modulefirst and not is_namespace %}
Module contents
---------------
{{ automodule(pkgname, automodule_options) }}
{% endif %}
+164
View File
@@ -0,0 +1,164 @@
# -- Path setup --------------------------------------------------------------
import sys
# -- Project information -----------------------------------------------------
project = "Prompt flow"
copyright = "2024, Microsoft"
author = "Microsoft"
sys.path.append(".")
from gallery_directive import GalleryDirective # noqa: E402
# -- General configuration ---------------------------------------------------
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.todo",
"sphinxext.rediraffe",
"sphinx_design",
"sphinx_copybutton",
"matplotlib.sphinxext.plot_directive",
"sphinx_togglebutton",
"myst_nb",
# 'myst_parser',
"sphinx.builders.linkcheck",
"jupyter_sphinx",
]
# -- Internationalization ------------------------------------------------
# specifying the natural language populates some key tags
language = "en"
# specify charset as utf-8 to accept chinese punctuation
charset_type = "utf-8"
autosummary_generate = True
# Add any paths that contain templates here, relative to this directory.
# templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
nb_execution_mode = "off"
exclude_patterns = [
"_build",
"Thumbs.db",
".DS_Store",
"**.ipynb_checkpoints",
"**.py",
"**.yml",
"**.sh",
"**.zip",
"**.skip",
]
source_suffix = [".rst", ".md", ".ipynb"]
# Options for the linkcheck builder
linkcheck_ignore = [
# openai related sites blocks the IP of the CI server.
r"https://openai\.com/",
r"https://platform\.openai\.com/",
r"https://help\.openai\.com/",
# These are used in card links, for example 'xx.html', .md can't be resolved.
r"^(?!https?)",
"deploy-using-docker.html",
"deploy-using-kubernetes.html",
"https://portal.azure.com/#create/Microsoft.CognitiveServicesTextAnalytics", # sphinx recognizes #create as an anchor while it's not. # noqa: E501
"https://ms.portal.azure.com/#view/Microsoft_Azure_Marketplace/MarketplaceOffersBlade/searchQuery/machine%20learning", # noqa: E501
]
linkcheck_exclude_documents = [
"contributing",
r".*/tutorials/.*", # ignore link in copied notebooks.
]
# -- Extension options -------------------------------------------------------
# This allows us to use ::: to denote directives, useful for admonitions
myst_enable_extensions = ["colon_fence", "substitution"]
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "pydata_sphinx_theme"
html_logo = "_static/logo.svg"
html_favicon = "_static/logo32.ico"
html_sourcelink_suffix = ""
html_show_sourcelink = False
# Define the json_url for our version switcher.
html_theme_options = {
"github_url": "https://github.com/microsoft/promptflow",
"header_links_before_dropdown": 6,
"icon_links": [
{
"name": "PyPI",
"url": "https://pypi.org/project/promptflow/",
"icon": "fa-solid fa-box",
},
],
"logo": {
"text": "Prompt flow",
"alt_text": "Prompt flow",
},
"use_edit_page_button": True,
"show_toc_level": 1,
"navbar_align": "left", # [left, content, right] For testing that the navbar items align properly
"navbar_center": ["navbar-nav"],
"announcement": "🚀<b style='color:black;'>"
"Promptflow 1.13.0 has released! Try new feature: "
"<a href='https://microsoft.github.io/promptflow/how-to-guides/tracing/index.html' style='color:black;'>"
"<u>tracing interaction with LLMs</u></a>."
"</b>",
"show_nav_level": 1,
}
html_sidebars = {
# "quick_start/README.md": ['localtoc.html', 'relations.html', 'searchbox.html'],
# "examples/persistent-search-field": ["search-field"],
# Blog sidebars
# ref: https://ablog.readthedocs.io/manual/ablog-configuration-options/#blog-sidebars
"features": ["localtoc.html", "relations.html", "searchbox.html"],
# "tutorials": ['localtoc.html', 'relations.html', 'searchbox.html'],
}
html_context = {
"default_mode": "light",
"github_user": "",
"github_repo": "microsoft/promptflow",
"github_version": "main",
"doc_path": "docs",
}
rediraffe_redirects = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
html_css_files = ["custom.css"]
html_js_files = ["custom.js"]
todo_include_todos = True
# myst reference config
myst_heading_anchors = 5
# allow annotation for __call__ methods
autodoc_default_options = {
'special-members': '__call__',
}
def setup(app):
# Add the gallery directive
app.add_directive("gallery-grid", GalleryDirective)
+262
View File
@@ -0,0 +1,262 @@
<#
.DESCRIPTION
Script to build doc site
.EXAMPLE
PS> ./doc_generation.ps1 -SkipInstall # skip pip install
PS> ./doc_generation.ps1 -BuildLinkCheck -WarningAsError:$true -SkipInstall
#>
[CmdletBinding()]
param(
[switch]$SkipInstall,
[switch]$WarningAsError = $false,
[switch]$BuildLinkCheck = $false,
[switch]$WithReferenceDoc = $false
)
[string] $ScriptPath = $PSCommandPath | Split-Path -Parent
[string] $RepoRootPath = $ScriptPath | Split-Path -Parent | Split-Path -Parent
[string] $DocPath = [System.IO.Path]::Combine($RepoRootPath, "docs")
[string] $TempDocPath = New-TemporaryFile | % { Remove-Item $_; New-Item -ItemType Directory -Path $_ }
[string] $PkgSrcPath = [System.IO.Path]::Combine($RepoRootPath, "src")
[string] $OutPath = [System.IO.Path]::Combine($ScriptPath, "_build")
[string] $SphinxApiDoc = [System.IO.Path]::Combine($DocPath, "sphinx_apidoc.log")
[string] $SphinxBuildDoc = [System.IO.Path]::Combine($DocPath, "sphinx_build.log")
[string] $WarningErrorPattern = "WARNING:|ERROR:|CRITICAL:| broken "
[System.Collections.ArrayList]$IncludeList = @("promptflow-tracing", "promptflow-core", "promptflow-devkit", "promptflow-azure", "promptflow-rag", "promptflow-evals")
$apidocWarningsAndErrors = $null
$buildWarningsAndErrors = $null
if (-not $SkipInstall){
# Prepare doc generation packages
pip install pydata-sphinx-theme==0.11.0
pip install sphinx==5.1
pip install sphinx-copybutton==0.5.0
pip install sphinx_design==0.3.0
pip install sphinx-sitemap==2.2.0
pip install sphinx-togglebutton==0.3.2
pip install sphinxext-rediraffe==0.2.7
pip install sphinxcontrib-mermaid==0.8.1
pip install ipython-genutils==0.2.0
pip install myst-nb==0.17.1
pip install numpydoc==1.5.0
pip install myst-parser==0.18.1
pip install "numpy<1.25"
pip install matplotlib==3.4.3
pip install jinja2==3.0.1
pip install jupyter-sphinx==0.4.0
Write-Host "===============Finished install requirements==============="
}
function ProcessFiles {
# Exclude files not mean to be in doc site
$exclude_files = "README.md", "dev"
foreach ($f in $exclude_files)
{
$full_path = [System.IO.Path]::Combine($TempDocPath, $f)
Remove-Item -Path $full_path -Recurse
}
}
Write-Host "===============PreProcess Files==============="
Write-Host "Copy doc to: $TempDocPath"
ROBOCOPY $DocPath $TempDocPath /S /NFL /NDL /XD "*.git" [System.IO.Path]::Combine($DocPath, "_scripts\_build")
ProcessFiles
function Update-Sub-Pkg-Index-Title {
param (
[string] $SubPkgRefDocPath,
[string] $SubPkgName
)
# This is used to update the title of the promptflow.rst file in the sub package
# from 'promptflow namespaces' to package name
$IndexRst = [System.IO.Path]::Combine($SubPkgRefDocPath, "promptflow.rst")
$IndexContent = Get-Content $IndexRst
$IndexContent[0] = ("{0} package" -f $SubPkgName)
$IndexContent[1] = "================================="
$IndexContent[2] = ".. py:module:: promptflow"
$IndexContent[3] = " :noindex:"
Set-Content $IndexRst $IndexContent
}
function Add-Changelog {
$ChangelogFolder = [System.IO.Path]::Combine($TempDocPath, "reference\changelog")
New-Item -ItemType Directory -Path $ChangelogFolder -Force
Write-Host "===============Collect Package ChangeLog==============="
$TocTreeContent = @("", "``````{toctree}", ":maxdepth: 1", ":hidden:", "")
foreach($Item in Get-Childitem -path $PkgSrcPath)
{
if((-not ($IncludeList -contains $Item.Name)) -and ($Item.Name -ne "promptflow")){
continue
}
# Collect CHANGELOG, name with package.md
$ChangelogPath = [System.IO.Path]::Combine($Item.FullName, "CHANGELOG.md")
$TargetChangelogPath = [System.IO.Path]::Combine($ChangelogFolder, "{0}.md" -f $Item.Name)
if($Item.Name -ne "promptflow"){
$TocTreeContent += $Item.name
}
Copy-Item -Path $ChangelogPath -Destination $TargetChangelogPath
}
$TocTreeContent += "``````"
# Add subpackage index to promptflow changelog
$PromptflowChangelog = [System.IO.Path]::Combine($ChangelogFolder, "promptflow.md")
$PromptflowChangelogContent = Get-Content $PromptflowChangelog
$PromptflowChangelogContent[0] = "# promptflow package"
$PromptflowChangelogContent += $TocTreeContent
Set-Content $PromptflowChangelog $PromptflowChangelogContent
}
function Add-Api-Reference {
$RefDocRelativePath = "reference\python-library-reference"
$RefDocPath = [System.IO.Path]::Combine($TempDocPath, $RefDocRelativePath)
$PlaceHolderFile = [System.IO.Path]::Combine($RefDocPath, "promptflow.md")
if(!(Test-Path $RefDocPath)){
throw "Reference doc path not found. Please make sure '$RefDocRelativePath' is under '$DocPath'"
}
Remove-Item $PlaceHolderFile -Force
$ApidocWarningsAndErrors = [System.Collections.ArrayList]::new()
foreach($Item in Get-Childitem -path $PkgSrcPath){
if(-not ($IncludeList -contains $Item.Name)){
continue
}
# Build API reference doc
$SubPkgPath = [System.IO.Path]::Combine($Item.FullName, "promptflow")
$SubPkgRefDocPath = [System.IO.Path]::Combine($RefDocPath, $Item.Name)
Write-Host "===============Build $Item Reference Doc==============="
$TemplatePath = [System.IO.Path]::Combine($RepoRootPath, "scripts\docs\api_doc_templates")
sphinx-apidoc --separate --module-first --no-toc --implicit-namespaces "$SubPkgPath" -o "$SubPkgRefDocPath" -t $TemplatePath | Tee-Object -FilePath $SphinxApiDoc
$SubPkgWarningsAndErrors = Select-String -Path $SphinxApiDoc -Pattern $WarningErrorPattern
if($SubPkgWarningsAndErrors){
$ApidocWarningsAndErrors.AddRange($SubPkgWarningsAndErrors)
}
Update-Sub-Pkg-Index-Title $SubPkgRefDocPath $Item.Name
}
}
function Add-Metadata{
param (
[string] $NotebookPath,
[string] $NotebookRepoPath,
[System.Collections.ArrayList] $AuthorList
)
if (-not $AuthorList){
# Skip insert if author list not set
throw "Skip Add Metadata: $NotebookPath - Author list not set"
return
}
$NotebookContent = Get-Content $NotebookPath -Raw | ConvertFrom-Json
# Covert to System.Collections.ArrayList to avoid 'Collection was of a fixed size' error.
$NotebookContent.cells = [System.Collections.ArrayList]::new($NotebookContent.cells)
if($NotebookContent.cells[0].source.Length -gt 1){
# If the first cell length > 1, indicate there are more things than title it self in the first cell
throw "Skip Add Metadata: $NotebookPath - First cell length > 1, only leave title to that cell."
return
}
$MetadataFormat = "Authored by:&nbsp;{0}{1}"
$SingleAuthor = "&nbsp;<a href='https://github.com/{0}' target='_blank'><img src='https://github.com/{0}.png' alt='Avatar' class='avatar dark-light'></a>"
$JumpLink = "<a href='{0}' target='_blank'><img decoding='async' loading='lazy' src='https://img.shields.io/badge/Open%20on%20GitHub-grey?logo=github' alt='Open on GitHub' class='img_ev3q' style='float: right;'></a>" -f $NotebookRepoPath
$Authors = $AuthorList | ForEach-Object { $SingleAuthor -f $_.replace("@github.com", "") }
$Metadata = $MetadataFormat -f ($Authors -join ""), $JumpLink
# Insert metadata to cells
$MetadataCell = @{
"cell_type" = "markdown";
"metadata" = @{};
"source" = @($Metadata)
}
$NotebookContent.cells.Insert(1, $MetadataCell)
$NotebookContent | ConvertTo-Json -Depth 100 | Set-Content $NotebookPath
}
function Add-Notebook
{
Write-Host "===============Collect Package Notebooks==============="
$NotebookRootPath = [System.IO.Path]::Combine($RepoRootPath, "examples")
$TargetNotebookPath = [System.IO.Path]::Combine($TempDocPath, "tutorials")
# Create section list
$SectionNames = "Tracing", "Prompty", "Flow", "Rag"
$Sections = [ordered]@{
Tracing=[System.Collections.ArrayList]::new();
Prompty=[System.Collections.ArrayList]::new();
Flow=[System.Collections.ArrayList]::new()
Rag=[System.Collections.ArrayList]::new()
}
foreach($Item in Get-Childitem -path $NotebookRootPath -Recurse -Filter "*.ipynb")
{
# Notebook to build must have metadata: {"build_doc": {"category": "local/azure"}}
$NotebookContent = Get-Content $Item.FullName -Raw | ConvertFrom-Json
if(-not $NotebookContent.metadata.build_doc){
continue
}
$RepoPath = $Item.FullName.Replace($RepoRootPath, "https://github.com/microsoft/promptflow/tree/main/")
$SectionName = $NotebookContent.metadata.build_doc.section
[int]$Weight = $NotebookContent.metadata.build_doc.weight
$Category = $NotebookContent.metadata.build_doc.category
$AuthorList = $NotebookContent.metadata.build_doc.author
# If category is 'azure', add 1000 to weight
if($Category -eq "azure"){
$Weight += 1000
}
# Add ItemName, Category tuple to sections
$Sections[$SectionName].Add([Tuple]::Create($Item.Name.Replace(".ipynb", ""), $Weight))
# Copy notebook to doc path
Write-Host "Adding Notebook $Item ..."
$MediaDir = $Item.FullName + '\..\media'
Copy-Item -Path $Item.FullName -Destination $TargetNotebookPath
if(Test-Path $MediaDir){
# copy image referenced in notebook
Write-Host "Copying media files from $MediaDir ..."
Copy-Item -Path $MediaDir -Destination $TargetNotebookPath -Recurse -Force
}
# Append metadata to notebook
$CopiedNotebookPath = [System.IO.Path]::Combine($TargetNotebookPath, $Item.Name)
Add-Metadata $CopiedNotebookPath $RepoPath $AuthorList
}
# Reverse sort each section list by Weight
foreach($SectionName in $SectionNames){
$Sections[$SectionName] = $Sections[$SectionName] | Sort-Object -Property { $_.Item2 }
}
$TocTreeContent = @("", "``````{{toctree}}", ":caption: {0}", ":hidden:", ":maxdepth: 1", "", "{1}", "``````")
# Build toctree content for each section, append to tutorials index.md
$TutorialIndex = [System.IO.Path]::Combine($TargetNotebookPath, "index.md")
foreach($SectionName in $SectionNames){
$SectionTocTree = $TocTreeContent -join "`n"
# Join Item1 to a string in list
$ExampleList = ($Sections[$SectionName] | ForEach-Object { $_.Item1 }) -join "`n"
$SectionTocTree = $SectionTocTree -f $SectionName, $ExampleList
Write-Debug $SectionTocTree
Add-Content -Path $TutorialIndex -Value $SectionTocTree
}
}
if($WithReferenceDoc){
Add-Api-Reference
}
# Build subpackage changelog
Add-Changelog
# Build notebook examples
Add-Notebook
Write-Host "===============Build Documentation with internal=${Internal}==============="
$BuildParams = [System.Collections.ArrayList]::new()
if($WarningAsError){
$BuildParams.Add("-W")
$BuildParams.Add("--keep-going")
}
if($BuildLinkCheck){
$BuildParams.Add("-blinkcheck")
}
sphinx-build $TempDocPath $OutPath -c $ScriptPath $BuildParams -v | Tee-Object -FilePath $SphinxBuildDoc
$buildWarningsAndErrors = Select-String -Path $SphinxBuildDoc -Pattern $WarningErrorPattern
Write-Host "Clean path: $TempDocPath"
Remove-Item $TempDocPath -Recurse -Confirm:$False -Force
if ($buildWarningsAndErrors) {
Write-Host "=============== Build warnings and errors ==============="
foreach ($line in $buildWarningsAndErrors) {
Write-Host $line -ForegroundColor Red
}
}
+139
View File
@@ -0,0 +1,139 @@
"""A directive to generate a gallery of images from structured data.
Generating a gallery of images that are all the same size is a common
pattern in documentation, and this can be cumbersome if the gallery is
generated programmatically. This directive wraps this particular use-case
in a helper-directive to generate it with a single YAML configuration file.
It currently exists for maintainers of the pydata-sphinx-theme,
but might be abstracted into a standalone package if it proves useful.
"""
from yaml import safe_load
from typing import List
from pathlib import Path
from docutils import nodes
from docutils.parsers.rst import directives
from sphinx.util.docutils import SphinxDirective
from sphinx.util import logging
logger = logging.getLogger(__name__)
TEMPLATE_GRID = """
`````{{grid}} {grid_columns}
{container_options}
{content}
`````
"""
GRID_CARD = """
````{{grid-item-card}} {title}
{card_options}
{content}
````
"""
class GalleryDirective(SphinxDirective):
"""A directive to show a gallery of images and links in a grid."""
name = "gallery-grid"
has_content = True
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
option_spec = {
# A class to be added to the resulting container
"grid-columns": directives.unchanged,
"class-container": directives.unchanged,
"class-card": directives.unchanged,
}
def run(self) -> List[nodes.Node]: # noqa: C901
if self.arguments:
# If an argument is given, assume it's a path to a YAML file
# Parse it and load it into the directive content
path_data_rel = Path(self.arguments[0])
path_doc, _ = self.get_source_info()
path_doc = Path(path_doc).parent
path_data = (path_doc / path_data_rel).resolve()
if not path_data.exists():
logger.warn(f"Could not find grid data at {path_data}.")
nodes.text("No grid data found at {path_data}.")
return
yaml_string = path_data.read_text()
else:
yaml_string = "\n".join(self.content)
# Read in YAML so we can generate the gallery
grid_data = safe_load(yaml_string)
grid_items = []
for item in grid_data:
# Grid card parameters
options = {}
if "website" in item:
options["link"] = item["website"]
if "class-card" in self.options:
options["class-card"] = self.options["class-card"]
if "img-background" in item:
options["img-background"] = item["img-background"]
if "img-top" in item:
options["img-top"] = item["img-top"]
if "img-bottom" in item:
options["img-bottom"] = item["img-bottom"]
options_str = "\n".join(f":{k}: {v}" for k, v in options.items()) + "\n\n"
# Grid card content
content_str = ""
if "header" in item:
content_str += f"{item['header']}\n\n^^^\n\n"
if "image" in item:
content_str += f"![Gallery image]({item['image']})\n\n"
if "content" in item:
content_str += f"{item['content']}\n\n"
if "footer" in item:
content_str += f"+++\n\n{item['footer']}\n\n"
title = item.get("title", "")
content_str += "\n"
grid_items.append(
GRID_CARD.format(
card_options=options_str, content=content_str, title=title
)
)
# Parse the template with Sphinx Design to create an output
container = nodes.container()
# Prep the options for the template grid
container_options = {"gutter": 2, "class-container": "gallery-directive"}
if "class-container" in self.options:
container_options[
"class-container"
] += f' {self.options["class-container"]}'
container_options_str = "\n".join(
f":{k}: {v}" for k, v in container_options.items()
)
# Create the directive string for the grid
grid_directive = TEMPLATE_GRID.format(
grid_columns=self.options.get("grid-columns", "1 2 3 4"),
container_options=container_options_str,
content="\n".join(grid_items),
)
# Parse content as a directive so Sphinx Design processes it
self.state.nested_parse([grid_directive], 0, container)
# Sphinx Design outputs a container too, so just use that
container = container.children[0]
# Add extra classes
if self.options.get("container-class", []):
container.attributes["classes"] += self.options.get("class", [])
return [container]