mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
a6f3e635d4
* feat(docs): add local authoring and resource workflows Add docs +script workflows for isolated draft initialization and tolerant XML/Markdown profiling. Support local and remote document resources across create and update flows with safe, bounded-concurrency uploads, binding verification, and cleanup. Synchronize shared credential-source selection during concurrent uploads, refresh lark-doc guidance, and expand unit, dry-run, and live E2E coverage. * docs(lark-doc): clarify genre reference paths * fix(docs): address PR validation feedback * docs(lark-doc): clarify remote image handling * feat: streamline docs draft workflow * fix(docs): clarify script input and resource cleanup * fix(docs): align script dry-run test with auth flow * fix(docs): authenticate local script e2e test * fix(docs): refine script diagnostics and image preflight * fix(docs): align draft workspace cleanup with VFS * fix(docs): route workspace cleanup through FileIO * docs(lark-doc): simplify profile check guidance
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package docxparse
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
compatibleBlockIDSelfClosing = regexp.MustCompile(`^<block_id="([^"]+)"\s*/>`)
|
|
compatibleBlockIDWithClosing = regexp.MustCompile(`^<block_id="([^"]+)"\s*>\s*</block_id>`)
|
|
compatibleBlockIDOpen = regexp.MustCompile(`^<block_id="([^"]+)"\s*>`)
|
|
)
|
|
|
|
// normalizeCompatibleXMLInput applies deterministic legacy-shape rewrites
|
|
// before the tolerant parser builds its in-memory tree. The repaired XML is
|
|
// intentionally not exposed or written back by docs +script parse.
|
|
func normalizeCompatibleXMLInput(source string) string {
|
|
var out strings.Builder
|
|
out.Grow(len(source))
|
|
for offset := 0; offset < len(source); {
|
|
relative := strings.IndexByte(source[offset:], '<')
|
|
if relative < 0 {
|
|
out.WriteString(source[offset:])
|
|
break
|
|
}
|
|
start := offset + relative
|
|
out.WriteString(source[offset:start])
|
|
|
|
_, end, state := scanXMLToken(source, start)
|
|
if state == tokenComment || state == tokenCDATA || state == tokenProcessingInstruction {
|
|
out.WriteString(source[start:end])
|
|
offset = end
|
|
continue
|
|
}
|
|
|
|
if replacement, consumed, ok := rewriteCompatibleBlockID(source[start:]); ok {
|
|
out.WriteString(replacement)
|
|
offset = start + consumed
|
|
continue
|
|
}
|
|
if end > start+1 && (state == tokenOK || state == tokenInvalid) {
|
|
out.WriteString(source[start:end])
|
|
offset = end
|
|
continue
|
|
}
|
|
|
|
out.WriteByte(source[start])
|
|
offset = start + 1
|
|
}
|
|
return out.String()
|
|
}
|
|
|
|
func rewriteCompatibleBlockID(source string) (string, int, bool) {
|
|
for _, expression := range []*regexp.Regexp{
|
|
compatibleBlockIDSelfClosing,
|
|
compatibleBlockIDWithClosing,
|
|
compatibleBlockIDOpen,
|
|
} {
|
|
match := expression.FindStringSubmatchIndex(source)
|
|
if len(match) < 4 || match[0] != 0 {
|
|
continue
|
|
}
|
|
return `<block_id>` + source[match[2]:match[3]] + `</block_id>`, match[1], true
|
|
}
|
|
return "", 0, false
|
|
}
|