diff options
author | Aleksandr Beliaev | 2023-08-01 19:34:48 +1200 |
---|---|---|
committer | Aleksandr Beliaev | 2023-08-01 19:34:48 +1200 |
commit | c6a9ec9caceac36ab1a195bce0a0a603aa3844f2 (patch) | |
tree | 40c72fce726aa9281bf4f2f680bdb04a8c3685a4 | |
parent | a00cc041126a133f08b8c365b70ef85e596c86a6 (diff) | |
download | aur-c6a9ec9caceac36ab1a195bce0a0a603aa3844f2.tar.gz |
v1.4.274.r2.gd9c08cbc9
-rw-r--r-- | .SRCINFO | 11 | ||||
-rw-r--r-- | 001_vendor_patch_1.diff | 1672 | ||||
-rw-r--r-- | 001_vendor_patch_2.diff | 33 | ||||
-rw-r--r-- | 002_multi_def_patch_1.diff | 11 | ||||
-rw-r--r-- | 002_multi_def_patch_2.diff | 11 | ||||
-rw-r--r-- | PKGBUILD | 68 |
6 files changed, 1781 insertions, 25 deletions
@@ -1,6 +1,6 @@ pkgbase = quarto-cli-git pkgdesc = Quarto is an open-source scientific and technical publishing system built on [Pandoc](https://pandoc.org). This package tracks main git branch of Quarto. - pkgver = 1.4.96.r1.gf23b0ad34 + pkgver = 1.4.274.r2.gd9c08cbc9 pkgrel = 1 url = https://quarto.org/ arch = x86_64 @@ -15,6 +15,7 @@ pkgbase = quarto-cli-git depends = esbuild depends = pandoc depends = lua-lpeg + depends = typst provides = quarto conflicts = quarto-cli-bin conflicts = quarto-cli @@ -24,9 +25,17 @@ pkgbase = quarto-cli-git source = https://github.com/b-fuze/deno-dom/archive/refs/tags/v0.1.35-alpha-artifacts.tar.gz source = https://github.com/c4spar/deno-cliffy/archive/refs/tags/v0.25.7.tar.gz source = https://github.com/denoland/deno_std/archive/refs/tags/0.170.0.tar.gz + source = 001_vendor_patch_1.diff + source = 001_vendor_patch_2.diff + source = 002_multi_def_patch_1.diff + source = 002_multi_def_patch_2.diff sha256sums = SKIP sha256sums = 14fb042a6912041b9fda91fd643cf278764d075bc9539aa1e107475915cd896c sha256sums = 519709be1dfcf4743930b7f21a513d8fbf3663380020eac8ba629081395f6cc0 sha256sums = 369bc68b848532bedcb786a8fce5e52000624b9262f05ceeeb16bc851b6cf752 + sha256sums = 937a39f116c4310c4989cf71b9e174b6dc7bfdd84c6632e5dd0b47508cffef86 + sha256sums = 144101b799267869395ba2fe85ab8549be277b18af9545c106675f620e73a85b + sha256sums = 6c1adcf6a21ab6a2949eee9770fe19ef453758dc2e1d3f7a071f07c66d5c92b2 + sha256sums = 1ee399808579aa05f38b9c27dfd23e9102f38fffb437233d360b0c076118312f pkgname = quarto-cli-git diff --git a/001_vendor_patch_1.diff b/001_vendor_patch_1.diff new file mode 100644 index 000000000000..ea8c8ca8c9c0 --- /dev/null +++ b/001_vendor_patch_1.diff @@ -0,0 +1,1672 @@ +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie_jar.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie_jar.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie_jar.ts 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie_jar.ts 1970-01-01 12:00:00.000000000 +1200 +@@ -1,259 +0,0 @@ +-import { +- Cookie, +- CookieOptions, +- isSameDomainOrSubdomain, +- parseURL, +-} from "./cookie.ts"; +- +-const strictMatchProps = [ +- "value", +- "secure", +- "httpOnly", +- "maxAge", +- "expires", +- "sameSite", +-]; +- +-function cookieMatches( +- options: Cookie | CookieOptions, +- comparedWith: Cookie, +- strictMatch = false, +-): boolean { +- if ( +- options.path !== undefined && !comparedWith.path?.startsWith(options.path) +- ) { +- return false; +- } +- +- if (options.domain) { +- if (!isSameDomainOrSubdomain(options.domain, comparedWith.domain)) { +- return false; +- } +- } +- +- if ( +- options.name !== undefined && +- options.name !== comparedWith.name +- ) { +- return false; +- } +- +- if ( +- strictMatch && +- strictMatchProps.some((propKey) => +- // deno-lint-ignore ban-ts-comment +- // @ts-ignore +- options[propKey] !== undefined && +- // deno-lint-ignore ban-ts-comment +- // @ts-ignore +- options[propKey] !== comparedWith[propKey] +- ) +- ) { +- return false; +- } +- +- return true; +-} +- +-// cookie compare from tough-cookie +-const MAX_TIME = 2147483647000; // 31-bit max +-/** +- * Cookies with longer paths are listed before cookies with +- * shorter paths. +- * +- * Among cookies that have equal-length path fields, cookies with +- * earlier creation-times are listed before cookies with later +- * creation-times." +- */ +-function cookieCompare(a: Cookie, b: Cookie) { +- let cmp = 0; +- +- // descending for length: b CMP a +- const aPathLen = a.path?.length || 0; +- const bPathLen = b.path?.length || 0; +- cmp = bPathLen - aPathLen; +- if (cmp !== 0) { +- return cmp; +- } +- +- // ascending for time: a CMP b +- const aTime = a.creationDate || MAX_TIME; +- const bTime = b.creationDate || MAX_TIME; +- cmp = aTime - bTime; +- if (cmp !== 0) { +- return cmp; +- } +- +- // tie breaker +- cmp = a.creationIndex - b.creationIndex; +- +- return cmp; +-} +- +-export class CookieJar { +- cookies = Array<Cookie>(); +- +- /** +- * @param cookies - the cookies array to initialize with +- */ +- constructor(cookies?: Array<Cookie> | Array<CookieOptions>) { +- this.replaceCookies(cookies); +- } +- +- /** +- * Sets or replaces a cookie inside the jar. +- * Only sets new cookies if cookie is valid and not expired. +- * Validation and expiration checks are not run when replacing a cookie. +- * @param url - the url that this cookie from received from. mainly used by the fetch wrapper. +- * will automatically set domain and path if provided and it was not found inside Cookie/cookiestring. +- */ +- setCookie(cookie: Cookie | string, url?: string | Request | URL) { +- let cookieObj; +- if (typeof cookie === "string") { +- cookieObj = Cookie.from(cookie); +- } else { +- cookieObj = cookie; +- } +- if (url) { +- if (!cookieObj.domain) { +- cookieObj.setDomain(url); +- } +- if (!cookieObj.path) { +- cookieObj.setPath(url); +- } +- } +- +- if (!cookieObj.isValid()) { +- return; +- } +- +- const foundCookie = this.getCookie(cookieObj); +- if (foundCookie) { +- const indexOfCookie = this.cookies.indexOf(foundCookie); +- if (!cookieObj.isExpired()) { +- this.cookies.splice(indexOfCookie, 1, cookieObj); +- } else { +- this.cookies.splice(indexOfCookie, 1); +- } +- } else if (!cookieObj.isExpired()) { +- this.cookies.push(cookieObj); +- } +- +- // sort by creation date, so when searching, we get the latest created cookies. +- this.cookies.sort(cookieCompare); +- } +- +- /** +- * Gets the first cooking matching the defined properties of a given Cookie or CookieOptions. +- * returns undefined if not found or expired. `creationDate` prop is not checked. +- * Also removes the cookie and returns undefined if cookie is expired. +- */ +- getCookie(options: Cookie | CookieOptions): Cookie | undefined { +- const strictMatch = typeof (options as Cookie).isValid !== "function"; +- for (const [index, cookie] of this.cookies.entries()) { +- if (cookieMatches(options, cookie, strictMatch)) { +- if (!cookie.isExpired()) { +- return cookie; +- } else { +- this.cookies.splice(index, 1); +- return undefined; +- } +- } +- } +- } +- +- /** +- * returnes cookies that matches the options excluding expired ones, also removes expired cookies before returning. +- * @param options - the options to filter cookies with, and if not provided, returnes all cookies. +- * if no cookie is found with given options, an empty array is returned. +- */ +- getCookies(options?: CookieOptions | Cookie) { +- if (options) { +- const matchedCookies: Cookie[] = []; +- const removeCookies: Cookie[] = []; +- for (const cookie of this.cookies) { +- if (cookieMatches(options, cookie)) { +- if (!cookie.isExpired()) { +- matchedCookies.push(cookie); +- } else { +- removeCookies.push(cookie); +- } +- } +- } +- if (removeCookies.length) { +- this.cookies = this.cookies.filter((cookie) => +- !removeCookies.includes(cookie) +- ); +- } +- return matchedCookies; +- } else { +- return this.cookies; +- } +- } +- +- getCookieString(url: string | Request | URL) { +- const searchCookie = new Cookie(); +- searchCookie.setDomain(url); +- const cookiesToSend = this.getCookies(searchCookie) +- .filter((cookie) => { +- return cookie.canSendTo(parseURL(url)); +- }) +- .map((c) => c.getCookieString()) +- .join("; "); +- return cookiesToSend; +- } +- +- toJSON() { +- return this.cookies; +- } +- +- /** +- * Removes first cookie that matches the given option. +- * +- * Returns the deleted cookie if found or undefined otherwise. +- */ +- removeCookie(options: CookieOptions | Cookie): Cookie | undefined { +- for (const [index, cookie] of this.cookies.entries()) { +- if (cookieMatches(options, cookie)) { +- return this.cookies.splice(index, 1)[0]; +- } +- } +- } +- +- /** +- * Removes all cookies that matches the given option. +- * If options is not given, all cookies will be deleted. +- * +- * Returns the deleted cookies if found or undefined otherwise. +- */ +- removeCookies(options?: CookieOptions | Cookie): Array<Cookie> | undefined { +- if (options) { +- const deletedCookies: Cookie[] = []; +- this.cookies = this.cookies.filter((cookie) => { +- if (cookieMatches(options, cookie)) { +- deletedCookies.push(cookie); +- return false; +- } +- return true; +- }); +- return deletedCookies.length ? deletedCookies : undefined; +- } else { +- this.cookies = []; +- } +- } +- +- replaceCookies(cookies?: Array<Cookie> | Array<CookieOptions>) { +- if (cookies?.length) { +- if (typeof (cookies[0] as Cookie).isValid === "function") { +- this.cookies = cookies as Array<Cookie>; +- } else { +- this.cookies = []; +- for (const option of cookies) { +- this.cookies.push(new Cookie(option)); +- } +- } +- } else { +- this.cookies = []; +- } +- } +-} +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie.ts 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/cookie.ts 1970-01-01 12:00:00.000000000 +1200 +@@ -1,450 +0,0 @@ +-// import { } from "./deps.ts"; +- +-// deno-lint-ignore no-control-regex +-const CONTROL_CHARS = /[\x00-\x1F\x7F]/; +- +-// with help from https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie and rfc6265 +-const COOKIE_NAME_BLOCKED = /[()<>@,;:\\"/[\]?={}]/; +- +-// cookie octet should not have control characters, Whitespace, double quotes, comma, semicolon, and backslash +-const COOKIE_OCTET_BLOCKED = /[\s",;\\]/; +-const COOKIE_OCTET = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/; +- +-const TERMINATORS = ["\n", "\r", "\0"]; +- +-/** +- * does not make a difference which one is domainA or domainB +- * +- * according to https://stackoverflow.com/a/30676300/3542461 +- */ +-export function isSameDomainOrSubdomain(domainA?: string, domainB?: string) { +- if (!domainA || !domainB) { +- return false; +- } +- +- let longerDomain; +- let shorterDomain; +- if (domainB.length > domainA.length) { +- longerDomain = domainB; +- shorterDomain = domainA; +- } else { +- longerDomain = domainA; +- shorterDomain = domainB; +- } +- +- // check if it's a subdomain or only partially matched +- const indexOfDomain = longerDomain.indexOf(shorterDomain); +- if (indexOfDomain === -1) { +- return false; +- } else if (indexOfDomain > 0) { +- // if the character behind the part is not a dot, its not a subdomain +- if (longerDomain.charAt(indexOfDomain - 1) !== ".") { +- return false; +- } +- } +- // indexOfDomain === 0 is valid +- +- return true; +-} +- +-// from tough-cookie +-function trimTerminator(str: string) { +- if (str === undefined || str === "") return str; +- for (let t = 0; t < TERMINATORS.length; t++) { +- const terminatorIdx = str.indexOf(TERMINATORS[t]); +- if (terminatorIdx !== -1) { +- str = str.substr(0, terminatorIdx); +- } +- } +- +- return str; +-} +- +-function isValidName(name: string | undefined) { +- if (!name) { +- return false; +- } +- if (CONTROL_CHARS.test(name) || COOKIE_NAME_BLOCKED.test(name)) { +- return false; +- } +- return true; +-} +- +-function trimWrappingDoubleQuotes(val: string) { +- // the value can be wrapped in double quotes, but can't contain double quotes within the value +- if (val.length >= 2 && val.at(0) === '"' && val.at(-1) === '"') { +- return val.slice(1, -1); +- } +- return val; +-} +- +-function isValidValue(val: string | undefined) { +- if (val === "") { +- return true; +- } +- if (!val) { +- return false; +- } +- if ( +- CONTROL_CHARS.test(val) || +- COOKIE_OCTET_BLOCKED.test(val) || +- !COOKIE_OCTET.test(val) +- ) { +- return false; +- } +- +- return true; +-} +- +-export function parseURL(input: string | Request | URL) { +- let copyUrl: string; +- if (input instanceof Request) { +- copyUrl = input.url; +- } else if (input instanceof URL) { +- copyUrl = input.toString(); +- } else { +- copyUrl = input; +- } +- // we *need* to replace the leading dot to simplify usage and expectations +- copyUrl = copyUrl.replace(/^\./, ""); +- if (!copyUrl.includes("://")) { +- // the protocol does not matter, but we default to insecure for use inside canSendTo +- copyUrl = "http://" + copyUrl; +- } +- return new URL(copyUrl); +-} +- +-export type CookieOptions = { +- name?: string; +- value?: string; +- path?: string; +- domain?: string; +- /** in milliseconds */ +- expires?: number; +- /** in seconds */ +- maxAge?: number; +- secure?: boolean; +- httpOnly?: boolean; +- sameSite?: "Lax" | "Strict" | "None"; +- /** used for checking against maxAge */ +- creationDate?: number; +-}; +- +-export class Cookie { +- // important +- name: string | undefined; +- value: string | undefined; +- path: string | undefined; +- domain: string | undefined; +- // expire +- /** in milliseconds */ +- expires: number | undefined; +- /** in seconds */ +- maxAge: number | undefined; +- // other +- secure: boolean | undefined; +- httpOnly: boolean | undefined; +- sameSite: "Lax" | "Strict" | "None" | undefined; +- creationDate = Date.now(); +- // deno-lint-ignore ban-ts-comment +- // @ts-ignore +- creationIndex: number; +- +- static cookiesCreated = 0; +- +- constructor(options?: CookieOptions) { +- if (options) { +- this.name = options.name; +- this.value = options.value; +- this.path = options.path; +- this.domain = options.domain; +- this.expires = options.expires; +- this.maxAge = options.maxAge; +- this.secure = options.secure; +- this.httpOnly = options.httpOnly; +- this.sameSite = options.sameSite; +- +- if (options.creationDate) { +- this.creationDate = options.creationDate; +- } +- } +- +- // used to break creation ties in cookieCompare(): +- Object.defineProperty(this, "creationIndex", { +- configurable: false, +- enumerable: false, // important for assertStrictEquals checks +- writable: true, +- value: ++Cookie.cookiesCreated, +- }); +- } +- +- static from(cookieStr: string) { +- const options = { +- name: undefined, +- value: undefined, +- path: undefined, +- domain: undefined, +- expires: undefined, +- maxAge: undefined, +- secure: undefined, +- httpOnly: undefined, +- sameSite: undefined, +- creationDate: Date.now(), +- } as CookieOptions; +- +- const unparsed = cookieStr.slice().trim(); // copy +- const attrAndValueList = unparsed.split(";"); +- +- // first split is the key value pair, +- // if theres no semicolon in the string, still the first element in array is key value pair +- const keyValuePairString = trimTerminator(attrAndValueList.shift() || "") +- .trim(); +- const keyValuePairEqualsIndex = keyValuePairString.indexOf("="); +- if (keyValuePairEqualsIndex < 0) { +- return new Cookie(); +- } +- const name = keyValuePairString.slice(0, keyValuePairEqualsIndex); +- const value = trimWrappingDoubleQuotes( +- keyValuePairString.slice(keyValuePairEqualsIndex + 1), +- ); +- +- if (!(isValidName(name) && isValidValue(value))) { +- return new Cookie(); +- } +- options.name = name; +- options.value = value; +- +- // now get attributes +- while (attrAndValueList.length) { +- const cookieAV = attrAndValueList.shift()?.trim(); +- if (!cookieAV) { +- // invalid attribute length +- continue; +- } +- +- const avSeperatorIndex = cookieAV.indexOf("="); +- let attrKey, attrValue; +- +- if (avSeperatorIndex === -1) { +- attrKey = cookieAV; +- attrValue = ""; +- } else { +- attrKey = cookieAV.substr(0, avSeperatorIndex); +- attrValue = cookieAV.substr(avSeperatorIndex + 1); +- } +- +- attrKey = attrKey.trim().toLowerCase(); +- +- if (attrValue) { +- attrValue = attrValue.trim(); +- } +- +- switch (attrKey) { +- case "expires": +- if (attrValue) { +- const expires = new Date(attrValue).getTime(); +- if (expires && !isNaN(expires)) { +- options.expires = expires; +- } +- } +- break; +- +- case "max-age": +- if (attrValue) { +- const maxAge = parseInt(attrValue, 10); +- if (!isNaN(maxAge)) { +- options.maxAge = maxAge; +- } +- } +- break; +- +- case "domain": +- if (attrValue) { +- const domain = parseURL(attrValue).host; +- if (domain) { +- options.domain = domain; +- } +- } +- break; +- +- case "path": +- if (attrValue) { +- options.path = attrValue.startsWith("/") +- ? attrValue +- : "/" + attrValue; +- } +- break; +- +- case "secure": +- options.secure = true; +- break; +- +- case "httponly": +- options.httpOnly = true; +- break; +- +- case "samesite": { +- const lowerCasedSameSite = attrValue.toLowerCase(); +- switch (lowerCasedSameSite) { +- case "strict": +- options.sameSite = "Strict"; +- break; +- case "lax": +- options.sameSite = "Lax"; +- break; +- case "none": +- options.sameSite = "None"; +- break; +- default: +- break; +- } +- break; +- } +- // unknown attribute +- default: +- break; +- } +- } +- +- return new Cookie(options); +- } +- +- isValid(): boolean { +- return isValidName(this.name) && isValidValue(this.value); +- } +- +- /** +- * @param url - the url that we are checking against +- */ +- canSendTo(url: string | Request | URL) { +- const urlObj = parseURL(url); +- +- if (this.secure && urlObj.protocol !== "https:") { +- return false; +- } +- +- if (this.sameSite === "None" && !this.secure) return false; +- +- if (this.path) { +- if ( +- this.path === urlObj.pathname // identical +- ) { +- return true; +- } +- if ( +- urlObj.pathname.startsWith(this.path) && +- this.path[this.path.length - 1] === "/" // any sub path after a '/' +- ) { +- return true; +- } +- if ( +- this.path.length < urlObj.pathname.length && +- urlObj.pathname.startsWith(this.path) && +- urlObj.pathname[this.path.length] === "/" +- ) { +- return true; +- // this one was a bit tricky to understand for me +- // quick explain: +- // imagin two path where A is the cookie path and B and C is the requested paths: +- // A: /foo +- // B: /foo/bar --> true +- // C: /foobar ---> false +- // Difference with previous if ? very slight difference, A is /foo/ instead of /foo in the example +- } +- +- return false; +- } +- +- if (this.domain) { +- const host = urlObj.host; // 'host' includes port number, if specified +- if (isSameDomainOrSubdomain(this.domain, host)) { +- return true; +- } +- } +- +- return false; +- } +- +- getCookieString() { +- return `${this.name || ""}=${this.value || ""}`; +- } +- +- setDomain(url: string | Request | URL) { +- this.domain = parseURL(url).host; +- } +- +- setPath(url: string | Request | URL) { +- // https://www.rfc-editor.org/rfc/rfc6265#section-5.1.4 +- const uriPath = parseURL(url).pathname; // step 1 +- +- if (!uriPath || uriPath[0] !== "/") { // step 2 +- this.path = "/"; +- } else { +- const rightmostSlashIdx = uriPath.lastIndexOf("/"); +- if (rightmostSlashIdx <= 0) { // step 3 +- this.path = "/"; +- } else { // step 4 +- this.path = uriPath.slice(0, rightmostSlashIdx); +- } +- } +- } +- +- setExpires(exp: Date | number) { +- if (exp instanceof Date) { +- this.expires = exp.getTime(); +- } else if (typeof exp === "number" && exp >= 0) { +- this.expires = exp; +- } +- } +- +- isExpired() { +- if (this.maxAge !== undefined) { +- if (Date.now() - this.creationDate >= this.maxAge * 1000) { +- return true; +- } +- } +- if (this.expires !== undefined) { +- // now is past beyond the expire +- if (Date.now() - this.expires >= 0) { +- return true; +- } +- } +- +- return false; +- } +- +- toString() { +- let str = this.getCookieString(); +- +- if (this.expires && this.expires !== Infinity) { +- str += "; Expires=" + (new Date(this.expires)).toUTCString(); +- } +- +- if (this.maxAge && this.maxAge !== Infinity) { +- str += `; Max-Age=${this.maxAge}`; +- } +- +- if (this.domain) { +- str += `; Domain=${this.domain}`; +- } +- if (this.path) { +- str += `; Path=${this.path}`; +- } +- +- if (this.secure) { +- str += "; Secure"; +- } +- if (this.httpOnly) { +- str += "; HttpOnly"; +- } +- if (this.sameSite) { +- str += `; SameSite=${this.sameSite}`; +- } +- +- return str; +- } +- +- clone() { +- return new Cookie(JSON.parse(JSON.stringify(this))); +- } +-} +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/fetch_wrapper.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/fetch_wrapper.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/fetch_wrapper.ts 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/fetch_wrapper.ts 1970-01-01 12:00:00.000000000 +1200 +@@ -1,50 +0,0 @@ +-import { CookieJar } from "./cookie_jar.ts"; +- +-export type WrapFetchOptions = { +- /** your own fetch function. defaults to global fetch. This allows wrapping your fetch function multiple times. */ +- fetch?: typeof fetch; +- /** The cookie jar to use when wrapping fetch. Will create a new one if not provided. */ +- cookieJar?: CookieJar; +-}; +- +-type FetchParameters = Parameters<typeof fetch>; +- +-export function wrapFetch(options?: WrapFetchOptions): typeof fetch { +- const { cookieJar = new CookieJar(), fetch = globalThis.fetch } = options || +- {}; +- +- async function wrappedFetch( +- input: FetchParameters[0], +- init?: FetchParameters[1], +- ) { +- // let fetch handle the error +- if (!input) { +- return await fetch(input); +- } +- const cookieString = cookieJar.getCookieString(input); +- +- let interceptedInit: RequestInit; +- if (init) { +- interceptedInit = init; +- } else if (input instanceof Request) { +- interceptedInit = input; +- } else { +- interceptedInit = {}; +- } +- +- if (!(interceptedInit.headers instanceof Headers)) { +- interceptedInit.headers = new Headers(interceptedInit.headers || {}); +- } +- interceptedInit.headers.set("cookie", cookieString); +- +- const response = await fetch(input, interceptedInit); +- response.headers.forEach((value, key) => { +- if (key.toLowerCase() === "set-cookie") { +- cookieJar.setCookie(value, input); +- } +- }); +- return response; +- } +- +- return wrappedFetch; +-} +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/mod.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/mod.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v4.1.4/mod.ts 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v4.1.4/mod.ts 1970-01-01 12:00:00.000000000 +1200 +@@ -1,4 +0,0 @@ +-export { Cookie } from "./cookie.ts"; +-export type { CookieOptions } from "./cookie.ts"; +-export { CookieJar } from "./cookie_jar.ts"; +-export * from "./fetch_wrapper.ts"; +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie_jar.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie_jar.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie_jar.ts 1970-01-01 12:00:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie_jar.ts 2023-02-27 16:31:36.000000000 +1300 +@@ -0,0 +1,264 @@ ++import { ++ Cookie, ++ CookieOptions, ++ isSameDomainOrSubdomain, ++ parseURL, ++} from "./cookie.ts"; ++ ++const strictMatchProps = [ ++ "value", ++ "secure", ++ "httpOnly", ++ "maxAge", ++ "expires", ++ "sameSite", ++]; ++ ++function cookieMatches( ++ options: Cookie | CookieOptions, ++ comparedWith: Cookie, ++ strictMatch = false, ++): boolean { ++ if ( ++ options.path !== undefined && !comparedWith.path?.startsWith(options.path) ++ ) { ++ return false; ++ } ++ ++ if (options.domain) { ++ if (!isSameDomainOrSubdomain(options.domain, comparedWith.domain)) { ++ return false; ++ } ++ } ++ ++ if ( ++ options.name !== undefined && ++ options.name !== comparedWith.name ++ ) { ++ return false; ++ } ++ ++ if ( ++ strictMatch && ++ strictMatchProps.some((propKey) => ++ // deno-lint-ignore ban-ts-comment ++ // @ts-ignore ++ options[propKey] !== undefined && ++ // deno-lint-ignore ban-ts-comment ++ // @ts-ignore ++ options[propKey] !== comparedWith[propKey] ++ ) ++ ) { ++ return false; ++ } ++ ++ return true; ++} ++ ++// cookie compare from tough-cookie ++const MAX_TIME = 2147483647000; // 31-bit max ++/** ++ * Cookies with longer paths are listed before cookies with ++ * shorter paths. ++ * ++ * Among cookies that have equal-length path fields, cookies with ++ * earlier creation-times are listed before cookies with later ++ * creation-times." ++ */ ++function cookieCompare(a: Cookie, b: Cookie) { ++ let cmp = 0; ++ ++ // descending for length: b CMP a ++ const aPathLen = a.path?.length || 0; ++ const bPathLen = b.path?.length || 0; ++ cmp = bPathLen - aPathLen; ++ if (cmp !== 0) { ++ return cmp; ++ } ++ ++ // ascending for time: a CMP b ++ const aTime = a.creationDate || MAX_TIME; ++ const bTime = b.creationDate || MAX_TIME; ++ cmp = aTime - bTime; ++ if (cmp !== 0) { ++ return cmp; ++ } ++ ++ // tie breaker ++ cmp = a.creationIndex - b.creationIndex; ++ ++ return cmp; ++} ++ ++export class CookieJar { ++ cookies = Array<Cookie>(); ++ ++ /** ++ * @param cookies - the cookies array to initialize with ++ */ ++ constructor(cookies?: Array<Cookie> | Array<CookieOptions>) { ++ this.replaceCookies(cookies); ++ } ++ ++ /** ++ * Sets or replaces a cookie inside the jar. ++ * Only sets new cookies if cookie is valid and not expired. ++ * Validation and expiration checks are not run when replacing a cookie. ++ * @param url - the url that this cookie from received from. mainly used by the fetch wrapper. ++ * will automatically set domain and path if provided and it was not found inside Cookie/cookiestring. ++ */ ++ setCookie(cookie: Cookie | string, url?: string | Request | URL) { ++ let cookieObj; ++ if (typeof cookie === "string") { ++ cookieObj = Cookie.from(cookie); ++ } else { ++ cookieObj = cookie; ++ } ++ if (url) { ++ if (!cookieObj.domain) { ++ cookieObj.setDomain(url); ++ } ++ if (!cookieObj.path) { ++ cookieObj.setPath(url); ++ } ++ } ++ ++ if (!cookieObj.isValid()) { ++ return; ++ } ++ ++ const foundCookie = this.getCookie(cookieObj); ++ if (foundCookie) { ++ const indexOfCookie = this.cookies.indexOf(foundCookie); ++ if (!cookieObj.isExpired()) { ++ this.cookies.splice(indexOfCookie, 1, cookieObj); ++ } else { ++ this.cookies.splice(indexOfCookie, 1); ++ } ++ } else if (!cookieObj.isExpired()) { ++ this.cookies.push(cookieObj); ++ } ++ ++ // sort by creation date, so when searching, we get the latest created cookies. ++ this.cookies.sort(cookieCompare); ++ } ++ ++ /** ++ * Gets the first cooking matching the defined properties of a given Cookie or CookieOptions. ++ * returns undefined if not found or expired. `creationDate` prop is not checked. ++ * Also removes the cookie and returns undefined if cookie is expired. ++ */ ++ getCookie(options: Cookie | CookieOptions): Cookie | undefined { ++ const strictMatch = typeof (options as Cookie).isValid !== "function"; ++ for (const [index, cookie] of this.cookies.entries()) { ++ if (cookieMatches(options, cookie, strictMatch)) { ++ if (!cookie.isExpired()) { ++ return cookie; ++ } else { ++ this.cookies.splice(index, 1); ++ return undefined; ++ } ++ } ++ } ++ } ++ ++ /** ++ * Returns cookies that match the options excluding expired ones, also removes expired cookies before returning. ++ * @param options - the options to filter cookies with, and if not provided, returnes all cookies. ++ * if no cookie is found with given options, an empty array is returned. ++ */ ++ getCookies(options?: CookieOptions | Cookie) { ++ if (options) { ++ const matchedCookies: Cookie[] = []; ++ const removeCookies: Cookie[] = []; ++ for (const cookie of this.cookies) { ++ if (cookieMatches(options, cookie)) { ++ if (!cookie.isExpired()) { ++ matchedCookies.push(cookie); ++ } else { ++ removeCookies.push(cookie); ++ } ++ } ++ } ++ if (removeCookies.length) { ++ this.cookies = this.cookies.filter((cookie) => ++ !removeCookies.includes(cookie) ++ ); ++ } ++ return matchedCookies; ++ } else { ++ return this.cookies; ++ } ++ } ++ ++ /** ++ * Converts the cookies to a string that can be used in a request. ++ * @param url - the url to get the cookies for. if provided, will only return cookies that match the domain and path of the url. ++ * @returns string of all cookies that match the url, in the from of `<cookie-name>=<cookie-value>` seperated by `; ` ++ */ ++ getCookieString(url: string | Request | URL) { ++ const searchCookie = new Cookie(); ++ searchCookie.setDomain(url); ++ const cookiesToSend = this.getCookies(searchCookie) ++ .filter((cookie) => { ++ return cookie.canSendTo(parseURL(url)); ++ }) ++ .map((c) => c.getCookieString()) ++ .join("; "); ++ return cookiesToSend; ++ } ++ ++ toJSON() { ++ return this.cookies; ++ } ++ ++ /** ++ * Removes first cookie that matches the given option. ++ * ++ * Returns the deleted cookie if found or undefined otherwise. ++ */ ++ removeCookie(options: CookieOptions | Cookie): Cookie | undefined { ++ for (const [index, cookie] of this.cookies.entries()) { ++ if (cookieMatches(options, cookie)) { ++ return this.cookies.splice(index, 1)[0]; ++ } ++ } ++ } ++ ++ /** ++ * Removes all cookies that matches the given option. ++ * If options is not given, all cookies will be deleted. ++ * ++ * Returns the deleted cookies if found or undefined otherwise. ++ */ ++ removeCookies(options?: CookieOptions | Cookie): Array<Cookie> | undefined { ++ if (options) { ++ const deletedCookies: Cookie[] = []; ++ this.cookies = this.cookies.filter((cookie) => { ++ if (cookieMatches(options, cookie)) { ++ deletedCookies.push(cookie); ++ return false; ++ } ++ return true; ++ }); ++ return deletedCookies.length ? deletedCookies : undefined; ++ } else { ++ this.cookies = []; ++ } ++ } ++ ++ replaceCookies(cookies?: Array<Cookie> | Array<CookieOptions>) { ++ if (cookies?.length) { ++ if (typeof (cookies[0] as Cookie).isValid === "function") { ++ this.cookies = cookies as Array<Cookie>; ++ } else { ++ this.cookies = []; ++ for (const option of cookies) { ++ this.cookies.push(new Cookie(option)); ++ } ++ } ++ } else { ++ this.cookies = []; ++ } ++ } ++} +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie.ts 1970-01-01 12:00:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/cookie.ts 2023-02-27 16:31:36.000000000 +1300 +@@ -0,0 +1,452 @@ ++// import { } from "./deps.ts"; ++ ++// deno-lint-ignore no-control-regex ++const CONTROL_CHARS = /[\x00-\x1F\x7F]/; ++ ++// with help from https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie and rfc6265 ++const COOKIE_NAME_BLOCKED = /[()<>@,;:\\"/[\]?={}]/; ++ ++// cookie octet should not have control characters, Whitespace, double quotes, comma, semicolon, and backslash ++const COOKIE_OCTET_BLOCKED = /[\s",;\\]/; ++const COOKIE_OCTET = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/; ++ ++const TERMINATORS = ["\n", "\r", "\0"]; ++ ++/** ++ * does not make a difference which one is domainA or domainB ++ * ++ * according to https://stackoverflow.com/a/30676300/3542461 ++ */ ++export function isSameDomainOrSubdomain(domainA?: string, domainB?: string) { ++ if (!domainA || !domainB) { ++ return false; ++ } ++ ++ let longerDomain; ++ let shorterDomain; ++ if (domainB.length > domainA.length) { ++ longerDomain = domainB; ++ shorterDomain = domainA; ++ } else { ++ longerDomain = domainA; ++ shorterDomain = domainB; ++ } ++ ++ // check if it's a subdomain or only partially matched ++ const indexOfDomain = longerDomain.indexOf(shorterDomain); ++ if (indexOfDomain === -1) { ++ return false; ++ } else if (indexOfDomain > 0) { ++ // if the character behind the part is not a dot, its not a subdomain ++ if (longerDomain.charAt(indexOfDomain - 1) !== ".") { ++ return false; ++ } ++ } ++ // indexOfDomain === 0 is valid ++ ++ return true; ++} ++ ++// from tough-cookie ++function trimTerminator(str: string) { ++ if (str === undefined || str === "") return str; ++ for (let t = 0; t < TERMINATORS.length; t++) { ++ const terminatorIdx = str.indexOf(TERMINATORS[t]); ++ if (terminatorIdx !== -1) { ++ str = str.substr(0, terminatorIdx); ++ } ++ } ++ ++ return str; ++} ++ ++function isValidName(name: string | undefined) { ++ if (!name) { ++ return false; ++ } ++ if (CONTROL_CHARS.test(name) || COOKIE_NAME_BLOCKED.test(name)) { ++ return false; ++ } ++ return true; ++} ++ ++function trimWrappingDoubleQuotes(val: string) { ++ // the value can be wrapped in double quotes, but can't contain double quotes within the value ++ if (val.length >= 2 && val.at(0) === '"' && val.at(-1) === '"') { ++ return val.slice(1, -1); ++ } ++ return val; ++} ++ ++function isValidValue(val: string | undefined) { ++ if (val === "") { ++ return true; ++ } ++ if (!val) { ++ return false; ++ } ++ if ( ++ CONTROL_CHARS.test(val) || ++ COOKIE_OCTET_BLOCKED.test(val) || ++ !COOKIE_OCTET.test(val) ++ ) { ++ return false; ++ } ++ ++ return true; ++} ++ ++export function parseURL(input: string | Request | URL) { ++ let copyUrl: string; ++ if (input instanceof Request) { ++ copyUrl = input.url; ++ } else if (input instanceof URL) { ++ copyUrl = input.toString(); ++ } else { ++ copyUrl = input; ++ } ++ // we *need* to replace the leading dot to simplify usage and expectations ++ copyUrl = copyUrl.replace(/^\./, ""); ++ if (!copyUrl.includes("://")) { ++ // the protocol does not matter, but we default to insecure for use inside canSendTo ++ copyUrl = "http://" + copyUrl; ++ } ++ return new URL(copyUrl); ++} ++ ++export type CookieOptions = { ++ name?: string; ++ value?: string; ++ path?: string; ++ domain?: string; ++ /** in milliseconds */ ++ expires?: number; ++ /** in seconds */ ++ maxAge?: number; ++ secure?: boolean; ++ httpOnly?: boolean; ++ sameSite?: "Lax" | "Strict" | "None"; ++ /** used for checking against maxAge */ ++ creationDate?: number; ++}; ++ ++export class Cookie { ++ // important ++ name: string | undefined; ++ value: string | undefined; ++ path: string | undefined; ++ domain: string | undefined; ++ // expire ++ /** in milliseconds */ ++ expires: number | undefined; ++ /** in seconds */ ++ maxAge: number | undefined; ++ // other ++ secure: boolean | undefined; ++ httpOnly: boolean | undefined; ++ sameSite: "Lax" | "Strict" | "None" | undefined; ++ creationDate = Date.now(); ++ // deno-lint-ignore ban-ts-comment ++ // @ts-ignore ++ creationIndex: number; ++ ++ static cookiesCreated = 0; ++ ++ constructor(options?: CookieOptions) { ++ if (options) { ++ this.name = options.name; ++ this.value = options.value; ++ this.path = options.path; ++ this.domain = options.domain; ++ this.expires = options.expires; ++ this.maxAge = options.maxAge; ++ this.secure = options.secure; ++ this.httpOnly = options.httpOnly; ++ this.sameSite = options.sameSite; ++ ++ if (options.creationDate) { ++ this.creationDate = options.creationDate; ++ } ++ } ++ ++ // used to break creation ties in cookieCompare(): ++ Object.defineProperty(this, "creationIndex", { ++ configurable: false, ++ enumerable: false, // important for assertStrictEquals checks ++ writable: true, ++ value: ++Cookie.cookiesCreated, ++ }); ++ } ++ ++ static from(cookieStr: string) { ++ const options = { ++ name: undefined, ++ value: undefined, ++ path: undefined, ++ domain: undefined, ++ expires: undefined, ++ maxAge: undefined, ++ secure: undefined, ++ httpOnly: undefined, ++ sameSite: undefined, ++ creationDate: Date.now(), ++ } as CookieOptions; ++ ++ const unparsed = cookieStr.slice().trim(); // copy ++ const attrAndValueList = unparsed.split(";"); ++ ++ // first split is the key value pair, ++ // if theres no semicolon in the string, still the first element in array is key value pair ++ const keyValuePairString = trimTerminator(attrAndValueList.shift() || "") ++ .trim(); ++ const keyValuePairEqualsIndex = keyValuePairString.indexOf("="); ++ if (keyValuePairEqualsIndex < 0) { ++ return new Cookie(); ++ } ++ const name = keyValuePairString.slice(0, keyValuePairEqualsIndex); ++ const value = trimWrappingDoubleQuotes( ++ keyValuePairString.slice(keyValuePairEqualsIndex + 1), ++ ); ++ ++ if (!(isValidName(name) && isValidValue(value))) { ++ return new Cookie(); ++ } ++ options.name = name; ++ options.value = value; ++ ++ // now get attributes ++ while (attrAndValueList.length) { ++ const cookieAV = attrAndValueList.shift()?.trim(); ++ if (!cookieAV) { ++ // invalid attribute length ++ continue; ++ } ++ ++ const avSeperatorIndex = cookieAV.indexOf("="); ++ let attrKey, attrValue; ++ ++ if (avSeperatorIndex === -1) { ++ attrKey = cookieAV; ++ attrValue = ""; ++ } else { ++ attrKey = cookieAV.substr(0, avSeperatorIndex); ++ attrValue = cookieAV.substr(avSeperatorIndex + 1); ++ } ++ ++ attrKey = attrKey.trim().toLowerCase(); ++ ++ if (attrValue) { ++ attrValue = attrValue.trim(); ++ } ++ ++ switch (attrKey) { ++ case "expires": ++ if (attrValue) { ++ const expires = new Date(attrValue).getTime(); ++ if (expires && !isNaN(expires)) { ++ options.expires = expires; ++ } ++ } ++ break; ++ ++ case "max-age": ++ if (attrValue) { ++ const maxAge = parseInt(attrValue, 10); ++ if (!isNaN(maxAge)) { ++ options.maxAge = maxAge; ++ } ++ } ++ break; ++ ++ case "domain": ++ if (attrValue) { ++ const domain = parseURL(attrValue).hostname; ++ if (domain) { ++ options.domain = domain; ++ } ++ } ++ break; ++ ++ case "path": ++ if (attrValue) { ++ options.path = attrValue.startsWith("/") ++ ? attrValue ++ : "/" + attrValue; ++ } ++ break; ++ ++ case "secure": ++ options.secure = true; ++ break; ++ ++ case "httponly": ++ options.httpOnly = true; ++ break; ++ ++ case "samesite": { ++ const lowerCasedSameSite = attrValue.toLowerCase(); ++ switch (lowerCasedSameSite) { ++ case "strict": ++ options.sameSite = "Strict"; ++ break; ++ case "lax": ++ options.sameSite = "Lax"; ++ break; ++ case "none": ++ options.sameSite = "None"; ++ break; ++ default: ++ break; ++ } ++ break; ++ } ++ // unknown attribute ++ default: ++ break; ++ } ++ } ++ ++ return new Cookie(options); ++ } ++ ++ isValid(): boolean { ++ return isValidName(this.name) && isValidValue(this.value); ++ } ++ ++ /** ++ * @param url - the url that we are checking against ++ */ ++ canSendTo(url: string | Request | URL) { ++ const urlObj = parseURL(url); ++ ++ if (this.secure && urlObj.protocol !== "https:") { ++ return false; ++ } ++ ++ if (this.sameSite === "None" && !this.secure) return false; ++ ++ if (this.path) { ++ if ( ++ this.path === urlObj.pathname // identical ++ ) { ++ return true; ++ } ++ if ( ++ urlObj.pathname.startsWith(this.path) && ++ this.path[this.path.length - 1] === "/" // any sub path after a '/' ++ ) { ++ return true; ++ } ++ if ( ++ this.path.length < urlObj.pathname.length && ++ urlObj.pathname.startsWith(this.path) && ++ urlObj.pathname[this.path.length] === "/" ++ ) { ++ return true; ++ // this one was a bit tricky to understand for me ++ // quick explain: ++ // imagin two path where A is the cookie path and B and C is the requested paths: ++ // A: /foo ++ // B: /foo/bar --> true ++ // C: /foobar ---> false ++ // Difference with previous if ? very slight difference, A is /foo/ instead of /foo in the example ++ } ++ ++ return false; ++ } ++ ++ if (this.domain) { ++ // according to rfc 6265 8.5. Weak Confidentiality, ++ // port should not matter, hence the usage of 'hostname' over 'host' ++ const hostname = urlObj.hostname; // 'host' includes port number, if specified, hostname does not ++ if (isSameDomainOrSubdomain(this.domain, hostname)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ getCookieString() { ++ return `${this.name || ""}=${this.value || ""}`; ++ } ++ ++ setDomain(url: string | Request | URL) { ++ this.domain = parseURL(url).hostname; ++ } ++ ++ setPath(url: string | Request | URL) { ++ // https://www.rfc-editor.org/rfc/rfc6265#section-5.1.4 ++ const uriPath = parseURL(url).pathname; // step 1 ++ ++ if (!uriPath || uriPath[0] !== "/") { // step 2 ++ this.path = "/"; ++ } else { ++ const rightmostSlashIdx = uriPath.lastIndexOf("/"); ++ if (rightmostSlashIdx <= 0) { // step 3 ++ this.path = "/"; ++ } else { // step 4 ++ this.path = uriPath.slice(0, rightmostSlashIdx); ++ } ++ } ++ } ++ ++ setExpires(exp: Date | number) { ++ if (exp instanceof Date) { ++ this.expires = exp.getTime(); ++ } else if (typeof exp === "number" && exp >= 0) { ++ this.expires = exp; ++ } ++ } ++ ++ isExpired() { ++ if (this.maxAge !== undefined) { ++ if (Date.now() - this.creationDate >= this.maxAge * 1000) { ++ return true; ++ } ++ } ++ if (this.expires !== undefined) { ++ // now is past beyond the expire ++ if (Date.now() - this.expires >= 0) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ toString() { ++ let str = this.getCookieString(); ++ ++ if (this.expires && this.expires !== Infinity) { ++ str += "; Expires=" + (new Date(this.expires)).toUTCString(); ++ } ++ ++ if (this.maxAge && this.maxAge !== Infinity) { ++ str += `; Max-Age=${this.maxAge}`; ++ } ++ ++ if (this.domain) { ++ str += `; Domain=${this.domain}`; ++ } ++ if (this.path) { ++ str += `; Path=${this.path}`; ++ } ++ ++ if (this.secure) { ++ str += "; Secure"; ++ } ++ if (this.httpOnly) { ++ str += "; HttpOnly"; ++ } ++ if (this.sameSite) { ++ str += `; SameSite=${this.sameSite}`; ++ } ++ ++ return str; ++ } ++ ++ clone() { ++ return new Cookie(JSON.parse(JSON.stringify(this))); ++ } ++} +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/fetch_wrapper.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/fetch_wrapper.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/fetch_wrapper.ts 1970-01-01 12:00:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/fetch_wrapper.ts 2023-02-27 16:31:36.000000000 +1300 +@@ -0,0 +1,145 @@ ++import { CookieJar } from "./cookie_jar.ts"; ++ ++// Max 20 redirects is fetch default setting ++const MAX_REDIRECT = 20; ++ ++export type WrapFetchOptions = { ++ /** your own fetch function. defaults to global fetch. This allows wrapping your fetch function multiple times. */ ++ fetch?: typeof fetch; ++ /** The cookie jar to use when wrapping fetch. Will create a new one if not provided. */ ++ cookieJar?: CookieJar; ++}; ++ ++interface ExtendedRequestInit extends RequestInit { ++ redirectCount?: number; ++} ++ ++const redirectStatus = new Set([301, 302, 303, 307, 308]); ++ ++function isRedirect(status: number): boolean { ++ return redirectStatus.has(status); ++} ++ ++// Credit <https://github.com/node-fetch/node-fetch/blob/5e78af3ba7555fa1e466e804b2e51c5b687ac1a2/src/utils/is.js#L68>. ++function isDomainOrSubdomain(destination: string, original: string): boolean { ++ const orig = new URL(original).hostname; ++ const dest = new URL(destination).hostname; ++ ++ return orig === dest || orig.endsWith(`.${dest}`); ++} ++ ++export function wrapFetch(options?: WrapFetchOptions): typeof fetch { ++ const { cookieJar = new CookieJar(), fetch = globalThis.fetch } = options || ++ {}; ++ ++ async function wrappedFetch( ++ input: RequestInfo | URL, ++ init?: ExtendedRequestInit, ++ ): Promise<Response> { ++ // let fetch handle the error ++ if (!input) { ++ return await fetch(input); ++ } ++ const cookieString = cookieJar.getCookieString(input); ++ ++ let originalRedirectOption: ExtendedRequestInit["redirect"]; ++ const originalRequestUrl: string = (input as Request).url || ++ input.toString(); ++ ++ if (input instanceof Request) { ++ originalRedirectOption = input.redirect; ++ } ++ if (init?.redirect) { ++ originalRedirectOption = init?.redirect; ++ } ++ ++ const interceptedInit: ExtendedRequestInit = { ++ ...init, ++ redirect: "manual", ++ }; ++ ++ const reqHeaders = new Headers((input as Request).headers || {}); ++ ++ if (init?.headers) { ++ new Headers(init.headers).forEach((value, key) => { ++ reqHeaders.set(key, value); ++ }); ++ } ++ ++ reqHeaders.set("cookie", cookieString); ++ reqHeaders.delete("cookie2"); // Remove cookie2 if it exists, It's deprecated ++ ++ interceptedInit.headers = reqHeaders; ++ ++ const response = await fetch(input, interceptedInit as RequestInit); ++ ++ response.headers.forEach((value, key) => { ++ if (key.toLowerCase() === "set-cookie") { ++ cookieJar.setCookie(value, response.url); ++ } ++ }); ++ ++ const redirectCount = interceptedInit.redirectCount ?? 0; ++ const redirectUrl = response.headers.has("location") ++ ? new URL( ++ response.headers.get("location")!.toString(), ++ originalRequestUrl, ++ ).toString() ++ : undefined; ++ ++ // Do this check here to allow tail recursion of redirect. ++ if (redirectCount > 0) { ++ Object.defineProperty(response, "redirected", { value: true }); ++ } ++ ++ if ( ++ // Return if response is not redirect ++ !isRedirect(response.status) || ++ // or location is not set ++ !redirectUrl || ++ // or if it's the first request and request.redirect is set to 'manual' ++ (redirectCount === 0 && originalRedirectOption === "manual") ++ ) { ++ return response; ++ } ++ ++ if (originalRedirectOption === "error") { ++ await response.body?.cancel(); ++ throw new TypeError( ++ `URI requested responded with a redirect and redirect mode is set to error: ${response.url}`, ++ ); ++ } ++ ++ // If maximum redirects are reached throw error ++ if (redirectCount >= MAX_REDIRECT) { ++ await response.body?.cancel(); ++ throw new TypeError( ++ `Reached maximum redirect of ${MAX_REDIRECT} for URL: ${response.url}`, ++ ); ++ } ++ ++ await response.body?.cancel(); ++ ++ interceptedInit.redirectCount = redirectCount + 1; ++ ++ const filteredHeaders = new Headers(interceptedInit.headers); ++ ++ // Do not forward sensitive headers to third-party domains. ++ if (!isDomainOrSubdomain(originalRequestUrl, redirectUrl)) { ++ for (const name of ["authorization", "www-authenticate"]) { // cookie headers are handled differently ++ filteredHeaders.delete(name); ++ } ++ } ++ ++ if (interceptedInit.method === "POST") { ++ filteredHeaders.delete("content-length"); ++ interceptedInit.method = "GET"; ++ interceptedInit.body = undefined; ++ } ++ interceptedInit.headers = filteredHeaders; ++ ++ return await wrappedFetch(redirectUrl, interceptedInit as RequestInit); ++ } ++ ++ return wrappedFetch; ++} +diff -Nru quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/mod.ts quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/mod.ts +--- quarto-cli-1.4.250.original/src/vendor/deno.land/x/another_cookiejar@v5.0.3/mod.ts 1970-01-01 12:00:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/deno.land/x/another_cookiejar@v5.0.3/mod.ts 2023-02-27 16:31:36.000000000 +1300 +@@ -0,0 +1,4 @@ ++export { Cookie } from "./cookie.ts"; ++export type { CookieOptions } from "./cookie.ts"; ++export { CookieJar } from "./cookie_jar.ts"; ++export * from "./fetch_wrapper.ts"; +diff -Nru quarto-cli-1.4.250.original/src/vendor/import_map.json quarto-cli-1.4.250/src/vendor/import_map.json +--- quarto-cli-1.4.250.original/src/vendor/import_map.json 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/vendor/import_map.json 2023-07-22 10:18:46.244042638 +1200 +@@ -81,7 +81,7 @@ + "crypto/mod.ts": "./deno.land/std@0.185.0/crypto/mod.ts", + "encoding/hex.ts": "./deno.land/std@0.185.0/encoding/hex.ts", + "cliffy/prompt/secret.ts": "./deno.land/x/cliffy@v0.25.4/prompt/secret.ts", +- "another_cookiejar/mod.ts": "./deno.land/x/another_cookiejar@v4.1.4/mod.ts", ++ "another_cookiejar/mod.ts": "./deno.land/x/another_cookiejar@v5.0.3/mod.ts", + "binary-search-bounds": "./cdn.skypack.dev/binary-search-bounds@2.0.5.js", + "testing/asserts.ts": "./deno.land/std@0.185.0/testing/asserts.ts", + "https://deno.land/std@0.161.0/fmt/colors.ts": "./deno.land/std@0.185.0/fmt/colors.ts", diff --git a/001_vendor_patch_2.diff b/001_vendor_patch_2.diff new file mode 100644 index 000000000000..38af763c0241 --- /dev/null +++ b/001_vendor_patch_2.diff @@ -0,0 +1,33 @@ +diff -Nu quarto-cli-1.4.250.original/src/dev_import_map.json quarto-cli-1.4.250/src/dev_import_map.json +--- quarto-cli-1.4.250.original/src/dev_import_map.json 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/dev_import_map.json 2023-07-22 10:18:23.820831240 +1200 +@@ -30,7 +30,7 @@ + "deno_dom/": "./vendor/deno.land/x/deno_dom@v0.1.35-alpha/", + "xmlp/": "./vendor/deno.land/x/xmlp@v0.2.8/", + "xml/": "./vendor/deno.land/x/xml@2.1.1/", +- "another_cookiejar/": "./vendor/deno.land/x/another_cookiejar@v4.1.4/", ++ "another_cookiejar/": "./vendor/deno.land/x/another_cookiejar@v5.0.3/", + "semver/": "./vendor/deno.land/x/semver@v1.4.0/", + "media_types/": "./vendor/deno.land/x/media_types@v2.10.1/", + "dayjs/": "./vendor/cdn.skypack.dev/dayjs@1.8.21/", +@@ -125,7 +125,7 @@ + "crypto/mod.ts": "./vendor/deno.land/std@0.185.0/crypto/mod.ts", + "encoding/hex.ts": "./vendor/deno.land/std@0.185.0/encoding/hex.ts", + "cliffy/prompt/secret.ts": "./vendor/deno.land/x/cliffy@v0.25.4/prompt/secret.ts", +- "another_cookiejar/mod.ts": "./vendor/deno.land/x/another_cookiejar@v4.1.4/mod.ts", ++ "another_cookiejar/mod.ts": "./vendor/deno.land/x/another_cookiejar@v5.0.3/mod.ts", + "testing/asserts.ts": "./vendor/deno.land/std@0.185.0/testing/asserts.ts", + "https://deno.land/std@0.161.0/fmt/colors.ts": "./vendor/deno.land/std@0.185.0/fmt/colors.ts", + "https://deno.land/std@0.161.0/encoding/base64.ts": "./vendor/deno.land/std@0.185.0/encoding/base64.ts", +diff -Nu quarto-cli-1.4.250.original/src/import_map.json quarto-cli-1.4.250/src/import_map.json +--- quarto-cli-1.4.250.original/src/import_map.json 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/import_map.json 2023-07-22 10:18:34.027442398 +1200 +@@ -30,7 +30,7 @@ + "deno_dom/": "https://deno.land/x/deno_dom@v0.1.35-alpha/", + "xmlp/": "https://deno.land/x/xmlp@v0.2.8/", + "xml/": "https://deno.land/x/xml@2.1.1/", +- "another_cookiejar/": "https://deno.land/x/another_cookiejar@v4.1.4/", ++ "another_cookiejar/": "https://deno.land/x/another_cookiejar@v5.0.3/", + "semver/": "https://deno.land/x/semver@v1.4.0/", + "media_types/": "https://deno.land/x/media_types@v2.10.1/", + "dayjs/": "https://cdn.skypack.dev/dayjs@1.8.21/", diff --git a/002_multi_def_patch_1.diff b/002_multi_def_patch_1.diff new file mode 100644 index 000000000000..fa136efee612 --- /dev/null +++ b/002_multi_def_patch_1.diff @@ -0,0 +1,11 @@ +diff -Nru quarto-cli-1.4.250.original/src/format/formats-shared.ts quarto-cli-1.4.250/src/format/formats-shared.ts +--- quarto-cli-1.4.250.original/src/format/formats-shared.ts 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/format/formats-shared.ts 2023-07-22 10:15:16.808512080 +1200 +@@ -242,7 +242,6 @@ + [kLatexAutoMk]: true, + [kLatexAutoInstall]: true, + [kLatexClean]: true, +- [kLatexMaxRuns]: 1, + [kLatexMaxRuns]: 10, + [kLatexMakeIndex]: "makeindex", + [kLatexMakeIndexOpts]: [], diff --git a/002_multi_def_patch_2.diff b/002_multi_def_patch_2.diff new file mode 100644 index 000000000000..e03a08ab6a33 --- /dev/null +++ b/002_multi_def_patch_2.diff @@ -0,0 +1,11 @@ +diff -Nru quarto-cli-1.4.250.original/src/render/notebook/notebook-contributor-jats.ts quarto-cli-1.4.250/src/render/notebook/notebook-contributor-jats.ts +--- quarto-cli-1.4.250.original/src/render/notebook/notebook-contributor-jats.ts 2023-07-22 08:39:00.000000000 +1200 ++++ quarto-cli-1.4.250/src/render/notebook/notebook-contributor-jats.ts 2023-07-22 10:15:31.408433063 +1200 +@@ -102,7 +102,6 @@ + [kOutputFile]: outputFile(nbPath), + [kTemplate]: subarticleTemplatePath, + [kNotebookPreserveCells]: true, +- [kNotebookPreserveCells]: true, + }, + quiet: false, + }, @@ -1,18 +1,15 @@ # Maintainer: Aleksandr Beliaev <trap000d at gmail dot com> pkgname=quarto-cli-git -pkgver=1.4.96.r1.gf23b0ad34 +pkgver=1.4.274.r2.gd9c08cbc9 pkgrel=1 _pkgbasename=quarto-cli _denodomver="0.1.35-alpha-artifacts" _deno_arch="deno-x86_64-unknown-linux-gnu" -_denocliffyver="0.25.7" -_denostdver="0.170.0" - pkgdesc="Quarto is an open-source scientific and technical publishing system built on [Pandoc](https://pandoc.org). This package tracks main git branch of Quarto." arch=('x86_64' 'i686') -depends=('nodejs' 'deno' 'dart-sass' 'esbuild' 'pandoc' 'lua-lpeg') +depends=('nodejs' 'deno' 'dart-sass' 'esbuild' 'pandoc' 'lua-lpeg' 'typst') makedepends=('git' 'npm' 'rust') url="https://quarto.org/" license=('MIT') @@ -22,20 +19,39 @@ options=(!strip) source=("git+https://github.com/quarto-dev/quarto-cli.git" "https://github.com/b-fuze/deno-dom/archive/refs/tags/v${_denodomver}.tar.gz" - "https://github.com/c4spar/deno-cliffy/archive/refs/tags/v${_denocliffyver}.tar.gz" - "https://github.com/denoland/deno_std/archive/refs/tags/${_denostdver}.tar.gz" + "https://github.com/c4spar/deno-cliffy/archive/refs/tags/v0.25.7.tar.gz" + "https://github.com/denoland/deno_std/archive/refs/tags/0.170.0.tar.gz" + "001_vendor_patch_1.diff" + "001_vendor_patch_2.diff" + "002_multi_def_patch_1.diff" + "002_multi_def_patch_2.diff" ) sha256sums=('SKIP' '14fb042a6912041b9fda91fd643cf278764d075bc9539aa1e107475915cd896c' '519709be1dfcf4743930b7f21a513d8fbf3663380020eac8ba629081395f6cc0' - '369bc68b848532bedcb786a8fce5e52000624b9262f05ceeeb16bc851b6cf752') + '369bc68b848532bedcb786a8fce5e52000624b9262f05ceeeb16bc851b6cf752' + '937a39f116c4310c4989cf71b9e174b6dc7bfdd84c6632e5dd0b47508cffef86' + '144101b799267869395ba2fe85ab8549be277b18af9545c106675f620e73a85b' + '6c1adcf6a21ab6a2949eee9770fe19ef453758dc2e1d3f7a071f07c66d5c92b2' + '1ee399808579aa05f38b9c27dfd23e9102f38fffb437233d360b0c076118312f') pkgver() { cd ${_pkgbasename} git describe --tags | sed 's/^v//' | sed 's/\([^-v]*-g\)/r\1/;s/-/./g' } +prepare() { + cd "${srcdir}/${_pkgbasename}" + msg "Patching cookiejar..." + patch -p1 < ../001_vendor_patch_1.diff + patch -p1 < ../001_vendor_patch_2.diff + msg "Patching multi definitions..." + patch -p1 < ../002_multi_def_patch_1.diff + patch -p1 < ../002_multi_def_patch_2.diff + +} + build() { cd "${srcdir}/${_pkgbasename}" source configuration @@ -46,35 +62,39 @@ build() { if [ -z "$QUARTO_DENO" ]; then export QUARTO_DENO=$SCRIPT_PATH/../dist/bin/tools/deno fi + # keep deno cache directory out of default $home/.cache/deno + export DENO_DIR="${srcdir}/${_pkgbasename}/package/cache" - #mkdir -p package/dist/bin/tools/${_deno_arch}/{deno_dom,dart-sass} - mkdir -p package/dist/bin/tools/${_deno_arch} - mkdir -p package/dist/bin/tools/dart-sass - mkdir -p package/dist/bin/tools/deno_dom + mkdir -p package/dist/bin/tools/${arch}/dart-sass + mkdir -p package/dist/bin/tools/${arch}/deno_dom cp /usr/bin/deno package/dist/bin/tools - ln -sfT /usr/bin/pandoc package/dist/bin/tools/pandoc - ln -sfT /usr/bin/sass package/dist/bin/tools/dart-sass/sass - ln -sfT /usr/bin/esbuild package/dist/bin/tools/esbuild + ln -sfT /usr/bin/pandoc package/dist/bin/tools/${arch}/pandoc + ln -sfT /usr/bin/sass package/dist/bin/tools/${arch}/dart-sass/sass + ln -sfT /usr/bin/esbuild package/dist/bin/tools/${arch}/esbuild msg "Building Deno Stdlib..." cd "${srcdir}/deno-dom-${_denodomver}" cargo build --release - cd "${srcdir}/${_pkgbasename}/package/src" + cd "${srcdir}/${_pkgbasename}" + # unsure if it's needed at all + # package/dist/bin/tools/deno run --allow-all package/src/common/create-deno-config.ts > deno.jsonc + cd package/src + #../dist/bin/tools/deno run --unstable --allow-env --allow-read --allow-write --allow-run --allow-net --allow-ffi --importmap=../../src/dev_import_map.json bld.ts configure --log-level info ../dist/bin/tools/deno run --unstable --allow-env --allow-read --allow-write --allow-run --allow-net --allow-ffi --importmap=../../src/import_map.json bld.ts prepare-dist --log-level info } package() { cd "${srcdir}/${_pkgbasename}" - mkdir -p package/pkg-working/bin/tools/${_deno_arch} - mkdir -p package/pkg-working/bin/tools/dart-sass - mkdir -p package/pkg-working/bin/tools/deno_dom - cp "${srcdir}/deno-dom-${_denodomver}/target/release/libplugin.so" "${srcdir}/${_pkgbasename}/package/pkg-working/bin/tools/deno_dom" - ln -sfT /usr/bin/pandoc package/pkg-working/bin/tools/pandoc - ln -sfT /usr/bin/deno package/pkg-working/bin/tools/${_deno_arch}/deno - ln -sfT /usr/bin/sass package/pkg-working/bin/tools/dart-sass/sass - ln -sfT /usr/bin/esbuild package/pkg-working/bin/tools/esbuild + mkdir -p package/pkg-working/bin/tools/${arch}/dart-sass + mkdir -p package/pkg-working/bin/tools/${arch}/deno_dom + cp "${srcdir}/deno-dom-${_denodomver}/target/release/libplugin.so" "${srcdir}/${_pkgbasename}/package/pkg-working/bin/tools/${arch}/deno_dom" + ln -sfT /usr/bin/pandoc package/pkg-working/bin/tools/${arch}/pandoc + ln -sfT /usr/bin/deno package/pkg-working/bin/tools/${arch}/deno + ln -sfT /usr/bin/sass package/pkg-working/bin/tools/${arch}/dart-sass/sass + ln -sfT /usr/bin/esbuild package/pkg-working/bin/tools/${arch}/esbuild + ln -sfT /usr/bin/typst package/pkg-working/bin/tools/${arch}/typst ## 2. Remove symlinks created by build script in ~/bin and ~/.local/bin directories rm -f "$HOME/.local/bin/quarto" rm -f "$HOME/bin/quarto" |