← back to jeduden__mdsmith

Function bodies 497 total

All specs Real LLM only Function bodies
engine.Runner.log method · go · L117-L122 (6 LOC)
internal/engine/runner.go
func (r *Runner) log() *vlog.Logger {
	if r.Logger != nil {
		return r.Logger
	}
	return &vlog.Logger{}
}
engine.Runner.logRules method · go · L125-L137 (13 LOC)
internal/engine/runner.go
func (r *Runner) logRules(effective map[string]config.RuleCfg) {
	l := r.log()
	if !l.Enabled {
		return
	}
	for _, rl := range r.Rules {
		cfg, ok := effective[rl.Name()]
		if !ok || !cfg.Enabled {
			continue
		}
		l.Printf("rule: %s %s", rl.ID(), rl.Name())
	}
}
engine.ruleCategoryLookup function · go · L140-L148 (9 LOC)
internal/engine/runner.go
func ruleCategoryLookup(rules []rule.Rule) func(string) string {
	m := make(map[string]string, len(rules))
	for _, rl := range rules {
		m[rl.Name()] = rl.Category()
	}
	return func(name string) string {
		return m[name]
	}
}
engine.sortDiagnostics function · go · L151-L162 (12 LOC)
internal/engine/runner.go
func sortDiagnostics(diags []lint.Diagnostic) {
	sort.Slice(diags, func(i, j int) bool {
		di, dj := diags[i], diags[j]
		if di.File != dj.File {
			return di.File < dj.File
		}
		if di.Line != dj.Line {
			return di.Line < dj.Line
		}
		return di.Column < dj.Column
	})
}
fix.Fixer.Fix method · go · L43-L73 (31 LOC)
internal/fix/fix.go
func (f *Fixer) Fix(paths []string) *Result {
	res := &Result{}

	for _, path := range paths {
		if config.IsIgnored(f.Config.Ignore, path) {
			continue
		}
		res.FilesChecked++
		f.log().Printf("file: %s", path)
		beforeDiags, remainingDiags, modified, errs := f.fixFile(path)
		res.Failures += len(beforeDiags)
		res.Diagnostics = append(res.Diagnostics, remainingDiags...)
		if modified != "" {
			res.Modified = append(res.Modified, modified)
		}
		res.Errors = append(res.Errors, errs...)
	}

	sort.Slice(res.Diagnostics, func(i, j int) bool {
		di, dj := res.Diagnostics[i], res.Diagnostics[j]
		if di.File != dj.File {
			return di.File < dj.File
		}
		if di.Line != dj.Line {
			return di.Line < dj.Line
		}
		return di.Column < dj.Column
	})

	return res
}
fix.Fixer.fixFile method · go · L78-L131 (54 LOC)
internal/fix/fix.go
func (f *Fixer) fixFile(path string) ([]lint.Diagnostic, []lint.Diagnostic, string, []error) {
	var errs []error

	source, err := os.ReadFile(path)
	if err != nil {
		return nil, nil, "", []error{fmt.Errorf("reading %q: %w", path, err)}
	}

	info, err := os.Stat(path)
	if err != nil {
		return nil, nil, "", []error{fmt.Errorf("stat %q: %w", path, err)}
	}

	lf, err := lint.NewFileFromSource(path, source, f.StripFrontMatter)
	if err != nil {
		return nil, nil, "", []error{fmt.Errorf("parsing %q: %w", path, err)}
	}

	dirFS := os.DirFS(filepath.Dir(path))
	lf.FS = dirFS
	effective := f.effectiveWithCategories(path)

	f.logRules(effective)

	fixable, settingsErrs := f.fixableRules(effective)
	errs = append(errs, settingsErrs...)
	beforeDiags, checkErrs := engine.CheckRules(lf, f.Rules, effective)
	errs = append(errs, checkErrs...)

	current := f.applyFixPasses(path, lf.Source, fixable, dirFS, &errs)

	var modified string
	if !bytes.Equal(lf.Source, current) {
		out := lf.FullSource(curren
fix.Fixer.applyFixPasses method · go · L134-L163 (30 LOC)
internal/fix/fix.go
func (f *Fixer) applyFixPasses(
	path string, source []byte, fixable []rule.FixableRule, dirFS fs.FS, errs *[]error,
) []byte {
	const maxPasses = 10
	current := source
	for pass := 0; pass < maxPasses; pass++ {
		f.log().Printf("fix: pass %d on %s", pass+1, path)
		before := current
		for _, fr := range fixable {
			parsedFile, err := lint.NewFile(path, current)
			if err != nil {
				*errs = append(*errs, fmt.Errorf("parsing %q: %w", path, err))
				break
			}
			parsedFile.FS = dirFS

			diags := fr.Check(parsedFile)
			if len(diags) == 0 {
				continue
			}

			current = fr.Fix(parsedFile)
		}
		if bytes.Equal(before, current) {
			f.log().Printf("fix: %s stable after %d passes", path, pass+1)
			break
		}
	}
	return current
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
fix.Fixer.log method · go · L167-L172 (6 LOC)
internal/fix/fix.go
func (f *Fixer) log() *vlog.Logger {
	if f.Logger != nil {
		return f.Logger
	}
	return &vlog.Logger{}
}
fix.Fixer.logRules method · go · L175-L187 (13 LOC)
internal/fix/fix.go
func (f *Fixer) logRules(effective map[string]config.RuleCfg) {
	l := f.log()
	if !l.Enabled {
		return
	}
	for _, rl := range f.Rules {
		cfg, ok := effective[rl.Name()]
		if !ok || !cfg.Enabled {
			continue
		}
		l.Printf("rule: %s %s", rl.ID(), rl.Name())
	}
}
fix.Fixer.effectiveWithCategories method · go · L191-L204 (14 LOC)
internal/fix/fix.go
func (f *Fixer) effectiveWithCategories(path string) map[string]config.RuleCfg {
	effective := config.Effective(f.Config, path)
	categories := config.EffectiveCategories(f.Config, path)
	explicit := config.EffectiveExplicitRules(f.Config, path)

	// Build rule-name-to-category lookup from the fixer's rule list.
	m := make(map[string]string, len(f.Rules))
	for _, rl := range f.Rules {
		m[rl.Name()] = rl.Category()
	}
	catLookup := func(name string) string { return m[name] }

	return config.ApplyCategories(effective, categories, catLookup, explicit)
}
fix.Fixer.fixableRules method · go · L209-L232 (24 LOC)
internal/fix/fix.go
func (f *Fixer) fixableRules(effective map[string]config.RuleCfg) ([]rule.FixableRule, []error) {
	var fixable []rule.FixableRule
	var errs []error
	for _, rl := range f.Rules {
		cfg, ok := effective[rl.Name()]
		if !ok || !cfg.Enabled {
			continue
		}

		configured, err := engine.ConfigureRule(rl, cfg)
		if err != nil {
			errs = append(errs, err)
			continue
		}

		if fr, ok := configured.(rule.FixableRule); ok {
			fixable = append(fixable, fr)
		}
	}
	sort.Slice(fixable, func(i, j int) bool {
		return fixable[i].ID() < fixable[j].ID()
	})
	return fixable, errs
}
lint.CollectCodeBlockLines function · go · L8-L27 (20 LOC)
internal/lint/codeblocks.go
func CollectCodeBlockLines(f *File) map[int]bool {
	lines := map[int]bool{}

	_ = ast.Walk(f.AST, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}

		switch cb := n.(type) {
		case *ast.FencedCodeBlock:
			addFencedCodeBlockLines(f, cb, lines)
		case *ast.CodeBlock:
			addBlockLines(f, cb, lines)
		}

		return ast.WalkContinue, nil
	})

	return lines
}
lint.addFencedCodeBlockLines function · go · L31-L65 (35 LOC)
internal/lint/codeblocks.go
func addFencedCodeBlockLines(f *File, fcb *ast.FencedCodeBlock, set map[int]bool) {
	// Determine the opening fence line by looking at the node's info or
	// the first content line. The opening fence is always the line before
	// the first content line (or, when there are no content lines, we find
	// it via the Info segment).
	openLine := findFencedOpenLine(f, fcb)
	if openLine > 0 {
		set[openLine] = true
	}

	// Content lines from the code block's segments.
	segs := fcb.Lines()
	lastContentLine := 0
	for i := 0; i < segs.Len(); i++ {
		seg := segs.At(i)
		ln := f.LineOfOffset(seg.Start)
		set[ln] = true
		if ln > lastContentLine {
			lastContentLine = ln
		}
	}

	// Closing fence line is the line after the last content line.
	// If there are no content lines, the closing fence is the line after
	// the opening fence.
	closeLine := 0
	if lastContentLine > 0 {
		closeLine = lastContentLine + 1
	} else if openLine > 0 {
		closeLine = openLine + 1
	}
	if closeLine > 0 && closeLine <= le
lint.findFencedOpenLine function · go · L68-L85 (18 LOC)
internal/lint/codeblocks.go
func findFencedOpenLine(f *File, fcb *ast.FencedCodeBlock) int {
	// If the code block has an info string, walk backwards from it to find
	// the start of the line.
	if fcb.Info != nil {
		return f.LineOfOffset(fcb.Info.Segment.Start)
	}
	// If there are content lines, the opening fence is on the previous line.
	if fcb.Lines().Len() > 0 {
		firstContentLine := f.LineOfOffset(fcb.Lines().At(0).Start)
		if firstContentLine > 1 {
			return firstContentLine - 1
		}
		return 1
	}
	// Empty fenced code block with no info: scan from the node's text position.
	// Fall back to using previous sibling or document start.
	return 0
}
lint.addBlockLines function · go · L88-L95 (8 LOC)
internal/lint/codeblocks.go
func addBlockLines(f *File, cb *ast.CodeBlock, set map[int]bool) {
	segs := cb.Lines()
	for i := 0; i < segs.Len(); i++ {
		seg := segs.At(i)
		ln := f.LineOfOffset(seg.Start)
		set[ln] = true
	}
}
Want this analysis on your repo? https://repobility.com/scan/
lint.NewFile function · go · L24-L37 (14 LOC)
internal/lint/file.go
func NewFile(path string, source []byte) (*File, error) {
	reader := text.NewReader(source)
	parser := goldmark.DefaultParser()
	node := parser.Parse(reader)

	lines := bytes.Split(source, []byte("\n"))

	return &File{
		Path:   path,
		Source: source,
		Lines:  lines,
		AST:    node,
	}, nil
}
lint.NewFileFromSource function · go · L43-L59 (17 LOC)
internal/lint/file.go
func NewFileFromSource(path string, source []byte, stripFrontMatter bool) (*File, error) {
	var fm []byte
	var offset int
	content := source
	if stripFrontMatter {
		fm, content = StripFrontMatter(source)
		offset = CountLines(fm)
	}

	f, err := NewFile(path, content)
	if err != nil {
		return nil, err
	}
	f.FrontMatter = fm
	f.LineOffset = offset
	return f, nil
}
lint.File.AdjustDiagnostics method · go · L62-L69 (8 LOC)
internal/lint/file.go
func (f *File) AdjustDiagnostics(diags []Diagnostic) {
	if f.LineOffset == 0 {
		return
	}
	for i := range diags {
		diags[i].Line += f.LineOffset
	}
}
lint.File.FullSource method · go · L73-L81 (9 LOC)
internal/lint/file.go
func (f *File) FullSource(body []byte) []byte {
	if len(f.FrontMatter) == 0 {
		return body
	}
	out := make([]byte, 0, len(f.FrontMatter)+len(body))
	out = append(out, f.FrontMatter...)
	out = append(out, body...)
	return out
}
lint.File.LineOfOffset method · go · L84-L92 (9 LOC)
internal/lint/file.go
func (f *File) LineOfOffset(offset int) int {
	line := 1
	for i := 0; i < offset && i < len(f.Source); i++ {
		if f.Source[i] == '\n' {
			line++
		}
	}
	return line
}
lint.matchesGlob function · go · L20-L32 (13 LOC)
internal/lint/files.go
func matchesGlob(patterns []string, path string) bool {
	cleanPath := filepath.Clean(path)
	for _, pattern := range patterns {
		g, err := glob.Compile(pattern)
		if err != nil {
			continue
		}
		if g.Match(path) || g.Match(cleanPath) || g.Match(filepath.Base(path)) {
			return true
		}
	}
	return false
}
lint.ResolveOpts.useGitignore method · go · L61-L66 (6 LOC)
internal/lint/files.go
func (o ResolveOpts) useGitignore() bool {
	if o.UseGitignore == nil {
		return true // default
	}
	return *o.UseGitignore
}
lint.ResolveFilesWithOpts function · go · L79-L102 (24 LOC)
internal/lint/files.go
func ResolveFilesWithOpts(args []string, opts ResolveOpts) ([]string, error) {
	seen := make(map[string]bool)
	var result []string

	addFile := func(path string) {
		abs, err := filepath.Abs(path)
		if err != nil {
			abs = path
		}
		if !seen[abs] {
			seen[abs] = true
			result = append(result, path)
		}
	}

	for _, arg := range args {
		if err := resolveArg(arg, opts, addFile); err != nil {
			return nil, err
		}
	}

	sort.Strings(result)
	return result, nil
}
Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
lint.resolveArg function · go · L106-L123 (18 LOC)
internal/lint/files.go
func resolveArg(arg string, opts ResolveOpts, addFile func(string)) error {
	if hasGlobChars(arg) {
		return resolveGlob(arg, opts, addFile)
	}

	info, err := os.Stat(arg)
	if err != nil {
		return fmt.Errorf("cannot access %q: %w", arg, err)
	}

	if info.IsDir() {
		return addDirFiles(arg, opts, addFile)
	}

	// Explicitly named files are never filtered by gitignore.
	addFile(arg)
	return nil
}
lint.resolveGlob function · go · L126-L154 (29 LOC)
internal/lint/files.go
func resolveGlob(pattern string, opts ResolveOpts, addFile func(string)) error {
	matches, err := filepath.Glob(pattern)
	if err != nil {
		return fmt.Errorf("invalid glob pattern %q: %w", pattern, err)
	}
	for _, m := range matches {
		// Skip symlinks matching no-follow-symlinks patterns.
		if len(opts.NoFollowSymlinks) > 0 {
			linfo, lerr := os.Lstat(m)
			if lerr == nil && linfo.Mode()&os.ModeSymlink != 0 {
				if matchesGlob(opts.NoFollowSymlinks, m) {
					continue
				}
			}
		}
		info, err := os.Stat(m)
		if err != nil {
			continue
		}
		if info.IsDir() {
			if err := addDirFiles(m, opts, addFile); err != nil {
				return err
			}
		} else if isMarkdown(m) {
			addFile(m)
		}
	}
	return nil
}
lint.addDirFiles function · go · L157-L166 (10 LOC)
internal/lint/files.go
func addDirFiles(dir string, opts ResolveOpts, addFile func(string)) error {
	dirFiles, err := walkDir(dir, opts.useGitignore(), opts.NoFollowSymlinks)
	if err != nil {
		return err
	}
	for _, f := range dirFiles {
		addFile(f)
	}
	return nil
}
lint.isSkippedSymlink function · go · L170-L178 (9 LOC)
internal/lint/files.go
func isSkippedSymlink(info os.FileInfo, path string, patterns []string) bool {
	if len(patterns) == 0 {
		return false
	}
	if info.Mode()&os.ModeSymlink == 0 {
		return false
	}
	return matchesGlob(patterns, path)
}
lint.walkDir function · go · L183-L218 (36 LOC)
internal/lint/files.go
func walkDir(dir string, useGitignore bool, noFollowSymlinks []string) ([]string, error) {
	var matcher *GitignoreMatcher
	if useGitignore {
		matcher = NewGitignoreMatcher(dir)
	}

	var files []string
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if isSkippedSymlink(info, path, noFollowSymlinks) {
			if info.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		if matcher != nil && isGitignored(matcher, path, info.IsDir()) {
			if info.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		if !info.IsDir() && isMarkdown(path) {
			files = append(files, path)
		}
		return nil
	})
	if err != nil {
		return nil, fmt.Errorf("walking directory %q: %w", dir, err)
	}
	return files, nil
}
lint.isGitignored function · go · L221-L227 (7 LOC)
internal/lint/files.go
func isGitignored(matcher *GitignoreMatcher, path string, isDir bool) bool {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return false
	}
	return matcher.IsIgnored(absPath, isDir)
}
lint.StripFrontMatter function · go · L9-L21 (13 LOC)
internal/lint/frontmatter.go
func StripFrontMatter(source []byte) (prefix, content []byte) {
	delim := []byte("---\n")
	if !bytes.HasPrefix(source, delim) {
		return nil, source
	}
	rest := source[len(delim):]
	idx := bytes.Index(rest, delim)
	if idx < 0 {
		return nil, source
	}
	end := len(delim) + idx + len(delim)
	return source[:end], source[end:]
}
lint.parseGitignoreFile function · go · L35-L90 (56 LOC)
internal/lint/gitignore.go
func parseGitignoreFile(path string) ([]ignoreRule, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer func() { _ = f.Close() }()

	base := filepath.Dir(path)
	var rules []ignoreRule

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()

		// Strip trailing whitespace (unless escaped with backslash).
		line = trimTrailingWhitespace(line)

		// Skip blank lines and comments.
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}

		r := ignoreRule{base: base}

		// Handle negation.
		if strings.HasPrefix(line, "!") {
			r.negate = true
			line = line[1:]
		}

		// Handle directory-only pattern (trailing /).
		if strings.HasSuffix(line, "/") {
			r.dirOnly = true
			line = strings.TrimSuffix(line, "/")
		}

		// A leading slash anchors the pattern to the base directory.
		// Remove it but note that the pattern contains a slash.
		if strings.HasPrefix(line, "/") {
			line = line[1:]
			r.hasSlash = true
		} else {
			// If t
Repobility (the analyzer behind this table) · https://repobility.com
lint.trimTrailingWhitespace function · go · L94-L104 (11 LOC)
internal/lint/gitignore.go
func trimTrailingWhitespace(s string) string {
	i := len(s)
	for i > 0 && (s[i-1] == ' ' || s[i-1] == '\t') {
		i--
	}
	// If the char before the trimmed spaces is a backslash, keep one space.
	if i < len(s) && i > 0 && s[i-1] == '\\' {
		return s[:i-1] + " "
	}
	return s[:i]
}
lint.NewGitignoreMatcher function · go · L110-L144 (35 LOC)
internal/lint/gitignore.go
func NewGitignoreMatcher(root string) *GitignoreMatcher {
	m := &GitignoreMatcher{}

	absRoot, err := filepath.Abs(root)
	if err != nil {
		return m
	}

	// Collect .gitignore files from ancestors (root of tree down to parent of root).
	ancestors := collectAncestorGitignores(absRoot)
	for _, gi := range ancestors {
		rules, err := parseGitignoreFile(gi)
		if err != nil {
			continue
		}
		m.rules = append(m.rules, rules...)
	}

	// Collect .gitignore files within the root directory tree.
	_ = filepath.Walk(absRoot, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}
		if !info.IsDir() && info.Name() == ".gitignore" {
			rules, parseErr := parseGitignoreFile(path)
			if parseErr != nil {
				return nil
			}
			m.rules = append(m.rules, rules...)
		}
		return nil
	})

	return m
}
lint.collectAncestorGitignores function · go · L148-L165 (18 LOC)
internal/lint/gitignore.go
func collectAncestorGitignores(root string) []string {
	var ancestors []string
	dir := filepath.Dir(root)
	for {
		gi := filepath.Join(dir, ".gitignore")
		if _, err := os.Stat(gi); err == nil {
			ancestors = append([]string{gi}, ancestors...)
		}
		parent := filepath.Dir(dir)
		if parent == dir {
			break
		}
		dir = parent
	}
	// Reverse so they go from root-of-tree down to immediate parent.
	// They are already collected root-first due to prepending, so no reversal needed.
	return ancestors
}
lint.GitignoreMatcher.IsIgnored method · go · L169-L180 (12 LOC)
internal/lint/gitignore.go
func (m *GitignoreMatcher) IsIgnored(absPath string, isDir bool) bool {
	ignored := false
	for _, r := range m.rules {
		if r.dirOnly && !isDir {
			continue
		}
		if matchRule(r, absPath) {
			ignored = !r.negate
		}
	}
	return ignored
}
lint.matchRule function · go · L183-L213 (31 LOC)
internal/lint/gitignore.go
func matchRule(r ignoreRule, absPath string) bool {
	// Compute the path relative to the rule's base directory.
	rel, err := filepath.Rel(r.base, absPath)
	if err != nil {
		return false
	}
	// Normalize to forward slashes for matching.
	rel = filepath.ToSlash(rel)

	// Paths outside the rule's base should not match.
	if strings.HasPrefix(rel, "..") {
		return false
	}

	if r.hasSlash {
		// Pattern contains a slash: match against the full relative path.
		return matchGitignorePattern(r.pattern, rel)
	}

	// No slash: match against just the basename, or any path component.
	// Per git spec, a pattern without a slash matches the basename of any
	// file at any depth.
	base := filepath.Base(absPath)
	if matchGitignorePattern(r.pattern, base) {
		return true
	}
	// Also try matching against the full relative path, since patterns like
	// "*.md" should match "sub/file.md" via basename matching above, but
	// patterns like "dir" should match "dir" at any level.
	return matchGitignorePattern
lint.matchGitignorePattern function · go · L217-L225 (9 LOC)
internal/lint/gitignore.go
func matchGitignorePattern(pattern, path string) bool {
	// Handle ** patterns by expanding them.
	if strings.Contains(pattern, "**") {
		return matchDoublestar(pattern, path)
	}
	// Use filepath.Match for simple patterns.
	matched, _ := filepath.Match(pattern, path)
	return matched
}
lint.matchDoublestar function · go · L228-L278 (51 LOC)
internal/lint/gitignore.go
func matchDoublestar(pattern, path string) bool {
	// Split pattern on "**" and match each segment.
	parts := strings.Split(pattern, "**")
	if len(parts) == 2 {
		prefix := parts[0]
		suffix := parts[1]

		// Leading ** — matches any path prefix.
		if prefix == "" || prefix == "/" {
			suffix = strings.TrimPrefix(suffix, "/")
			if suffix == "" {
				// Pattern is just "**" — matches everything.
				return true
			}
			// Try matching suffix against every possible subpath.
			pathParts := strings.Split(path, "/")
			for i := range pathParts {
				sub := strings.Join(pathParts[i:], "/")
				if matchGitignorePattern(suffix, sub) {
					return true
				}
			}
			return false
		}

		// Trailing ** — matches any path suffix.
		if suffix == "" || suffix == "/" {
			prefix = strings.TrimSuffix(prefix, "/")
			return strings.HasPrefix(path, prefix+"/") || path == prefix
		}

		// Middle ** — e.g., "a/**/b".
		prefix = strings.TrimSuffix(prefix, "/")
		suffix = strings.TrimPrefix(suffix, "/")
	
log.Logger.Printf method · go · L17-L22 (6 LOC)
internal/log/logger.go
func (l *Logger) Printf(format string, args ...any) {
	if !l.Enabled {
		return
	}
	_, _ = fmt.Fprintf(l.W, format+"\n", args...)
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
mdtext.extractText function · go · L23-L55 (33 LOC)
internal/mdtext/mdtext.go
func extractText(buf *strings.Builder, node ast.Node, source []byte) {
	// For text nodes, write the content.
	if t, ok := node.(*ast.Text); ok {
		buf.Write(t.Segment.Value(source))
		if t.SoftLineBreak() || t.HardLineBreak() {
			buf.WriteByte(' ')
		}
		return
	}

	// For code spans, extract the text content from children.
	if _, ok := node.(*ast.CodeSpan); ok {
		for c := node.FirstChild(); c != nil; c = c.NextSibling() {
			if t, ok := c.(*ast.Text); ok {
				buf.Write(t.Segment.Value(source))
			}
		}
		return
	}

	// For images, use alt text from children.
	if _, ok := node.(*ast.Image); ok {
		for c := node.FirstChild(); c != nil; c = c.NextSibling() {
			extractText(buf, c, source)
		}
		return
	}

	// For links, emphasis, strong, and other nodes: recurse into children.
	for c := node.FirstChild(); c != nil; c = c.NextSibling() {
		extractText(buf, c, source)
	}
}
mdtext.CountSentences function · go · L65-L84 (20 LOC)
internal/mdtext/mdtext.go
func CountSentences(text string) int {
	if strings.TrimSpace(text) == "" {
		return 0
	}
	count := 0
	runes := []rune(text)
	for i, r := range runes {
		if r == '.' || r == '!' || r == '?' {
			if i == len(runes)-1 {
				count++
			} else if unicode.IsSpace(runes[i+1]) {
				count++
			}
		}
	}
	if count == 0 {
		return 1
	}
	return count
}
mdtext.SplitSentences function · go · L99-L113 (15 LOC)
internal/mdtext/mdtext.go
func SplitSentences(text string) []string {
	if strings.TrimSpace(text) == "" {
		return nil
	}
	initOnce.Do(initTokenizer)
	sents := tokenizer.Tokenize(text)
	result := make([]string, 0, len(sents))
	for _, s := range sents {
		t := strings.TrimSpace(s.Text)
		if t != "" {
			result = append(result, t)
		}
	}
	return result
}
mdtext.CountCharacters function · go · L117-L125 (9 LOC)
internal/mdtext/mdtext.go
func CountCharacters(text string) int {
	count := 0
	for _, r := range text {
		if unicode.IsLetter(r) || unicode.IsDigit(r) {
			count++
		}
	}
	return count
}
metrics.concisenessScore function · go · L50-L92 (43 LOC)
internal/metrics/conciseness.go
func concisenessScore(text string) float64 {
	lower := strings.ToLower(text)
	tokens := tokenPattern.FindAllString(lower, -1)
	if len(tokens) == 0 {
		return 100.0
	}

	contentWords := 0
	fillerCount := 0
	for _, tok := range tokens {
		if _, ok := stopWords[tok]; !ok {
			contentWords++
		}
		if _, ok := fillerWords[tok]; ok {
			fillerCount++
		}
	}

	lexicalDensity := float64(contentWords) / float64(len(tokens))
	fillerRatio := float64(fillerCount) / float64(len(tokens))

	sentences := mdtext.CountSentences(text)
	if sentences < 1 {
		sentences = 1
	}

	avgSentenceWords := float64(len(tokens)) / float64(sentences)
	lengthPenalty := clamp((avgSentenceWords-24.0)/24.0, 0, 1)

	phraseHits := 0
	for _, phrase := range verbosePhrases {
		if strings.Contains(lower, phrase) {
			phraseHits++
		}
	}
	phrasePenalty := clamp(float64(phraseHits)/4.0, 0, 1)

	base := 100.0 * (0.65*lexicalDensity + 0.35*(1.0-fillerRatio))
	score := base - (22.0 * lengthPenalty) - (15.0 * phrasePenalty)
	score = 
metrics.clamp function · go · L94-L102 (9 LOC)
internal/metrics/conciseness.go
func clamp(v, min, max float64) float64 {
	if v < min {
		return min
	}
	if v > max {
		return max
	}
	return v
}
metrics.listDocsFromFS function · go · L33-L63 (31 LOC)
internal/metrics/docs.go
func listDocsFromFS(fsys fs.FS) ([]DocInfo, error) {
	entries, err := fs.ReadDir(fsys, ".")
	if err != nil {
		return nil, fmt.Errorf("reading metrics directory: %w", err)
	}

	var docs []DocInfo
	for _, entry := range entries {
		if !entry.IsDir() {
			continue
		}

		path := entry.Name() + "/README.md"
		data, err := fs.ReadFile(fsys, path)
		if err != nil {
			continue
		}

		info, err := parseFrontMatter(string(data))
		if err != nil {
			continue
		}
		info.Content = string(data)
		docs = append(docs, info)
	}

	sort.Slice(docs, func(i, j int) bool {
		return docs[i].ID < docs[j].ID
	})
	return docs, nil
}
metrics.lookupDocFromFS function · go · L65-L80 (16 LOC)
internal/metrics/docs.go
func lookupDocFromFS(fsys fs.FS, query string) (string, error) {
	docs, err := listDocsFromFS(fsys)
	if err != nil {
		return "", err
	}

	q := strings.ToUpper(strings.TrimSpace(query))
	qName := strings.ToLower(strings.TrimSpace(query))
	for _, d := range docs {
		if strings.ToUpper(d.ID) == q || d.Name == qName {
			return d.Content, nil
		}
	}

	return "", fmt.Errorf("unknown metric %q", query)
}
Want this analysis on your repo? https://repobility.com/scan/
metrics.parseFrontMatter function · go · L83-L116 (34 LOC)
internal/metrics/docs.go
func parseFrontMatter(content string) (DocInfo, error) {
	scanner := bufio.NewScanner(strings.NewReader(content))
	if !scanner.Scan() || strings.TrimSpace(scanner.Text()) != "---" {
		return DocInfo{}, fmt.Errorf("missing front matter")
	}

	var info DocInfo
	for scanner.Scan() {
		line := scanner.Text()
		if strings.TrimSpace(line) == "---" {
			break
		}
		key, val, ok := parseYAMLLine(line)
		if !ok {
			continue
		}
		switch key {
		case "id":
			info.ID = val
		case "name":
			info.Name = val
		case "description":
			info.Description = val
		}
	}

	if info.ID == "" {
		return DocInfo{}, fmt.Errorf("front matter missing id")
	}
	if info.Name == "" {
		return DocInfo{}, fmt.Errorf("front matter missing name")
	}
	return info, nil
}
metrics.parseYAMLLine function · go · L119-L127 (9 LOC)
internal/metrics/docs.go
func parseYAMLLine(line string) (key, value string, ok bool) {
	idx := strings.Index(line, ":")
	if idx < 0 {
		return "", "", false
	}
	key = strings.TrimSpace(line[:idx])
	value = strings.TrimSpace(line[idx+1:])
	return key, value, true
}
metrics.NewDocument function · go · L36-L41 (6 LOC)
internal/metrics/document.go
func NewDocument(path string, source []byte) *Document {
	return &Document{
		Path:   path,
		Source: source,
	}
}
‹ prevpage 3 / 10next ›