p1: /v2/scrape, /v1/fetch, auth, CLI, contract tests

Single Fetcher.Fetch on the Guard that holds DenyPrefixes. skipTlsVerification
is ignored. No 502. keys add writes the secret only to --out. Release binary
has no -test-allow-prefix.
This commit is contained in:
2026-09-22 21:54:01 -07:00
parent 6cb206fb27
commit 9444a35322
311 changed files with 238557 additions and 92 deletions
@@ -0,0 +1,9 @@
package escape
func IsBackslash(chars []byte, index int) int {
if chars[index] != '\\' {
return -1
}
return 1
}
@@ -0,0 +1,45 @@
package escape
func IsFencedCode(chars []byte, index int) int {
if chars[index] != '`' && chars[index] != '~' {
return -1
}
for i := index - 1; i >= 0; i-- {
if chars[i] == ' ' || chars[i] == placeholderByte {
continue
}
if chars[i] == '\n' {
break
}
return -1
}
count := 1
i := index + 1
for ; i < len(chars); i++ {
if chars[i] == placeholderByte {
continue
}
if chars[i] == '`' || chars[i] == '~' {
count++
continue
}
break
}
if count < 3 {
return -1
}
return i - index
}
func IsInlineCode(chars []byte, index int) int {
if chars[index] != '`' {
return -1
}
return 1
}
@@ -0,0 +1,47 @@
package escape
func IsDivider(chars []byte, index int) int {
if chars[index] != '-' && chars[index] != '_' && chars[index] != '*' {
return -1
}
for i := index - 1; i >= 0; i-- {
if chars[i] == '\n' {
break
}
if chars[i] == placeholderByte {
continue
}
if chars[i] == ' ' {
continue
}
return -1
}
count := 1
lastChar := len(chars)
for i := index + 1; i < len(chars); i++ {
if chars[i] == placeholderByte {
continue
}
if chars[i] == ' ' {
continue
}
if chars[i] == chars[index] {
count++
continue
}
if chars[i] == '\n' {
lastChar = i
break
}
return -1
}
if count >= 3 {
return lastChar - index
}
return -1
}
@@ -0,0 +1,77 @@
package escape
func IsAtxHeader(chars []byte, index int) int {
if chars[index] != '#' {
return -1
}
for i := index - 1; i >= 0; i-- {
if chars[i] == '\n' {
break
}
if chars[i] == placeholderByte {
continue
}
if chars[i] == ' ' {
continue
}
return -1
}
nPoundSigns := 1
for i := index + 1; i < len(chars); i++ {
if chars[i] == '#' {
nPoundSigns++
if nPoundSigns > 6 {
return -1
}
continue
}
if chars[i] == placeholderByte {
continue
}
if chars[i] == ' ' || chars[i] == '\t' || chars[i] == '\n' || chars[i] == '\r' {
// TODO: fix calculation with placeholder (maybe own for loop construct?)
// Returns the count of # that we encountered
return i - index
}
return -1
}
return 1
}
func IsSetextHeader(chars []byte, index int) int {
if chars[index] != '=' && chars[index] != '-' {
return -1
}
var newlineCount int
for i := index - 1; i >= 0; i-- {
if chars[i] == placeholderByte || chars[i] == ' ' {
continue
}
if chars[i] == '\n' {
newlineCount++
continue
}
if newlineCount == 0 {
// Without any newlines, this character is on the same line
// as the delimiter. So the delimiter is inside a normal text...
return -1
} else if newlineCount == 1 {
// The heading content is on the line above the delimiter
// which qualifies for a setext heading...
return 1
} else {
return -1
}
}
return -1
}
@@ -0,0 +1,36 @@
package escape
func IsImageOrLink(chars []byte, index int) int {
if chars[index] == '!' {
return isImageOrLinkStartExclamation(chars, index)
}
if chars[index] == '[' {
return isImageOrLinkStartBracket(chars, index)
}
return -1
}
func isImageOrLinkStartExclamation(chars []byte, index int) int {
nextIndex := index + 1
if nextIndex < len(chars) && chars[nextIndex] == '[' {
// It could be the start of an image
return 1
}
return -1
}
func isImageOrLinkStartBracket(chars []byte, index int) int {
for i := index + 1; i < len(chars); i++ {
if chars[i] == '\n' {
return -1
}
if chars[i] == ']' {
return 1
}
}
return -1
}
@@ -0,0 +1,21 @@
package escape
import (
"unicode"
)
func IsItalicOrBold(chars []byte, index int) int {
if chars[index] != '*' && chars[index] != '_' {
return -1
}
next := getNextAsRune(chars, index)
nextIsWhitespace := unicode.IsSpace(next) || next == 0
if nextIsWhitespace {
// "not followed by Unicode whitespace"
return -1
}
return 1
}
@@ -0,0 +1,67 @@
package escape
import (
"unicode"
)
func IsUnorderedList(chars []byte, index int) int {
if chars[index] != '-' && chars[index] != '*' && chars[index] != '+' {
return -1
}
for i := index - 1; i >= 0; i-- {
if chars[i] == '\n' {
break
}
if chars[i] == ' ' {
continue
}
if chars[i] == placeholderByte {
continue
}
return -1
}
next := getNext(chars, index)
if IsSpace(next) || next == 0 {
return 1
}
return -1
}
func IsOrderedList(chars []byte, index int) int {
if chars[index] != '.' && chars[index] != ')' {
return -1
}
// Directly before the dot needs to be a digit
prev := getPrevAsRune(chars, index)
if !unicode.IsDigit(prev) {
return -1
}
for i := index - 1; i >= 0; i-- {
if chars[i] == '\n' {
break
}
if chars[i] == ' ' {
continue
}
if chars[i] == placeholderByte {
continue
}
if IsDigit(chars[i]) {
continue
}
return -1
}
next := getNext(chars, index)
if IsSpace(next) || next == 0 {
return 1
}
return -1
}
@@ -0,0 +1,23 @@
package escape
func IsBlockQuote(chars []byte, index int) int {
if chars[index] != '>' {
return -1
}
for i := index - 1; i >= 0; i-- {
if chars[i] == '\n' {
break
}
if chars[i] == placeholderByte {
continue
}
if chars[i] == ' ' {
continue
}
return -1
}
return 1
}
@@ -0,0 +1,8 @@
package escape
import "github.com/JohannesKaufmann/html-to-markdown/v2/marker"
var placeholderRune rune = marker.MarkerEscaping
// IMPORTANT: Only internally we assume it is only byte
var placeholderByte byte = marker.BytesMarkerEscaping[0]
@@ -0,0 +1,70 @@
package escape
import "unicode/utf8"
// TODO: move to markers package?
func IsSpace(b byte) bool {
switch b {
case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0:
return true
}
return false
}
func IsDigit(b byte) bool {
switch b {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return true
}
return false
}
func getPrev(chars []byte, index int) byte {
for i := index - 1; i >= 0; i-- {
if chars[i] == placeholderByte {
continue
}
return chars[i]
}
return 0
}
func getNext(chars []byte, index int) byte {
for i := index + 1; i < len(chars); i++ {
if chars[i] == placeholderByte {
continue
}
return chars[i]
}
return 0
}
func getPrevAsRune(chars []byte, index int) rune {
for i := index - 1; i >= 0; i-- {
if chars[i] == placeholderByte {
continue
}
r, _ := utf8.DecodeLastRune(chars[:i+1])
return r
}
return 0
}
func getNextAsRune(source []byte, index int) rune {
for i := index + 1; i < len(source); i++ {
if source[i] == placeholderByte {
continue
}
r, _ := utf8.DecodeRune(source[i:])
return r
}
return 0
}
// TODO: make public?
func GetNextAsRune(source []byte, index int) rune {
return getNextAsRune(source, index)
}