chore: 初始开源发布
iotlcm-admin-svr:管理后台服务。 - Go module:iotlcm → git.5iot.com/iotlcm-public/iotlcm-admin-svr(729 文件) - 凭据与地址脱敏:JWT signingKey(含代码里的 MustGet 默认值)、 MySQL DSN、Redis 口令、告警邮件发件人邮箱全部改为占位; 私网 IP → 文档地址段;库名 xiujie_admin → iotlcm - 真实手机号/邮箱 → 合法 11 位编造号 / example.com - 移除内部资产:CI 触发器、过时 DDL(sql/db_iotlcm.sql)、 私有依赖 go get 行、明文 registry 登录口令 - 启动 banner 统一 IOTLCM 方块字 + 社区惯例署名 - Dockerfile 改用公共基础镜像 - 拼错的 RADEME.md → README.md,README 重写 - 需要真实数据库的用例改为可用 IOTLCM_TEST_WITH_DB=1 显式启用 - 补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes 数据库 schema 不随本仓发布(生产 DDL 已过时),README 已说明。
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
// 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")
|
||||
}
|
||||
Reference in New Issue
Block a user