# web.rest.github 库模块帮助文档

<details>  <summary>用法</summary>  <p>

## 几句代码查询公开仓库，无需 token

```aardio
import web.rest.github;
var gh = web.rest.github;

var entries = gh.list("octocat/Spoon-Knife");
var files = gh.findFiles("octocat/Spoon-Knife","*.html");
var code,err = gh.read("octocat/Spoon-Knife","index.html",{
    pattern = "<body>"; context = 4; maxBytes = 2000;
});
if(code) print(code.data); else print(err);
```

- `list(repoOrUrl[,path,options])`：单层列目录，一次 Contents 请求。
- `findFiles(repoOrUrl[,fileMask,options])`：一次递归 Git Trees 请求，仅筛选文件路径，不下载正文。
- `read(repoOrUrl[,path,options])`：带行号的文本预览；给 `pattern` 就在这个文件内搜索。
- 三者也支持 `函数(user,repo,path或fileMask,options)`；省略路径时可把 options 直接放在最后。
- 接受 `owner/repo`、仓库 URL、`blob/raw/tree` URL、`raw.githubusercontent.com` 文件 URL。未知仓库先联网搜索；需要按仓库名取首个结果才用 `repo(keyword)`。
- 成功返回结果表，失败返回 `null,err`；空目录、空文件、无匹配不是错误。原有 `getContent` 仍返回完整文本，`getJson` 返回解析后的 JSON。

## 预览、文件内查找与继续读取

```aardio
import web.rest.github;
var gh = web.rest.github;
var page,err = gh.read("https://github.com/octocat/Spoon-Knife/blob/main/index.html",{
    startLine = 1; lineCount = 30; maxBytes = 3000;
});

if(page && page.nextLine){
    page,err = gh.read("octocat/Spoon-Knife","index.html",{
        startLine = page.nextLine; lineCount = 30;
    });
}
```

`read` 的 options：
- `startLine=1`、`lineCount=80`：按行预览。索引自 1 开始；有 pattern 时忽略 lineCount，搜索 startLine 到文件末尾。
- `pattern`：默认**字面子串**，不必转义；`ignoreCase=true` 可忽略英文大小写。
- `literal=false`：显式改用 aardio 模式语法，不是 PCRE；此模式不支持 ignoreCase，请在模式内指定大小写规则。
- `context=3`：命中前后行数；相邻上下文合并，长行优先保留命中附近。
- `maxResults=20`：最多展示多少个命中行；`matchCount` 是请求搜索范围内的匹配行总数，不是子串出现次数。
- `maxBytes=8000`：data 的 UTF-8 字节预算，包含行号和省略标记；零值只取元信息。不会切断 UTF-8 字符。
- `maxFileSize=1048576`：默认只预览不超过 1 MiB 的文本；更大的文件建议下载后处理，可显式调大。
- `data` 是预览文本；`nextLine` 传回 startLine 即可续读/续搜。按行阅读时放不下的行整行留给下一段，分段边界不截断；只有单行超过 maxBytes 才行内裁剪，`clippedLines>0` 即有这种行，需完整长行可调大 maxBytes 重读该行。
- `complete=true` 才表示 data 已是整个文件（pattern 搜索时为整个文件的全部命中及上下文），没有省略。只读了一部分、从中间开始或有行内裁剪都是 false；分段续读以 `nextLine` 为空判断读到末尾。只要全文就直接用 `getContent(url)` 或 `getContent(user,repo,path)`，不必循环 read。

## 找文件而不是搜索全仓正文

```aardio
import web.rest.github;
var gh = web.rest.github;
var files = gh.findFiles("octocat/Spoon-Knife","*.html|*.css",{
    maxResults = 10; maxBytes = 2000;
});
// 路径已知就直接 read，不必先 list/findFiles。
```

