Cleaning things up to turn this into a proper parser
							parent
							
								
									0b2443c720
								
							
						
					
					
						commit
						c3b5d8e663
					
				| @ -0,0 +1,4 @@ | ||||
| node_modules/* | ||||
| package*.json | ||||
| dist/* | ||||
| reports/* | ||||
| @ -0,0 +1,217 @@ | ||||
| # This file is intended as a starting point for a customized makefile for a Go project.
 | ||||
| #
 | ||||
| # Targets:
 | ||||
| # 	all: Format, check, build, and test the code
 | ||||
| #   setup: Install build/test toolchain dependencies (e.g. gox)
 | ||||
| #   lint: Run linters against source code
 | ||||
| #   bump-{major,minor,patch}: create a new semver git tag
 | ||||
| #   release-{major,minor,patch}: push a tagged release
 | ||||
| # 	format: Format the source files
 | ||||
| # 	build: Build the command(s) for target OS/arch combinations
 | ||||
| # 	install: Install the command(s)
 | ||||
| # 	clean: Clean the build/test artifacts
 | ||||
| #   report: Generate build/test reports
 | ||||
| #	check: Run tests
 | ||||
| #   bench: Run benchmarks
 | ||||
| #   dist: zip/tar binaries & documentation
 | ||||
| #	debug: print parameters
 | ||||
| #
 | ||||
| # Parameters:
 | ||||
| # 	VERSION: release version in semver format
 | ||||
| #	BUILD_TAGS: additional build tags to pass to go build
 | ||||
| #	DISTDIR: path to save distribution files
 | ||||
| #	RPTDIR: path to save build/test reports
 | ||||
| #
 | ||||
| # Assumptions:
 | ||||
| #   - Your package contains a cmd/ package, containing a directory for each produced binary.
 | ||||
| #   - You have cloc installed and accessible in the PATH.
 | ||||
| #   - Your GOPATH and GOROOT are set correctly.
 | ||||
| #   - Your makefile is in the root of your package and does not have a space in its file name.
 | ||||
| #   - Your root package contains global string variables Version and Build, to receive the bild version number and commit ID, respectively.
 | ||||
| #
 | ||||
| # Features:
 | ||||
| #   - report generates files that can be consumed by Jenkins, as well as a list of external dependencies.
 | ||||
| #   - setup installs all the tools aside from cloc.
 | ||||
| #   - Works on Windows and with paths containing spaces.
 | ||||
| #   - Works when executing from outside the makefile directory using -f.
 | ||||
| #   - Targets are useful both in CI and developer workstations.
 | ||||
| #   - Handles cross-compiation for multiple OSes and architectures.
 | ||||
| #   - Bundles binaries and documentation into compressed archives, using tar/gz for Linux and Darwin, and zip for Windows.
 | ||||
| 
 | ||||
| 
 | ||||
| # Parameters
 | ||||
| PKG = code.ndumas.com/ndumas/wikilink-parser | ||||
| NAME = parse-wikilinks | ||||
| DOC = README.md LICENSE | ||||
| 
 | ||||
| 
 | ||||
| # Replace backslashes with forward slashes for use on Windows.
 | ||||
| # Make is !@#$ing weird.
 | ||||
| E := | ||||
| BSLASH := \$E | ||||
| FSLASH := / | ||||
| 
 | ||||
| # Directories
 | ||||
| WD := $(subst $(BSLASH),$(FSLASH),$(shell pwd)) | ||||
| MD := $(subst $(BSLASH),$(FSLASH),$(shell dirname "$(realpath $(lastword $(MAKEFILE_LIST)))")) | ||||
| PKGDIR = $(MD) | ||||
| CMDDIR = $(PKGDIR)/cmd | ||||
| DISTDIR ?= $(WD)/dist | ||||
| RPTDIR ?= $(WD)/reports | ||||
| GP = $(subst $(BSLASH),$(FSLASH),$(GOPATH)) | ||||
| 
 | ||||
| # Parameters
 | ||||
| VERSION ?= $(shell git -C "$(MD)" describe --tags --dirty=-dev) | ||||
| COMMIT_ID := $(shell git -C "$(MD)" rev-parse HEAD | head -c8) | ||||
| BUILD_TAGS ?= release | ||||
| CMDPKG = $(PKG)/cmd | ||||
| CMDS := $(shell find "$(CMDDIR)/" -mindepth 1 -maxdepth 1 -type d | sed 's/ /\\ /g' | xargs -n1 basename) | ||||
| BENCHCPUS ?= 1,2,4 | ||||
| 
 | ||||
| # Commands
 | ||||
| GOCMD = go | ||||
| ARCHES ?= amd64 386 | ||||
| OSES ?= windows linux darwin | ||||
| OUTTPL = $(DISTDIR)/$(NAME)-$(VERSION)-{{.OS}}_{{.Arch}}/{{.Dir}} | ||||
| LDFLAGS = -X $(PKG).Version=$(VERSION) -X $(PKG).Build=$(COMMIT_ID) | ||||
| GOBUILD = gox -osarch="!darwin/386" -rebuild -gocmd="$(GOCMD)" -arch="$(ARCHES)" -os="$(OSES)" -output="$(OUTTPL)" -tags "$(BUILD_TAGS)" -ldflags "$(LDFLAGS)" | ||||
| GOCLEAN = $(GOCMD) clean | ||||
| GOINSTALL = $(GOCMD) install -a -tags "$(BUILD_TAGS)" -ldflags "$(LDFLAGS)" | ||||
| GOTEST = $(GOCMD) test -v -tags "$(BUILD_TAGS)" | ||||
| DISABLED_LINTERS = varnamelen,interfacer,ifshort,exhaustivestruct,maligned,varcheck,scopelint,structcheck,deadcode,nosnakecase,golint,depguard | ||||
| GOLINT = golangci-lint run --enable-all --disable "$(DISABLED_LINTERS)" --timeout=30s --tests | ||||
| GODEP = $(GOCMD) get -d -t | ||||
| GOFMT = goreturns -w | ||||
| GOBENCH = $(GOCMD) test -v -tags "$(BUILD_TAGS)" -cpu=$(BENCHCPUS) -run=NOTHING -bench=. -benchmem -outputdir "$(RPTDIR)" | ||||
| GZCMD = tar -czf | ||||
| ZIPCMD = zip | ||||
| SHACMD = sha256sum | ||||
| SLOCCMD = cloc --by-file --xml --exclude-dir="vendor" --include-lang="Go" | ||||
| XUCMD = go2xunit | ||||
| DOCKER_CMD=docker --config ~/.docker/ | ||||
| 
 | ||||
| # Dynamic Targets
 | ||||
| INSTALL_TARGETS := $(addprefix install-,$(CMDS)) | ||||
| 
 | ||||
| .PHONY: all | ||||
| 
 | ||||
| all: debug setup dep format lint test bench build dist | ||||
| 
 | ||||
| git-push: | ||||
| 	git push origin main --tags | ||||
| 	git push github main --tags | ||||
| 
 | ||||
| release-major: bump-major git-push | ||||
| 
 | ||||
| release-minor: bump-minor git-push | ||||
| 
 | ||||
| release-patch: bump-patch git-push | ||||
| 
 | ||||
| 
 | ||||
| setup: setup-dirs setup-build setup-format setup-lint setup-reports setup-bump | ||||
| 
 | ||||
| setup-bump: | ||||
| 	go install github.com/guilhem/bump@latest | ||||
| 
 | ||||
| bump-major: setup-bump | ||||
| 	bump major | ||||
| 
 | ||||
| bump-minor: setup-bump | ||||
| 	bump minor | ||||
| 
 | ||||
| bump-patch: setup-bump | ||||
| 	bump patch | ||||
| 
 | ||||
| setup-reports: setup-dirs | ||||
| 	go install github.com/tebeka/go2xunit@latest | ||||
| 
 | ||||
| setup-build: setup-dirs | ||||
| 	go install github.com/mitchellh/gox@latest | ||||
| 
 | ||||
| setup-format: setup-dirs | ||||
| 	go install github.com/sqs/goreturns@latest | ||||
| 
 | ||||
| setup-lint: setup-dirs | ||||
| 	go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.53.1 | ||||
| 
 | ||||
| setup-dirs: | ||||
| 	mkdir -p "$(RPTDIR)" | ||||
| 	mkdir -p "$(DISTDIR)" | ||||
| 
 | ||||
| clean: | ||||
| 	$(GOCLEAN) $(PKG) | ||||
| 	rm -vrf "$(DISTDIR)"/* | ||||
| 	rm -vf "$(RPTDIR)"/* | ||||
| 
 | ||||
| format: | ||||
| 	$(GOFMT) "$(PKGDIR)" | ||||
| 
 | ||||
| dep: | ||||
| 	$(GODEP) $(PKG)/... | ||||
| 
 | ||||
| lint: setup-dirs dep | ||||
| 	$(GOLINT) "$(PKGDIR)" | tee "$(RPTDIR)/lint.out" | ||||
| 
 | ||||
| check: setup-dirs clean dep | ||||
| 	$(GOTEST) $$(go list "$(PKG)/..." | grep -v /vendor/) | tee "$(RPTDIR)/test.out" | ||||
| 
 | ||||
| bench: setup-dirs clean dep | ||||
| 	$(GOBENCH) $$(go list "$(PKG)/..." | grep -v /vendor/) | tee "$(RPTDIR)/bench.out" | ||||
| 
 | ||||
| report: check | ||||
| 	cd "$(PKGDIR)";$(SLOCCMD) --out="$(RPTDIR)/cloc.xml" . | tee "$(RPTDIR)/cloc.out" | ||||
| 	cat "$(RPTDIR)/test.out" | $(XUCMD) -output "$(RPTDIR)/tests.xml" | ||||
| 	go list -f '{{join .Deps "\n"}}' "$(CMDPKG)/..." | sort | uniq | xargs -I {} sh -c "go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' {} | tee -a '$(RPTDIR)/deps.out'" | ||||
| 
 | ||||
| build: $(CMDS) | ||||
| $(CMDS): setup-dirs dep | ||||
| 	$(GOBUILD) "$(CMDPKG)/$@" | tee "$(RPTDIR)/build-$@.out" | ||||
| install: $(INSTALL_TARGETS) | ||||
| $(INSTALL_TARGETS): | ||||
| 	$(GOINSTALL) "$(CMDPKG)/$(subst install-,,$@)" | ||||
| 
 | ||||
| dist: clean build | ||||
| 	for docfile in $(DOC); do \
 | ||||
| 		for dir in "$(DISTDIR)"/*; do \
 | ||||
| 			cp "$(PKGDIR)/$$docfile" "$$dir/"; \
 | ||||
| 		done; \
 | ||||
| 	done | ||||
| 	cd "$(DISTDIR)"; for dir in ./*linux*; do $(GZCMD) "$(basename "$$dir").tar.gz" "$$dir"; done | ||||
| 	cd "$(DISTDIR)"; for dir in ./*windows*; do $(ZIPCMD) "$(basename "$$dir").zip" "$$dir"; done | ||||
| 	cd "$(DISTDIR)"; for dir in ./*darwin*; do $(GZCMD) "$(basename "$$dir").tar.gz" "$$dir"; done | ||||
| 	cd "$(DISTDIR)"; find . -maxdepth 1 -type f -printf "$(SHACMD) %P | tee \"./%P.sha\"\n" | sh | ||||
| 	$(info "Built v$(VERSION), build $(COMMIT_ID)") | ||||
| 
 | ||||
| 
 | ||||
| .PHONY: docker | ||||
| docker: docker-image docker-push | ||||
| 
 | ||||
| .PHONY: docker-push | ||||
| docker-push: | ||||
| 	$(DOCKER_CMD) tag code.ndumas.com/ndumas/wikilink-parser:$(VERSION) code.ndumas.com/ndumas/wikilink-parser:latest | ||||
| 	$(DOCKER_CMD) push code.ndumas.com/ndumas/wikilink-parser:latest | ||||
| 	$(DOCKER_CMD) push code.ndumas.com/ndumas/wikilink-parser:$(VERSION) | ||||
| 
 | ||||
| .PHONY: docker-image | ||||
| docker-image: | ||||
| 	$(DOCKER_CMD) build --build-arg VERSION=$(VERSION) -t code.ndumas.com/ndumas/wikilink-parser:$(VERSION) . | ||||
| 
 | ||||
| .PHONY: build-alpine | ||||
| build-alpine: | ||||
| # this version breaks build variable injection
 | ||||
| # CGO_ENABLED=0 GOOS=linux go build -ldflags="buildmode=exe $(LDFLAGS) -linkmode external -w -extldflags '-static' "  -o $(DISTDIR)/$(NAME)-$(VERSION)-alpine/obp cmd/obp/*.go
 | ||||
| 	CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)"  -o $(DISTDIR)/$(NAME)-$(VERSION)-alpine/obp cmd/obp/*.go | ||||
| 
 | ||||
| 
 | ||||
| debug: | ||||
| 	$(info MD=$(MD)) | ||||
| 	$(info WD=$(WD)) | ||||
| 	$(info PKG=$(PKG)) | ||||
| 	$(info PKGDIR=$(PKGDIR)) | ||||
| 	$(info DISTDIR=$(DISTDIR)) | ||||
| 	$(info VERSION=$(VERSION)) | ||||
| 	$(info COMMIT_ID=$(COMMIT_ID)) | ||||
| 	$(info BUILD_TAGS=$(BUILD_TAGS)) | ||||
| 	$(info CMDS=$(CMDS)) | ||||
| 	$(info BUILD_TARGETS=$(BUILD_TARGETS)) | ||||
| 	$(info INSTALL_TARGETS=$(INSTALL_TARGETS)) | ||||
| @ -1,3 +1,3 @@ | ||||
| module wikilinks | ||||
| module code.ndumas.com/ndumas/wikilink-parser | ||||
| 
 | ||||
| go 1.19 | ||||
|  | ||||
| @ -1,54 +0,0 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"log" | ||||
| 	"regexp" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	alias      = regexp.MustCompile(`\|(.*)`) | ||||
| 	link       = regexp.MustCompile(`^([a-zA-Z ]+)?[\|\#\^\\]?`) | ||||
| 	subsection = regexp.MustCompile(`#([\w\s]+)`) | ||||
| 	block      = regexp.MustCompile(`#\^([a-zA-Z ]+)`) | ||||
| 	wholeLink  = regexp.MustCompile(`\[\[(.*)\]\]`) | ||||
| ) | ||||
| 
 | ||||
| type Link struct { | ||||
| 	Dest, Alias, Subsection, Block string | ||||
| } | ||||
| 
 | ||||
| func ExtractLink(raw string) Link { | ||||
| 	var li Link | ||||
| 
 | ||||
| 	rawLinkMatch := wholeLink.FindAllStringSubmatch(raw, -1) | ||||
| 	var rawLink string | ||||
| 	if len(rawLinkMatch) > 0 { | ||||
| 		rawLink = rawLinkMatch[0][1] | ||||
| 	} | ||||
| 
 | ||||
| 	l := link.FindAllStringSubmatch(rawLink, -1) | ||||
| 	if len(l) > 0 { | ||||
| 		li.Dest = l[0][1] | ||||
| 	} | ||||
| 
 | ||||
| 	a := alias.FindAllStringSubmatch(rawLink, -1) | ||||
| 	if len(a) > 0 { | ||||
| 		li.Alias = a[0][1] | ||||
| 	} | ||||
| 
 | ||||
| 	s := subsection.FindAllStringSubmatch(rawLink, -1) | ||||
| 	if len(s) > 0 { | ||||
| 		li.Subsection = s[0][1] | ||||
| 	} | ||||
| 
 | ||||
| 	b := block.FindAllStringSubmatch(rawLink, -1) | ||||
| 	if len(b) > 0 { | ||||
| 		li.Block = b[0][1] | ||||
| 	} | ||||
| 
 | ||||
| 	return li | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	log.Printf("%#v\n", ExtractLink(`Embedding a link in a bigger block of text [[Regular Link#^link to block]] shouldn't cause any problems `)) | ||||
| } | ||||
| @ -1,34 +0,0 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func Test_ExtractLink(t *testing.T) { | ||||
| 	tcs := []struct { | ||||
| 		name     string | ||||
| 		in       string | ||||
| 		expected Link | ||||
| 	}{ | ||||
| 		{"link", `[[Regular Link]]`, Link{Dest: "Regular Link"}}, | ||||
| 		{"transclude+link", `![[Transcluded Link]]`, Link{Dest: "Transcluded Link"}}, | ||||
| 		{"link+alias", `[[Regular Link|Alias]]`, Link{Dest: "Regular Link", Alias: "Alias"}}, | ||||
| 		{"link+subsection", `[[Regular Link#Subsection of page]]`, Link{Dest: "Regular Link", Subsection: "Subsection of page"}}, | ||||
| 		{"link+block", `[[Regular Link#^link to block]]`, Link{Dest: "Regular Link", Block: "link to block"}}, | ||||
| 		{"link+subsection+alias", `[[Regular Link#Subsection of page|Alias]]`, Link{Dest: "Regular Link", Subsection: "Subsection of page", Alias: "Alias"}}, | ||||
| 		{"link+block+alias", `[[Regular Link#^link to block|Alias]]`, Link{Dest: "Regular Link", Block: "link to block", Alias: "Alias"}}, | ||||
| 		{"link+alias+escape", `[[Regular Link\|Alias]]`, Link{Dest: "Regular Link", Alias: "Alias"}}, | ||||
| 		{"link+subsection+alias+escape", `[[Regular Link#Subsection of page\|Alias]]`, Link{Dest: "Regular Link", Subsection: "Subsection of page", Alias: "Alias"}}, | ||||
| 		{"link+block+alias+escape", `[[Regular Link#^link to block\|Alias]]`, Link{Dest: "Regular Link", Block: "link to block", Alias: "Alias"}}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range tcs { | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			out := ExtractLink(tc.in) | ||||
| 			if out != tc.expected { | ||||
| 				t.Logf("got %#v\n", out) | ||||
| 				t.Fail() | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| package wikilink | ||||
| 
 | ||||
| import ( | ||||
| // "log"
 | ||||
| // "github.com/13rac1/goldmark-wikilink"
 | ||||
| ) | ||||
| 
 | ||||
| type Wikilink struct { | ||||
| 	Link     string | ||||
| 	Fragment string | ||||
| 	Alias    string | ||||
| } | ||||
| 
 | ||||
| func Extract(raw string) Wikilink { | ||||
| 	var wl Wikilink | ||||
| 
 | ||||
| 	return wl | ||||
| } | ||||
| @ -0,0 +1,52 @@ | ||||
| package wikilink_test | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.ndumas.com/ndumas/wikilink-parser" | ||||
| ) | ||||
| 
 | ||||
| func Test_Extract_Link(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	tcs := []struct { | ||||
| 		name     string | ||||
| 		in       string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{name: "wikilink", in: "[[wikilink]]", expected: "wikilink"}, | ||||
| 		{name: "wikilink|display name", in: "[[wikilink|display name]]", expected: "wikilink"}, | ||||
| 		{name: "wikilink|display name|second pipe", in: "[[wikilink|display name|second pipe]]", expected: "wikilink"}, | ||||
| 		{name: "wikilink with numeric alias|420|second pipe", in: "[[wikilink|420|second pipe]]", expected: "wikilink with numeric aliases"}, | ||||
| 		{name: "wikilink with spaces in filename", in: "[[wikilink spaces]]", expected: "wikilink"}, | ||||
| 		{name: "#heading", in: "[[#heading]]", expected: ""}, | ||||
| 		{name: "wikilink#heading", in: "[[wikilink#heading]]", expected: "wikilink"}, | ||||
| 		{name: "wikilink#heading|display name", in: "[[wikilink#heading|display name]]", expected: "wikilink"}, | ||||
| 		{name: "wikilink#heading|display name", in: "[[wikilink#heading|display name]]", expected: "wikilink"}, | ||||
| 		{name: "wikilink with numeric aliases#heading|420|display name", in: "[[wikilink#heading|420|second pipe]]", expected: "wikilink"}, | ||||
| 	} | ||||
| 	/* | ||||
| 
 | ||||
| 
 | ||||
| 		"[[#^blockRef]]" | ||||
| 		"[[wikilink#^blockRef]]" | ||||
| 		"[[wikilink#^blockRef|display name]]" | ||||
| 		"[[wikilink#^blockRef|display name|secondpipe]]" | ||||
| 
 | ||||
| 		"[[#^blockRef]]" | ||||
| 		"[[wikilink#^blockRef]]" | ||||
| 		"[[wikilink#^blockRef|display name|secondpipe]]" | ||||
| 	*/ | ||||
| 
 | ||||
| 	for _, tc := range tcs { | ||||
| 		tc := tc | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			t.Parallel() | ||||
| 			out := wikilink.Extract(tc.in) | ||||
| 			if out.Link != tc.expected { | ||||
| 				t.Logf("got %#v\n", out) | ||||
| 				t.Fail() | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue