mirror of
https://github.com/mipmip/home-manager-option-search.git
synced 2024-07-14 18:30:29 +03:00
Merge branch 'nativeOptionsParse'
This commit is contained in:
commit
84dc79b6c0
41
.github/workflows/update.yml
vendored
41
.github/workflows/update.yml
vendored
@ -10,25 +10,40 @@ jobs:
|
||||
name: parse options and create search
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3
|
||||
#bundler-cache: true
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
|
||||
- run: |
|
||||
gem install bundler
|
||||
bundle install --jobs 4 --retry 3
|
||||
- name: master-options
|
||||
run: ./scripts/build_hm_options.sh
|
||||
|
||||
- run: |
|
||||
rm -v data/options.json
|
||||
ruby scripts/parse_appendix.rb
|
||||
ls -al data/options.json
|
||||
cat data/options.json | jq ".last_update"
|
||||
- name: update gitignore
|
||||
run: echo result > .gitignore
|
||||
|
||||
- name: release-options
|
||||
env:
|
||||
HM_RELEASE: release-23.11
|
||||
run: ./scripts/build_hm_options.sh
|
||||
|
||||
- name: release-options
|
||||
env:
|
||||
HM_RELEASE: release-23.05
|
||||
run: ./scripts/build_hm_options.sh
|
||||
#
|
||||
# - name: master-options
|
||||
# env:
|
||||
# RELEASE: release-22.11
|
||||
# run: ./scripts/build_hm_options.sh
|
||||
#
|
||||
# - name: master-options
|
||||
# env:
|
||||
# RELEASE: release-22.05
|
||||
# run: ./scripts/build_hm_options.sh
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_branch: pages-${{ github.ref_name }}
|
||||
publish_dir: .
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.temp.html
|
||||
.nix-gems
|
||||
.bundle
|
||||
result
|
||||
data/hm-options*
|
||||
|
@ -5,6 +5,9 @@
|
||||
- keyboard (tab) navigation (thanks to github.com/hallundbaek)
|
||||
- better result sorting (thanks to github.com/hallundbaek)
|
||||
- style improvements
|
||||
- native options export
|
||||
- improve example and descriptions layout
|
||||
- move to extranix.com
|
||||
|
||||
## Version 1.4
|
||||
|
||||
|
17
Gemfile.lock
17
Gemfile.lock
@ -1,17 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
mini_portile2 (2.8.5)
|
||||
nokogiri (1.16.2)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
racc (1.7.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
nokogiri
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
0
data/.keep
Normal file
0
data/.keep
Normal file
File diff suppressed because one or more lines are too long
19
index.html
19
index.html
@ -63,7 +63,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="searchform" xstyle="background-color: white;top:54px;position:sticky;>
|
||||
<div id="searchform" xstyle="background-color: white;top:54px;position:sticky;">
|
||||
<form method="get" action="?" onSubmit="searchEnter()">
|
||||
<div class="form-group">
|
||||
<label for="searchInput">
|
||||
@ -73,11 +73,26 @@
|
||||
|
||||
<input class="form-control" type="search" id="searchInput" autofocus="autofocus" placeholder="Search.. e.g. vim">
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="release">
|
||||
Home Manager release
|
||||
</label>
|
||||
<select id="releaseSelect">
|
||||
<option value="master">unstable</option>
|
||||
<option value="release-23.11">23.11</option>
|
||||
<option value="release-23.05">23.05</option>
|
||||
<!--
|
||||
<option value="release-22.11">22.11</option>
|
||||
<option value="release-22.05">22.05</option>
|
||||
-->
|
||||
</select>
|
||||
<!--
|
||||
<label for="advcheck">
|
||||
search options
|
||||
<input id="advcheck" type="checkbox" data-toggle="collapse" data-target="#advanced" />
|
||||
<input id="advcheck" type="checkbox" data-toggle="collapse" data-target="#advanced" />
|
||||
-->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
84
js/script.js
84
js/script.js
@ -9,12 +9,14 @@ var modalBody = document.getElementById('myModalBody');
|
||||
|
||||
var rebuildAndRerunSearch = function() {
|
||||
rebuildSearchIndex();
|
||||
searchOptions();
|
||||
searchOptions('');
|
||||
};
|
||||
|
||||
var docOnload = function(){
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const query = urlParams.get('query') ?? '';
|
||||
|
||||
searchInput.value = query;
|
||||
searchOptions(query);
|
||||
|
||||
@ -47,6 +49,7 @@ var indexedOptionsTableHeader = document.getElementById('indexedOptionsTableHead
|
||||
var lastUpdateElement = document.getElementById('lastUpdateElement');
|
||||
var indexedOptionsTBody = indexedOptionsTable.tBodies[0];
|
||||
var searchInput = document.getElementById('searchInput');
|
||||
var releaseSelect = document.getElementById('releaseSelect');
|
||||
var optionCountBadge = document.getElementById('optionCountBadge');
|
||||
|
||||
var updateLastUpdate = function(lastUpdate) {
|
||||
@ -105,21 +108,37 @@ var updateOptionsTable = function(options) {
|
||||
}
|
||||
};
|
||||
|
||||
function parseDescription(text){
|
||||
|
||||
text = text.replace(/<https(\s*([^>]*))/gi ,'<a href="https$1"><https$1</a>');
|
||||
text = text.replace(/\[\]\(#opt-(\s*([^)]*))/gi ,'<strong>$1</strong>').replace(/\)/gi,'');
|
||||
//[](#opt-wayland.windowManager.hyprland.plugins)
|
||||
text = text.replace(/\{var\}(\s*([^\n]*))/gi ,'<strong>$1</strong>').replace(/`/gi,'')
|
||||
text = text.replace(/:::\ \{\.note\}(\s*([^:::]*))/gi ,'<div class="alert alert-info" role="alert">$1</div>').replace(/:::/,'').replace(/\n/g, '<br />')
|
||||
return text;
|
||||
}
|
||||
|
||||
var expandOption = function(el){
|
||||
|
||||
modalTitle.innerHTML = currentSet[el].title;
|
||||
|
||||
var elDesc = "<h5 style='margin:1em 0 0 0'>Description</h5><div>" + currentSet[el].description + "</div>";
|
||||
//console.log(currentSet[el].description.replace(/:::\ \{\.note\}(\s*([^:::]*))/gi ,'<div class="alert alert-info" role="alert">$1</div>').replace(/:::/,''));
|
||||
|
||||
var elDesc = "<h5 style='margin:1em 0 0 0'>Description</h5><div>" + parseDescription(currentSet[el].description) + "</div>";
|
||||
var elType = "<h5 style='margin:1em 0 0 0'>Type</h5><div>" + currentSet[el].type + "</div>";
|
||||
var elNote = ( currentSet[el].note == "" ? "": "<h5 style='margin:1em 0 0 0'>Note</h5><div>" + currentSet[el].note + "</div>");
|
||||
//var elNote = ( currentSet[el].note == "" ? "": "<h5 style='margin:1em 0 0 0'>Note</h5><div>" + currentSet[el].note + "</div>");
|
||||
var elDefault = "<h5 style='margin:1em 0 0 0'>Default</h5><div><pre style='margin-top:0.5em'>" + currentSet[el].default + "</pre></div>";
|
||||
var elExample = ( currentSet[el].example == "" ? "" : "<h5 style='margin:1em 0 0 0'>Example</h5><div><pre style='margin-top:0.5em'>" + currentSet[el].example + "</pre></div>");
|
||||
|
||||
var declared_by_str = currentSet[el].declared_by;
|
||||
//var declared_by_str = currentSet[el].declarations[0].name;
|
||||
//console.log(currentSet[el].declarations[0].name);
|
||||
var declared_by_str;
|
||||
if(currentSet[el].declarations && currentSet[el].declarations.length >0 && currentSet[el].declarations[0].name){
|
||||
declared_by_str = '<a href="'+currentSet[el].declarations[0].url+'">'+currentSet[el].declarations[0].name.replace(/</,'<').replace(/>/,'>')+'</a>';
|
||||
}
|
||||
|
||||
var elDeclaredBy = "<h5 style='margin:1em 0 0 0'>Declared by</h5><div>" + declared_by_str+ "</div>";
|
||||
modalBody.innerHTML = elDesc + elNote + elType + elDefault + elExample + elDeclaredBy;
|
||||
|
||||
modalBody.innerHTML = elDesc + elType + elDefault + elExample + elDeclaredBy;
|
||||
|
||||
$('#myModal').modal('show')
|
||||
}
|
||||
@ -137,17 +156,19 @@ var updateOptionCountAndTable = function() {
|
||||
}
|
||||
};
|
||||
|
||||
var setSearchQueryToUrlParam = function(query) {
|
||||
var newUrl = '';
|
||||
|
||||
var setSearchQueryToUrlParam = function(query,release) {
|
||||
const urlParams = new URLSearchParams();
|
||||
urlParams.set('query', query);
|
||||
const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
|
||||
newUrl = `${window.location.pathname}?${urlParams.toString()}&release=${release}`;
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
};
|
||||
|
||||
var searchOptions = function(query) {
|
||||
results = search.search(query);
|
||||
|
||||
// Performance optimization: skip ordering if query is a single character
|
||||
// Performance optimization: skip ordering if query is a single character
|
||||
if (query.length > 1) {
|
||||
// Split terms by non-alphanumeric chars
|
||||
const terms = query.split(/[^A-Za-z0-9]/);
|
||||
@ -179,12 +200,12 @@ var searchOptions = function(query) {
|
||||
if (bIndex == -1) return -1;
|
||||
if (aIndex !== bIndex) return aIndex - bIndex
|
||||
|
||||
// Increment lastIndex by found index and term length, to sort based
|
||||
// Increment lastIndex by found index and term length, to sort based
|
||||
// on remaining string.
|
||||
lastIndex += aIndex + term.length;
|
||||
}
|
||||
|
||||
// Default to alphabetical order otherwise
|
||||
// Default to alphabetical order otherwise
|
||||
return aConcat.localeCompare(bConcat);
|
||||
});
|
||||
}
|
||||
@ -196,16 +217,42 @@ const SEARCH_INPUT_DEBOUNCE_MS = 100;
|
||||
|
||||
let debounceTimer;
|
||||
|
||||
searchInput.oninput = function() {
|
||||
clearTimeout(debounceTimer);
|
||||
|
||||
function newSearch(){
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => {
|
||||
|
||||
const query = searchInput.value;
|
||||
setSearchQueryToUrlParam(query);
|
||||
const release = releaseSelect.selectedOptions[0].value;
|
||||
|
||||
setSearchQueryToUrlParam(query, release);
|
||||
searchOptions(query);
|
||||
|
||||
}, SEARCH_INPUT_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
searchInput.oninput = function() {
|
||||
newSearch();
|
||||
};
|
||||
|
||||
releaseSelect.onchange = function(){
|
||||
|
||||
const query = searchInput.value;
|
||||
const release = releaseSelect.selectedOptions[0].value;
|
||||
|
||||
setSearchQueryToUrlParam(query, release);
|
||||
|
||||
//window.location.reload(false);
|
||||
|
||||
window.location.replace(newUrl);
|
||||
|
||||
//newSearch();
|
||||
|
||||
//var release = releaseSelect.selectedOptions[0].value;
|
||||
//xmlhttp.open('GET', 'data/hm-options-'+release+'.json', true);
|
||||
//xmlhttp.send();
|
||||
}
|
||||
|
||||
var updateOptionCount = function(numOptions) {
|
||||
optionCountBadge.innerText = numOptions + ' options';
|
||||
};
|
||||
@ -237,9 +284,12 @@ xmlhttp.onreadystatechange = function() {
|
||||
if(searchInput.value.trim() ==""){
|
||||
updateOptionsTable(allOptions);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
xmlhttp.open('GET', 'data/options.json', true);
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const release = urlParams.get('release') ?? 'master';
|
||||
document.getElementById('releaseSelect').value = release;
|
||||
|
||||
xmlhttp.open('GET', 'data/hm-options-'+release+'.json', true);
|
||||
xmlhttp.send();
|
||||
|
15
scripts/build_hm_options.sh
Executable file
15
scripts/build_hm_options.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Copyright 2024 Pim Snel <post@pimsnel.com
|
||||
# License: MIT
|
||||
|
||||
if [ -z $HM_RELEASE ]; then
|
||||
HM_RELEASE=master
|
||||
fi
|
||||
|
||||
echo "building Home Manager options from ${HM_RELEASE}"
|
||||
|
||||
rm -Rf result
|
||||
nix build github:nix-community/home-manager/${HM_RELEASE}#docs-json --no-write-lock-file
|
||||
rm -f ./data/hm-options-${HM_RELEASE}.json
|
||||
ruby ./scripts/parse_options-json.rb
|
@ -1,111 +0,0 @@
|
||||
require 'open-uri'
|
||||
require 'nokogiri'
|
||||
require 'json'
|
||||
require 'pp'
|
||||
|
||||
url = 'https://nix-community.github.io/home-manager/options.xhtml'
|
||||
html=""
|
||||
URI.open(url) do |f|
|
||||
html = f.read
|
||||
end
|
||||
html.gsub!("\n","")
|
||||
|
||||
doc = Nokogiri::HTML(html)
|
||||
|
||||
data = doc.search('dl.variablelist')
|
||||
|
||||
outarr = []
|
||||
|
||||
data.search('dt').each do |dt|
|
||||
dds = dt.xpath("following-sibling::dd[1]")
|
||||
|
||||
option_title = dt.css("span a code").inner_html
|
||||
|
||||
option_desc = ""
|
||||
option_note = ""
|
||||
option_type = ""
|
||||
option_default = ""
|
||||
option_example = ""
|
||||
option_declared_by = ""
|
||||
option_declared_by_link = ""
|
||||
|
||||
i = 0
|
||||
dds.children.each do | ch |
|
||||
i+=1
|
||||
p i.to_s + " " + ch.text
|
||||
if i == 1
|
||||
option_desc = ch.text.strip.gsub("\n"," ")
|
||||
elsif i == 2
|
||||
if ch.text[0..4] == "Type:"
|
||||
option_type = ch.text[5..-1].strip
|
||||
else
|
||||
option_note = ch.text.strip
|
||||
end
|
||||
|
||||
else
|
||||
if ch.text[0..4] == "Type:"
|
||||
option_type = ch.text[5..-1].strip.gsub("\n","")
|
||||
elsif ch.text[0..7] == "Default:"
|
||||
option_default = ch.text[8..-1].strip.gsub("\n","").gsub(/\s+/, ' ')
|
||||
elsif ch.text[0..11] == "Declared by:"
|
||||
declared = ch.xpath("following-sibling::table[1]")
|
||||
option_declared_by = declared.text.strip.gsub(/\s+/, "\n")
|
||||
declare_arr = option_declared_by.split("\n")
|
||||
|
||||
option_declared_by_link = ""
|
||||
decllink = ""
|
||||
if declare_arr.length > 1
|
||||
p option_title.upcase
|
||||
p declare_arr
|
||||
end
|
||||
declare_arr.each do | decl |
|
||||
decllink = 'https://github.com/nix-community/home-manager/blob/master/' + decl.gsub('<home-manager/','').gsub('>','')
|
||||
decltext = decl.gsub('<','').gsub('>','')
|
||||
option_declared_by_link += '<a href="'+decllink+'">'+decltext+'</a><br/>'
|
||||
end
|
||||
elsif ch.text[0..7] == "Example:"
|
||||
example = ch.xpath("following-sibling::pre[1]")
|
||||
if example.length > 0
|
||||
option_example = example.text
|
||||
else
|
||||
option_example = ch.xpath("code").text
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# print "---------------------------------------\n"
|
||||
print "TITLE:\n#{option_title}\n\n"
|
||||
print "DESC:\n#{option_desc}\n\n"
|
||||
# print "NOTE:\n#{option_note}\n\n" if option_note != ""
|
||||
# print "TYPE:\n#{option_type}\n\n"
|
||||
# print "DEFAULT:\n#{option_default}\n\n"
|
||||
# print "EXAMPLE:\n#{option_example}\n\n" if option_example != ""
|
||||
# print "DECLARED BY:\n#{option_declared_by}\n\n"
|
||||
# print "\n"
|
||||
#
|
||||
outrec = {}
|
||||
outrec["title"] = option_title
|
||||
outrec["description"] = option_desc
|
||||
outrec["note"] = option_note
|
||||
outrec["type"] = option_type
|
||||
outrec["default"] = option_default
|
||||
outrec["example"] = option_example
|
||||
outrec["declared_by"] = option_declared_by_link
|
||||
|
||||
outarr << outrec
|
||||
|
||||
end
|
||||
|
||||
|
||||
outobj = {}
|
||||
time = Time.new
|
||||
outobj["last_update"] = time.utc.strftime("%B %d, %Y at %k:%M UTC")
|
||||
outobj["options"] = outarr
|
||||
|
||||
File.open("data/options.json","w") do |f|
|
||||
f.write(outobj.to_json)
|
||||
end
|
||||
|
||||
print "Finished parsing home manager options."
|
49
scripts/parse_options-json.rb
Normal file
49
scripts/parse_options-json.rb
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright 2024 Pim Snel <post@pimsnel.com
|
||||
# License: MIT
|
||||
|
||||
require 'json'
|
||||
require 'pp'
|
||||
|
||||
if not ENV['HM_RELEASE']
|
||||
ENV['HM_RELEASE'] = "master"
|
||||
end
|
||||
|
||||
p ENV['HM_RELEASE']
|
||||
|
||||
in_file = File.read("./result/share/doc/home-manager/options.json")
|
||||
parsed = JSON.parse(in_file)
|
||||
|
||||
options_arr = []
|
||||
parsed.each do | name, val |
|
||||
|
||||
next if name == '_module.args'
|
||||
|
||||
val['title'] = name
|
||||
|
||||
if val.key? "example"
|
||||
val['example'] = val['example']['text']
|
||||
else
|
||||
val['example'] = ""
|
||||
end
|
||||
|
||||
if val.key? "default"
|
||||
val['default'] = val['default']['text']
|
||||
else
|
||||
val['default'] = ""
|
||||
end
|
||||
|
||||
options_arr << val
|
||||
end
|
||||
|
||||
outobj = {}
|
||||
time = Time.new
|
||||
outobj["last_update"] = time.utc.strftime("%B %d, %Y at %k:%M UTC")
|
||||
outobj["options"] = options_arr
|
||||
|
||||
filename = "data/hm-options-#{ENV['HM_RELEASE']}.json"
|
||||
|
||||
File.open(filename,"w") do |f|
|
||||
f.write(outobj.to_json)
|
||||
end
|
||||
|
||||
print "Finished parsing home manager options."
|
16
shell.nix
16
shell.nix
@ -1,16 +0,0 @@
|
||||
with (import <nixpkgs> {});
|
||||
mkShell {
|
||||
buildInputs = [
|
||||
ruby_3_3
|
||||
];
|
||||
shellHook = ''
|
||||
mkdir -p .nix-gems
|
||||
export GEM_HOME=$PWD/.nix-gems
|
||||
export GEM_PATH=$GEM_HOME
|
||||
export PATH=$GEM_HOME/bin:$PATH
|
||||
export PATH=$PWD/bin:$PATH
|
||||
|
||||
gem list -i ^bundler$ -v 1.17.3 || gem install bundler --version=1.17.3 --no-document
|
||||
bundle
|
||||
'';
|
||||
}
|
Loading…
Reference in New Issue
Block a user