`list/findFiles` 的 options：
- `fileMask`：文件名或完整路径通配符，支持 `*`、`?`、`**`、`|` 分隔多个模式；findFiles 的第 2 个参数就是 fileMask。默认忽略大小写，`ignoreCase=false` 可关闭。
- `path`：目录路径；list 直接查询该目录，findFiles 在取回的文件树中过滤这个目录及其后代（不会减少上游树的大小）。
- `maxResults=50`、`maxBytes=8000`：限制 items 数量和序列化后的 UTF-8 大小，不含外层元信息；预算不足时仍返回空数组 `[]`。
- `items` 仅保留 `path/type/size`；`total` 是已取得的目录/文件树中的匹配总数。
- `nextIndex` 传回 `startIndex` 继续列出。续列会重新请求；需要一致快照时请固定 ref 为 commit SHA。

三者共同支持 `ref`（分支、标签、commit，默认 HEAD）。URL 中自带 ref 会自动识别；含斜杠的分支若未编码，请显式指定，例如 `{ref="feature/test"}`，避免 URL 歧义。

**complete 与 truncated 不同**：list/findFiles 的 complete 表示上游目录/文件树完整，可与 truncated 同时为 true（上游完整，只是本次输出限量，按 nextIndex 续列）；read 取不到完整文件会直接返回错误，它的 complete 表示 data 已是整个文件或整个文件的全部命中，为 true 时 truncated 必为 false。truncated 表示输出或上游数据有省略。`complete=false` 时无匹配不能推断不存在。Contents 返回 1000 项时保守标为不完整；Git Trees 的截断标记原样尊重，不自动爬子树。

**小预览不等于小下载**：maxBytes 仅限制返回的预览；仍要获取目录/树或文件内容。没有自动翻页、全仓正文扫描、隐式重试或缓存。遇到限流直接返回错误，不继续轰炸接口。

## 官方端点无需另建 jsonClient

```aardio
import web.rest.github;
var repo = web.rest.github.repo("octocat/Spoon-Knife");
var commits,err = repo.commits.get({per_page=3});
// GET /repos/{owner}/{repo}/commits；参数沿用官方名称。
var api = web.rest.github().api();
// 例如 api.users["octocat"].repos.get({per_page=5})。
```

`repo()` 仍返回 `api,user,repo,url`；`web.rest.github().api()` 以 api.github.com 为根，端点、HTTP 方法和参数与官方相同，不用先读别的文档。响应未经精简，须用 per_page 等官方参数控制数量。读取 `_config.yml` 等以下划线开头的路径请直接用 read/getContent。

> **AI Agent 不要调用 `search.code`（GET /search/code）**：它需要认证，不属于本库的免认证轻量查询路线。跨仓库/全仓源码搜索优先联网搜索，或 `getZipUrl("owner/repo")` 下载仓库后本地搜索；不要尝试添加 token、反复重试或循环下载所有文件。

</p></details>

[无UI轻量查询](https://www.aardio.com/zh-cn/docs/examples/Web/REST/githubQuery.html) [GUI调用示例](https://www.aardio.com/zh-cn/docs/examples/Web/REST/github.html)

## web.rest.github 成员列表 <a id="web.rest.github" href="#web.rest.github">&#x23;</a>

GitHub 轻量查询首选：list 列目录，findFiles 找路径，read 限量阅读/文件内搜索。  
repo(...).端点.get(params) 与官方 REST 一致，无需另建 jsonClient。  
不要用需认证的 search.code；全仓正文搜索用联网搜索或下载后本地搜索。  
完整用法就在本库 details 内。

### web.rest.github.findFiles <a id="web.rest.github.findFiles" href="#web.rest.github.findFiles">&#x23;</a>
按路径找文件，仅一次递归 Git Trees 请求，不下载正文，不调用 search.code。  
返回 {items,total,complete,truncated,nextIndex,...}，失败 null,err。  
默认最多 50 项/8000 字节；complete=false 时未命中不代表不存在。

### web.rest.github.findFiles() <a id="web.rest.github.findFiles" href="#web.rest.github.findFiles">&#x23;</a>
[返回对象:webGithubListingObject](#webGithubListingObject)

### web.rest.github.findFiles(repoOrUrl,fileMask,options) <a id="web.rest.github.findFiles" href="#web.rest.github.findFiles">&#x23;</a>
例如 findFiles("owner/repo","*.js|*.ts",{path="src";maxResults=10})。  
mask 默认 *；支持文件名或完整路径通配符，默认忽略大小写。  
options：ref,path,fileMask,maxResults,maxBytes,startIndex,ignoreCase。

### web.rest.github.findFiles(user,repo,fileMask,options) <a id="web.rest.github.findFiles" href="#web.rest.github.findFiles">&#x23;</a>
分开指定 user,repo；其余参数可省略。

### web.rest.github.getContent(用户名,仓库名,文件路径,分支名) <a id="web.rest.github.getContent" href="#web.rest.github.getContent">&#x23;</a>
自指定的 GitHub 仓库获取数据，分支名可省略

### web.rest.github.getContent(网址) <a id="web.rest.github.getContent" href="#web.rest.github.getContent">&#x23;</a>
自指定的 GitHub 网址获取数据,  
包含 blob,raw 的 GitHub 网址可省略域名部分

### web.rest.github.getJson(用户名,仓库名,文件路径,分支名) <a id="web.rest.github.getJson" href="#web.rest.github.getJson">&#x23;</a>
自指定的 GitHub 仓库获取数据，分支名可省略。  
成功返回解析 JSON 得到的对象。

### web.rest.github.getJson(网址) <a id="web.rest.github.getJson" href="#web.rest.github.getJson">&#x23;</a>
自指定的 GitHub 网址获取 JSON 文件，成功返回解析 JSON 得到的对象。  
包含 blob,raw 的 GitHub 网址可省略域名部分

### web.rest.github.getZipUrl <a id="web.rest.github.getZipUrl" href="#web.rest.github.getZipUrl">&#x23;</a>
获取下载仓库的 zip 地址。

### web.rest.github.getZipUrl(仓库网址) <a id="web.rest.github.getZipUrl" href="#web.rest.github.getZipUrl">&#x23;</a>
如果未指定参数 @2 则解析参数 @1 指定的 GitHub 网址。  
包含 blob,raw 的 GitHub 网址可省略域名部分。  
也可以简写为 `用户名/项目名` 格式（用户名不能包含冒号`:`与`/`）

### web.rest.github.getZipUrl(搜索关键字) <a id="web.rest.github.getZipUrl" href="#web.rest.github.getZipUrl">&#x23;</a>
在 GitHub 上搜索仓库名，并返回搜索结果中的首个仓库的 zip 地址。  
注意不能过于频繁地调用搜索接口。

### web.rest.github.getZipUrl(用户名,仓库名) <a id="web.rest.github.getZipUrl" href="#web.rest.github.getZipUrl">&#x23;</a>
指定参数 @1,@2 则需要准确指定用户名与仓库名。

### web.rest.github.import(网址) <a id="web.rest.github.import" href="#web.rest.github.import">&#x23;</a>
自指定的 GitHub 网址获取 *.aardio 扩展库文件代码并安装,  
包含 blob,raw 的 GitHub 网址可省略域名部分,  
仅支持小型单文件扩展库,  
项目中的文件路径必须与库目录下的子路径一致

### web.rest.github.latestRelease("用户名/仓库名") <a id="web.rest.github.latestRelease" href="#web.rest.github.latestRelease">&#x23;</a>
获取最新发布版本信息  

如果参数@2指定文件名,或获取文件名的函数,  
则返回该文件的完整下载地址

### web.rest.github.list <a id="web.rest.github.list" href="#web.rest.github.list">&#x23;</a>
免认证列公开仓库目录，一次请求，默认最多 50 项/8000 字节。  
返回 {items,total,complete,truncated,nextIndex,...}，失败 null,err。  
官方端点可用 repo(...).contents.get()；轻量查询优先本函数。

### web.rest.github.list() <a id="web.rest.github.list" href="#web.rest.github.list">&#x23;</a>
[返回对象:webGithubListingObject](#webGithubListingObject)

### web.rest.github.list(repoOrUrl,path,options) <a id="web.rest.github.list" href="#web.rest.github.list">&#x23;</a>
repoOrUrl 支持 owner/repo 或 GitHub URL。  
path、options 可省略，可直接写 list(repoOrUrl,options)。  
options：ref,path,fileMask,maxResults,maxBytes,startIndex,ignoreCase。

### web.rest.github.list(user,repo,path,options) <a id="web.rest.github.list" href="#web.rest.github.list">&#x23;</a>
分开指定 user,repo；path 与 options 可省略。

### web.rest.github.parseUrl <a id="web.rest.github.parseUrl" href="#web.rest.github.parseUrl">&#x23;</a>
解析指定的 GitHub 网址；支持 blob/raw/tree、raw.githubusercontent.com、owner/repo。

### web.rest.github.parseUrl(用户名,仓库名,文件路径,分支名) <a id="web.rest.github.parseUrl" href="#web.rest.github.parseUrl">&#x23;</a>
如果指定了参数 @1 与 @2 则直接返回所有参数。  
其他参数可选

### web.rest.github.parseUrl(网址) <a id="web.rest.github.parseUrl" href="#web.rest.github.parseUrl">&#x23;</a>
如果未指定参数 @2 则解析指定的 GitHub 网址并返回：  
用户名,仓库名,文件路径,分支名。  

包含 blob,raw 的 GitHub 网址可省略域名部分。  
也可以简写为 `用户名/项目名` 格式（用户名不能包含冒号`:`与`/`）

### web.rest.github.read <a id="web.rest.github.read" href="#web.rest.github.read">&#x23;</a>
限量读取一个公开仓库文本文件，带行号；给 pattern 就搜索这个文件。  
例如 read("owner/repo","src/file.js",{pattern="init";context=3;maxBytes=4000})。  
返回 {data,totalLines,matchCount,nextLine,complete,truncated,...}，失败 null,err。  
不扫描全仓，不调用需认证的 search.code。

### web.rest.github.read() <a id="web.rest.github.read" href="#web.rest.github.read">&#x23;</a>
[返回对象:webGithubPreviewObject](#webGithubPreviewObject)

### web.rest.github.read(repoOrUrl,path,options) <a id="web.rest.github.read" href="#web.rest.github.read">&#x23;</a>
path、options 可省略；完整文件 URL 可直接 read(url,{maxBytes=4000})。  
options：ref,startLine=1,lineCount=80,pattern,literal=true,ignoreCase=false,context=3,maxResults=20,maxBytes=8000,maxFileSize=1048576。  
pattern 默认为字面子串；literal=false 才是 aardio 模式语法。

### web.rest.github.read(user,repo,path,options) <a id="web.rest.github.read" href="#web.rest.github.read">&#x23;</a>
分开指定 user,repo,path；options 可省略。

### web.rest.github.repo <a id="web.rest.github.repo" href="#web.rest.github.repo">&#x23;</a>
获取仓库接口。  
成功返回 api,user,repo,url 等 4 个值。  
返回 api 是由 web.rest.github（web.rest.jsonLiteClient API）创建的 API 对象。  
返回的 url 则是项目主页网址。  

失败返回 null,错误信息。  

调用返回对象的 getUrl 方法可获取找到的项目网址。

### web.rest.github.repo() <a id="web.rest.github.repo" href="#web.rest.github.repo">&#x23;</a>
[返回对象:webRestApiObject](https://www.aardio.com/zh-cn/docs/library-reference/web/rest/client.html#webRestApiObject)

### web.rest.github.repo(仓库网址) <a id="web.rest.github.repo" href="#web.rest.github.repo">&#x23;</a>
如果未指定参数 @2 则解析参数 @1 指定的 GitHub 网址。  
包含 blob,raw 的 GitHub 网址可省略域名部分。  
也可以简写为 `用户名/项目名` 格式（用户名不能包含冒号`:`与`/`）

### web.rest.github.repo(搜索关键字) <a id="web.rest.github.repo" href="#web.rest.github.repo">&#x23;</a>
在 GitHub 上搜索仓库名，并返回搜索结果中的首个仓库调用接口。  
注意不能过于频繁地调用搜索接口。

### web.rest.github.repo(用户名,仓库名) <a id="web.rest.github.repo" href="#web.rest.github.repo">&#x23;</a>
指定参数 @1,@2 则需要准确指定用户名与仓库名。

## web.rest 成员列表 <a id="web.rest" href="#web.rest">&#x23;</a>

### web.rest.github() <a id="web.rest.github" href="#web.rest.github">&#x23;</a>
创建 GitHub REST 客户端，继承 web.rest.jsonLiteClient。  
api() 默认以 api.github.com 为根，端点、方法与参数沿用官方 API。  
日常公开仓库查询直接用 web.rest.github.list/findFiles/read。  

[返回对象:webRestClientObject](https://www.aardio.com/zh-cn/docs/library-reference/web/rest/client.html#webRestClientObject)

## web.rest.github.!web_github_listing 成员列表 <a id="web.rest.github.!web_github_listing" href="#web.rest.github.!web_github_listing">&#x23;</a>

### web.rest.github.!web_github_listing.complete <a id="web.rest.github.!web_github_listing.complete" href="#web.rest.github.!web_github_listing.complete">&#x23;</a>
上游是否完整；false 时不可断言文件不存在。

### web.rest.github.!web_github_listing.items <a id="web.rest.github.!web_github_listing.items" href="#web.rest.github.!web_github_listing.items">&#x23;</a>
精简数组，元素仅含 path,type,size；目录没有 size。

### web.rest.github.!web_github_listing.nextIndex <a id="web.rest.github.!web_github_listing.nextIndex" href="#web.rest.github.!web_github_listing.nextIndex">&#x23;</a>
首个未显示匹配的索引；作为 options.startIndex 继续查询。

### web.rest.github.!web_github_listing.total <a id="web.rest.github.!web_github_listing.total" href="#web.rest.github.!web_github_listing.total">&#x23;</a>
已取得目录/文件树中的匹配总数，不受本次输出限制。

### web.rest.github.!web_github_listing.truncated <a id="web.rest.github.!web_github_listing.truncated" href="#web.rest.github.!web_github_listing.truncated">&#x23;</a>
输出或上游数据有省略；可与 complete 同时为 true。

## web.rest.github.!web_github_preview 成员列表 <a id="web.rest.github.!web_github_preview" href="#web.rest.github.!web_github_preview">&#x23;</a>

### web.rest.github.!web_github_preview.clippedLines <a id="web.rest.github.!web_github_preview.clippedLines" href="#web.rest.github.!web_github_preview.clippedLines">&#x23;</a>
行内裁剪数；需要完整长行请调大 maxBytes 重读该行。

### web.rest.github.!web_github_preview.complete <a id="web.rest.github.!web_github_preview.complete" href="#web.rest.github.!web_github_preview.complete">&#x23;</a>
data 已是整个文件（pattern 搜索时为整个文件的全部命中及上下文），没有省略。  
false 时不可当成全文；分段续读以 nextLine 为空判断读到末尾。

### web.rest.github.!web_github_preview.data <a id="web.rest.github.!web_github_preview.data" href="#web.rest.github.!web_github_preview.data">&#x23;</a>
带行号的 UTF-8 预览文本，字节数不超过 maxBytes。

### web.rest.github.!web_github_preview.endLine <a id="web.rest.github.!web_github_preview.endLine" href="#web.rest.github.!web_github_preview.endLine">&#x23;</a>
data 最后一行的行号；没有输出任何行时为空。

### web.rest.github.!web_github_preview.matchCount <a id="web.rest.github.!web_github_preview.matchCount" href="#web.rest.github.!web_github_preview.matchCount">&#x23;</a>
pattern 模式下，请求搜索范围内的匹配行总数，不是子串出现次数。

### web.rest.github.!web_github_preview.nextLine <a id="web.rest.github.!web_github_preview.nextLine" href="#web.rest.github.!web_github_preview.nextLine">&#x23;</a>
作为 options.startLine 续读/续搜；无更多匹配或行时为空。

### web.rest.github.!web_github_preview.startLine <a id="web.rest.github.!web_github_preview.startLine" href="#web.rest.github.!web_github_preview.startLine">&#x23;</a>
data 第一行的行号；没有输出任何行时为空。

### web.rest.github.!web_github_preview.totalLines <a id="web.rest.github.!web_github_preview.totalLines" href="#web.rest.github.!web_github_preview.totalLines">&#x23;</a>
完整文件的行数。

### web.rest.github.!web_github_preview.truncated <a id="web.rest.github.!web_github_preview.truncated" href="#web.rest.github.!web_github_preview.truncated">&#x23;</a>
有行或行内文本省略，不可将预览当成完整源码。
