2ed5dfa6a1
iotlcm-app:小程序端 + 用户端服务。 - app/:uni-app 小程序前端(基于 unibest,MIT) - 微信 AppID → YOUR_WX_APPID,uni-app AppID → __UNI__YOURAPPID - 内网后端地址 → admin.iotlcm.example.com - 应用标题与 unibest 模板 README 重写(保留上游致谢与 MIT 声明) - server/:GoFrame 用户端服务(基于 XiuAdmin,Apache-2.0) - module xiuadmin → git.5iot.com/iotlcm-public/iotlcm-app(360 文件) - 支付回调地址 → app.iotlcm.example.com,商户名与应用名泛化 - 真实手机号 → 合法 11 位编造号(保留号段前 3 位 + 后 4 位) - 依赖号码尾部的断言同步更新 - 补 server/LICENSE(Apache-2.0) - 移除内部资产:CI 触发器 - 补根 README,LF 行尾 + .gitattributes 已知:TestSysDept_RefreshDeptAncestors 在源仓同一提交上同样失败,属既有缺陷。
107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
// package gohtml
|
|
// @Link https://github.com/xiujiecn/xiu-admin
|
|
// @Copyright Copyright (c) 2025 LiXiujie
|
|
// @Author Lxj <li@xiujie.cn>
|
|
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
|
package gohtml
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
type formatterTokenType int
|
|
|
|
const (
|
|
formatterTokenType_Nothing formatterTokenType = iota
|
|
formatterTokenType_Tag
|
|
formatterTokenType_Text
|
|
)
|
|
|
|
type formattedBuffer struct {
|
|
buffer *bytes.Buffer
|
|
rawMode bool
|
|
|
|
indentString string
|
|
indentLevel int
|
|
|
|
lineWrapColumn int
|
|
lineWrapMaxSpillover int
|
|
|
|
curLineLength int
|
|
prevTokenType formatterTokenType
|
|
}
|
|
|
|
func (bf *formattedBuffer) writeLineFeed() {
|
|
if !bf.rawMode {
|
|
// Strip trailing newlines
|
|
bf.buffer = bytes.NewBuffer(bytes.TrimRightFunc(
|
|
bf.buffer.Bytes(),
|
|
func(r rune) bool {
|
|
return r != '\n' && unicode.IsSpace(r)
|
|
},
|
|
))
|
|
}
|
|
|
|
bf.buffer.WriteString("\n")
|
|
bf.curLineLength = 0
|
|
bf.prevTokenType = formatterTokenType_Nothing
|
|
}
|
|
|
|
func (bf *formattedBuffer) writeIndent() {
|
|
bf.buffer.WriteString(strings.Repeat(bf.indentString, bf.indentLevel))
|
|
bf.curLineLength += len(bf.indentString) * bf.indentLevel
|
|
}
|
|
|
|
func (bf *formattedBuffer) writeToken(token string, kind formatterTokenType) {
|
|
if bf.rawMode {
|
|
bf.buffer.WriteString(token)
|
|
bf.curLineLength += len(token)
|
|
return
|
|
}
|
|
|
|
if bf.prevTokenType == formatterTokenType_Nothing && strings.TrimSpace(token) == "" {
|
|
// It's a whitespace token, but we already have indentation which functions
|
|
// the same, so we ignore it
|
|
return
|
|
}
|
|
|
|
toWrite := token
|
|
if kind == formatterTokenType_Text && bf.prevTokenType == formatterTokenType_Text {
|
|
toWrite = " " + token
|
|
}
|
|
|
|
if bf.prevTokenType != formatterTokenType_Nothing && bf.lineWrapColumn > 0 {
|
|
switch {
|
|
case bf.curLineLength > bf.lineWrapColumn:
|
|
// Current line is too long
|
|
fallthrough
|
|
|
|
case bf.curLineLength+len(toWrite) > bf.lineWrapColumn+bf.lineWrapMaxSpillover:
|
|
// Current line + new token is too long even with allowed spillover
|
|
fallthrough
|
|
|
|
case bf.curLineLength+len(toWrite) > bf.lineWrapColumn &&
|
|
bf.curLineLength > bf.lineWrapColumn-bf.lineWrapMaxSpillover:
|
|
// Current line + new token is too long and doesn't quality for spillover
|
|
|
|
bf.writeLineFeed()
|
|
bf.writeToken(token, kind)
|
|
return
|
|
}
|
|
}
|
|
|
|
if bf.curLineLength == 0 {
|
|
bf.writeIndent()
|
|
}
|
|
bf.buffer.WriteString(toWrite)
|
|
bf.curLineLength += len(toWrite)
|
|
bf.prevTokenType = kind
|
|
}
|
|
|
|
// unifyLineFeed unifies line feeds.
|
|
func unifyLineFeed(s string) string {
|
|
return strings.ReplaceAll(strings.ReplaceAll(s, "\r\n", "\n"), "\r", "\n")
|
|
}
|