This commit is contained in:
ge 2025-01-22 03:23:08 +03:00
commit d5931aa5e0
13 changed files with 8849 additions and 0 deletions

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.v]
indent_style = tab

8
.gitattributes vendored Normal file
View File

@ -0,0 +1,8 @@
* text=auto eol=lf
*.bat eol=crlf
*.v linguist-language=V
*.vv linguist-language=V
*.vsh linguist-language=V
v.mod linguist-language=V
.vdocignore linguist-language=ignore

26
.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
# Binaries for programs and plugins
main
licenseid
*.exe
*.exe~
*.so
*.dylib
*.dll
# Ignore binary output folders
bin/
# Ignore common editor/system specific metadata
.DS_Store
.idea/
.vscode/
*.iml
# ENV
.env
# vweb and database
*.db
*.js
/doc

23
Makefile Normal file
View File

@ -0,0 +1,23 @@
SRC_DIR = src
DOC_DIR = doc
SPDX_LICENSE_LIST_FILE = src/licenselist.json
SPDX_LICENSE_LIST_FILE_MIN = src/licenselist.min.json
SPDX_LICENSE_LIST_FILE_TMP = /tmp/licenselist.json.new
SPDX_LICENSE_LIST_JSON_URL = https://spdx.org/licenses/licenses.json
licenselist:
wget -q -O $(SPDX_LICENSE_LIST_FILE_TMP) $(SPDX_LICENSE_LIST_JSON_URL1)
if ! diff $(SPDX_LICENSE_LIST_FILE) $(SPDX_LICENSE_LIST_FILE_TMP) >/dev/null 2>&1; \
then mv -v $(SPDX_LICENSE_LIST_FILE_TMP) $(SPDX_LICENSE_LIST_FILE); \
fi
jq -c . < $(SPDX_LICENSE_LIST_FILE) > $(SPDX_LICENSE_LIST_FILE_MIN)
doc:
v doc -f html -m ./$(SRC_DIR) -o $(DOC_DIR)
serve: clean doc
v -e "import net.http.file; file.serve(folder: '$(DOC_DIR)')"
clean:
rm -r $(DOC_DIR) || true

6
README.md Normal file
View File

@ -0,0 +1,6 @@
## Query the SPDX license list and licenses information
`licenseid` module embeds the SPDX license list data file taken from
https://spdx.org/licenses/licenses.json and allows you to obtain basic
information about the license from this file, as well as request the
license texts and additional data from the network.

22
UNLICENSE Normal file
View File

@ -0,0 +1,22 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and
successors. We intend this dedication to be an overt act of relinquishment in
perpetuity of all present and future rights to this software under copyright
law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

54
examples/getlicense.v Normal file
View File

@ -0,0 +1,54 @@
import os
import os.cmdline
import licenseid
const help_text = 'download license text from internet and apply width (80 by default)'
const usage_text = 'usage: getlicense [-help] [-w <width>] <license_id>'
fn main() {
argv := os.args[1..]
opts := cmdline.only_options(argv)
mut args := cmdline.only_non_options(argv)
mut width := 80
for opt in opts {
match true {
opt in ['-h', '-help', '--help'] {
println(help_text)
println(usage_text)
exit(0)
}
opt == '-w' {
arg := cmdline.option(argv, '-w', '')
if arg.int() <= 0 {
eprintln('invalid width ${opt}')
exit(2)
}
width = arg.int()
args.delete(args.index(arg))
}
else {
eprintln('unrecognized option ${opt}')
exit(2)
}
}
}
if args.len != 1 {
eprintln(usage_text)
exit(2)
}
license := licenseid.query(args[0]) or {
eprintln(err)
exit(1)
}
details := license.details() or {
eprintln(err)
exit(1)
}
for line in details.license_text.split_into_lines() {
if line == '' {
println('')
} else {
println(line.wrap(width: width))
}
}
}

84
examples/mkvmod.v Normal file
View File

@ -0,0 +1,84 @@
import os
import term
import strings
import semver
import licenseid
struct Module {
pub mut:
name string
description string
version string = '0.0.0'
license string = 'MIT'
author string
}
fn make() string {
eprintln('Create new v.mod, press ^C to quit')
mut manifest := Module{}
for {
name := os.input(term.bold('Name: '))
if !name.is_blank() {
manifest.name = name
break
}
eprintln(term.bright_red('Name cannot be blank'))
}
manifest.description = os.input(term.bold('Description: '))
for {
version := os.input(term.bold('Version: '))
if version.is_blank() {
break
}
if semver.is_valid(version) {
manifest.version = version
break
}
eprintln(term.bright_red('${version} violates semantic versioning rules, see https://semver.org/ for info'))
}
manifest.author = os.input(term.bold('Author: '))
for {
license := os.input(term.bold('License: '))
if license.is_blank() {
break
}
if _ := licenseid.query(license) {
manifest.license = license
break
}
eprintln(term.bright_red('${license} is not valid SPDX license identifier, see https://spdx.org/licenses/ for info'))
}
vmod := gen_vmod(manifest)
eprintln(term.bright_blue(vmod))
if os.input(term.bold('This is correct? ')).to_lower() in ['y', 'yes'] {
return vmod
}
eprintln(term.bold(term.bright_red('Aborted')))
exit(1)
}
fn gen_vmod(m Module) string {
mut b := strings.new_builder(200)
b.writeln('Module {')
b.writeln("\tname: '${m.name}'")
b.writeln("\tdescription: '${m.description}'")
b.writeln("\tversion: '${m.version}'")
b.writeln("\tauthor: '${m.author}'")
b.writeln("\tlicense: '${m.license}'")
b.writeln('\tdependencies: []')
b.writeln('}')
return b.str()
}
fn main() {
if !os.exists('v.mod') {
vmod := make()
os.write_file('v.mod', vmod) or {
eprintln(err)
exit(1)
}
eprintln(term.bright_green('v.mod is done'))
return
}
eprintln(term.bright_yellow('v.mod is already done'))
}

65
src/licenseid.v Normal file
View File

@ -0,0 +1,65 @@
module licenseid
import json
import net.http
const licenses_file = $embed_file('licenselist.min.json')
const licenses = json.decode(LicenseList, licenses_file.to_string()) or { LicenseList{} }
struct LicenseList {
licenses []License
}
pub struct License {
pub:
license_id string @[json: licenseId]
name string
reference string
reference_number int @[json: referenceNumber]
details_url string @[json: detailsUrl]
is_osi_approved bool @[json: isOsiApproved]
is_deprecated_license_id bool @[json: isDeprecatedLicenseId]
see_also []string @[json: seeAlso]
}
pub struct LicenseDetails {
pub:
license_id string @[json: licenseId]
name string
license_text string @[json: licenseText]
license_text_html string @[json: licenseTextHtml]
license_template string @[json: standardLicenseTemplate]
is_osi_approved bool @[json: isOsiApproved]
is_deprecated_license_id bool @[json: isDeprecatedLicenseId]
cross_ref []Reference @[json: crossRef]
see_also []string @[json: seeAlso]
}
pub struct Reference {
pub:
match string
url string
is_valid bool @[json: isValid]
is_live bool @[json: isLive]
is_way_backlink bool @[json: isWayBackLink]
timestamp string
order int
}
// details fetches the license details object from SPDX data file using the
// details_url. Requires access to public network.
pub fn (l License) details() !LicenseDetails {
response := http.get(l.details_url)!
details := json.decode(LicenseDetails, response.body)!
return details
}
// query returns license object from embedded SPDX license list data file.
pub fn query(license_id string) !License {
for license in licenses.licenses {
if license.license_id == license_id {
return license
}
}
return error('${license_id} is not valid SPDX license ID')
}

8533
src/licenselist.json Normal file

File diff suppressed because it is too large Load Diff

1
src/licenselist.min.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
import licenseid
fn test_query() {
l := licenseid.query('GPL-3.0-or-later')!
assert l.license_id == 'GPL-3.0-or-later'
}
fn test_details() {
l := licenseid.query('Unlicense')!
details := l.details()!
assert details.name == 'The Unlicense'
}

7
v.mod Normal file
View File

@ -0,0 +1,7 @@
Module{
name: 'licenseid'
description: 'Query the SPDX license list and licenses information'
version: '0.0.1'
license: 'Unlicense'
dependencies: []
}