zarchitect 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/zarchitect +3 -0
- data/data/_zarchitect.yaml +22 -0
- data/data/post.md.erb +16 -0
- data/lib/zarchitect.rb +179 -0
- data/lib/zarchitect/assets.rb +50 -0
- data/lib/zarchitect/audio.rb +31 -0
- data/lib/zarchitect/category.rb +62 -0
- data/lib/zarchitect/cmd_misc.rb +34 -0
- data/lib/zarchitect/cmd_new.rb +75 -0
- data/lib/zarchitect/cmd_update.rb +34 -0
- data/lib/zarchitect/config.rb +285 -0
- data/lib/zarchitect/content.rb +286 -0
- data/lib/zarchitect/file_manager.rb +64 -0
- data/lib/zarchitect/html.rb +54 -0
- data/lib/zarchitect/htmltable.rb +154 -0
- data/lib/zarchitect/image.rb +162 -0
- data/lib/zarchitect/image_set.rb +46 -0
- data/lib/zarchitect/index.rb +224 -0
- data/lib/zarchitect/misc_file.rb +19 -0
- data/lib/zarchitect/paginator.rb +73 -0
- data/lib/zarchitect/post.rb +202 -0
- data/lib/zarchitect/rouge_html.rb +34 -0
- data/lib/zarchitect/rss.rb +60 -0
- data/lib/zarchitect/scss.rb +32 -0
- data/lib/zarchitect/section.rb +126 -0
- data/lib/zarchitect/tag.rb +46 -0
- data/lib/zarchitect/util.rb +41 -0
- data/lib/zarchitect/video.rb +37 -0
- data/lib/zarchitect/zerb.rb +120 -0
- metadata +73 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 607e19ad07725bebd0ded8af4ab4ee37759e67b5648a0e5906cf542e9606cef8
|
|
4
|
+
data.tar.gz: 05f141c29c6521b1132a16730140034d16e1367415ef7ae2c5f991320e6c24d5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e550cbd2afe69837e0d3da6036c109f119bec7c2d2288bfcc749d504984515036622938267660ea1b0680fa3f6ecc05f401da7e18f16f28d5bb6de5c529f52b0
|
|
7
|
+
data.tar.gz: 9df3edff73bba15843381649827d0f97a12804fc1df8ff7bccb63a3de00a5b429afe389a89a0027a8328944a97a53f28aed854cb533c18fe237d6e9e7aabf72d
|
data/bin/zarchitect
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
--- # zarchitect website config file
|
|
2
|
+
url: http://www.example.com
|
|
3
|
+
email: user@example.com
|
|
4
|
+
site_name: example.com
|
|
5
|
+
site_slogan: the best exampled
|
|
6
|
+
site_description: "a short description of this website"
|
|
7
|
+
admin: webmaster_name
|
|
8
|
+
origin_year: 2020 # can be used for dynamic copyright notices
|
|
9
|
+
title_sep: " | " # separator used in the html title meta tag
|
|
10
|
+
site_keywords: keyA, keyB # keywords for meta tag, string
|
|
11
|
+
thumbl: [640,480] # size for large thumbnails
|
|
12
|
+
thumbs: [320, 240] # size for small thumbnails
|
|
13
|
+
image_limit: 20.0 # MB
|
|
14
|
+
audio_limit: 20.0
|
|
15
|
+
video_limit: 40.0
|
|
16
|
+
rss_size: 10 # number of items in rss feed
|
|
17
|
+
scss_enabled: # root is _assets/ | list of scss files to be turned into css
|
|
18
|
+
- "example.scss"
|
|
19
|
+
exclude_assets: # files with these extensions don't get copied into html tree
|
|
20
|
+
- .scss
|
|
21
|
+
- .scss.swp
|
|
22
|
+
- .css.map
|
data/data/post.md.erb
ADDED
data/lib/zarchitect.rb
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
require 'gpi'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
require 'erb'
|
|
4
|
+
require 'sanitize'
|
|
5
|
+
require 'rss'
|
|
6
|
+
require 'nokogiri'
|
|
7
|
+
|
|
8
|
+
class Zarchitect
|
|
9
|
+
|
|
10
|
+
HTMLDIR = "_html"
|
|
11
|
+
BUILDIR = "_build"
|
|
12
|
+
FILEDIR = "_files"
|
|
13
|
+
ASSETDIR = "_assets"
|
|
14
|
+
DRAFTDIR = "_drafts"
|
|
15
|
+
LAYOUTDIR = "_layouts"
|
|
16
|
+
CONFIGDIR = "_config"
|
|
17
|
+
|
|
18
|
+
FILESDIR = "files"
|
|
19
|
+
SHARESDIR = "share" # directory under _files that doesn't have thumbnails
|
|
20
|
+
ASSETSDIR = "assets"
|
|
21
|
+
DEBUGSDIR = "debug"
|
|
22
|
+
|
|
23
|
+
def initialize
|
|
24
|
+
@@sections = Array.new
|
|
25
|
+
GPI.app_name = "zarchitect"
|
|
26
|
+
GPI.extend(:dir)
|
|
27
|
+
GPI.extend(:file)
|
|
28
|
+
GPI.extend(:hash)
|
|
29
|
+
GPI.extend(:numeric)
|
|
30
|
+
GPI.extend(:string)
|
|
31
|
+
GPI::CLU.init
|
|
32
|
+
# Command name | range of parameter num | options
|
|
33
|
+
GPI::CLU.use_command("u", [0], "rvqdD")
|
|
34
|
+
GPI::CLU.use_command("update", [0], "rvqdD")
|
|
35
|
+
|
|
36
|
+
GPI::CLU.use_command("ua", [0], "v")
|
|
37
|
+
GPI::CLU.use_command("update-assets", [0], "v")
|
|
38
|
+
|
|
39
|
+
GPI::CLU.use_command("uf", [0], "v")
|
|
40
|
+
GPI::CLU.use_command("update-files", [0], "v")
|
|
41
|
+
GPI::CLU.use_command("setup", [0], "v")
|
|
42
|
+
|
|
43
|
+
GPI::CLU.use_command("new", 2..3, "v")
|
|
44
|
+
#app_command(0..2, "r") # appname = command.name
|
|
45
|
+
GPI::CLU.process_args
|
|
46
|
+
@@rss = ZRSS.new
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def main
|
|
50
|
+
if GPI::CLU.check_option('v')
|
|
51
|
+
GPI.print "Verbose Mode"
|
|
52
|
+
else
|
|
53
|
+
GPI.print "Non-verbose Mode"
|
|
54
|
+
end
|
|
55
|
+
# Load config
|
|
56
|
+
case GPI::CLU.command
|
|
57
|
+
when "new" # create md file for new web page
|
|
58
|
+
load_conf
|
|
59
|
+
cmd = CMD::New.new
|
|
60
|
+
cmd.run
|
|
61
|
+
when "update","u"
|
|
62
|
+
load_conf
|
|
63
|
+
cmd = CMD::Update.new
|
|
64
|
+
cmd.run
|
|
65
|
+
when "sync"
|
|
66
|
+
# draw data from mastodon / twitter api
|
|
67
|
+
when "update-assets","ua"
|
|
68
|
+
load_conf
|
|
69
|
+
CMD::Misc.update_assets
|
|
70
|
+
when "update-files","uf"
|
|
71
|
+
load_conf
|
|
72
|
+
CMD::Misc.update_files
|
|
73
|
+
when "setup"
|
|
74
|
+
CMD::Misc.setup
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def rss
|
|
79
|
+
@@rss
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def self.rebuild
|
|
85
|
+
# delete all contents of _html
|
|
86
|
+
Dir[ File.join(HTMLDIR, "**", "*") ].reverse.reject do |fullpath|
|
|
87
|
+
if File.directory?(fullpath)
|
|
88
|
+
GPI.print "deleting dir #{fullpath}"
|
|
89
|
+
Dir.delete(fullpath)
|
|
90
|
+
GPI.print "deleted dir #{fullpath}"
|
|
91
|
+
else
|
|
92
|
+
GPI.print "deleting file #{fullpath}"
|
|
93
|
+
File.delete(fullpath)
|
|
94
|
+
GPI.print "deleted file #{fullpath}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def self.setup_html_tree
|
|
100
|
+
Util.mkdir(HTMLDIR)
|
|
101
|
+
Util.mkdir(File.join(HTMLDIR, ASSETSDIR))
|
|
102
|
+
Util.mkdir(File.join(HTMLDIR, FILESDIR))
|
|
103
|
+
Util.mkdir(File.join(BUILDDIR, DEBUGSDIR)) if GPI::CLU.check_option('d')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def load_conf
|
|
107
|
+
@@zr_config = Config.new("_config/_zarchitect.yaml", "configuration")
|
|
108
|
+
@@zr_config.validate_zrconf
|
|
109
|
+
@@zr_config.setup
|
|
110
|
+
@@index_config = Config.new("_config/_index.yaml", "index")
|
|
111
|
+
@@index_config.validate
|
|
112
|
+
@@index_config.setup
|
|
113
|
+
@@sec_config = Array.new
|
|
114
|
+
Dir.files("_config").each do |f|
|
|
115
|
+
next if f[0] == "." # don't read swap files
|
|
116
|
+
next if f == "_zarchitect.yaml"
|
|
117
|
+
next if f == "_index.yaml"
|
|
118
|
+
n = f.sub(".yaml", "")
|
|
119
|
+
@@sec_config.push Config.new("_config/#{f}", n)
|
|
120
|
+
@@sec_config.last.validate
|
|
121
|
+
@@sec_config.last.setup
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def Zarchitect.conf
|
|
126
|
+
@@zr_config
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def Zarchitect.iconf
|
|
130
|
+
@@index_config
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def Zarchitect.sconf
|
|
134
|
+
@@sec_config
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def Zarchitect.add_section(conf)
|
|
138
|
+
#@@sections[conf.key] = Section.new(conf)
|
|
139
|
+
@@sections.push Section.new(conf)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def Zarchitect.sections
|
|
143
|
+
@@sections
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def Zarchitect.section(key)
|
|
147
|
+
@@sections.each do |s|
|
|
148
|
+
return s if s.key == key
|
|
149
|
+
end
|
|
150
|
+
nil
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
require 'zarchitect/assets.rb'
|
|
156
|
+
require 'zarchitect/audio.rb'
|
|
157
|
+
require 'zarchitect/category.rb'
|
|
158
|
+
require 'zarchitect/config.rb'
|
|
159
|
+
require 'zarchitect/content.rb'
|
|
160
|
+
require 'zarchitect/file_manager.rb'
|
|
161
|
+
require 'zarchitect/html.rb'
|
|
162
|
+
require 'zarchitect/htmltable.rb'
|
|
163
|
+
require 'zarchitect/image.rb'
|
|
164
|
+
require 'zarchitect/image_set.rb'
|
|
165
|
+
require 'zarchitect/index.rb'
|
|
166
|
+
require 'zarchitect/cmd_misc.rb'
|
|
167
|
+
require 'zarchitect/cmd_new.rb'
|
|
168
|
+
require 'zarchitect/cmd_update.rb'
|
|
169
|
+
require 'zarchitect/misc_file.rb'
|
|
170
|
+
require 'zarchitect/post.rb'
|
|
171
|
+
require 'zarchitect/paginator.rb'
|
|
172
|
+
require 'zarchitect/rouge_html.rb'
|
|
173
|
+
require 'zarchitect/rss.rb'
|
|
174
|
+
require 'zarchitect/scss.rb'
|
|
175
|
+
require 'zarchitect/section.rb'
|
|
176
|
+
require 'zarchitect/tag.rb'
|
|
177
|
+
require 'zarchitect/util.rb'
|
|
178
|
+
require 'zarchitect/video.rb'
|
|
179
|
+
require 'zarchitect/zerb.rb'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'gpi'
|
|
2
|
+
|
|
3
|
+
class Assets < Zarchitect
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@from = ASSETDIR
|
|
7
|
+
@to = File.join(HTMLDIR, ASSETSDIR)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def update
|
|
11
|
+
Dir[ File.join(@from, '**', '*') ].reject do |fullpath|
|
|
12
|
+
path = fullpath[(@from.length)..-1]
|
|
13
|
+
if path.include?(HTMLDIR)
|
|
14
|
+
realpath = path[1..-1]
|
|
15
|
+
else
|
|
16
|
+
realpath = File.join(@to, path)
|
|
17
|
+
Util.mkdir(realpath) if File.directory?(fullpath)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
next if File.directory?(fullpath)
|
|
21
|
+
|
|
22
|
+
if File.exist?(realpath)
|
|
23
|
+
if File.stat(fullpath).mtime > File.stat(realpath).mtime
|
|
24
|
+
copy_file(fullpath, realpath)
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
copy_file(fullpath, realpath)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def cpdirs
|
|
33
|
+
Dir[ File.join(@from, '**', '*') ].reject do |fullpath|
|
|
34
|
+
path = fullpath[(@from.length)..-1]
|
|
35
|
+
if path.include?(HTMLDIR)
|
|
36
|
+
realpath = path[1..-1]
|
|
37
|
+
else
|
|
38
|
+
realpath = File.join(@to, path)
|
|
39
|
+
Util.mkdir(realpath) if File.directory?(fullpath)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def copy_file(a, b)
|
|
46
|
+
GPI.print "Copying from #{a} to #{b}.", GPI::CLU.check_option('v')
|
|
47
|
+
File.copy(a, b)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class Audio < Zarchitect
|
|
2
|
+
attr_reader :size, :type, :url
|
|
3
|
+
|
|
4
|
+
def initialize(path)
|
|
5
|
+
@path = path
|
|
6
|
+
@url = path.clone
|
|
7
|
+
@url[0] = "/"
|
|
8
|
+
@size = File.size(path)
|
|
9
|
+
@type = "audio/" << File.extname(path)[1..-1]
|
|
10
|
+
|
|
11
|
+
if @size > Zarchitect.conf.audio_limit.to_f.mib_to_bytes
|
|
12
|
+
GPI.print "Error: File #{path} too large "\
|
|
13
|
+
"(#{@size.bytes_to_mib.to_f.round(2)}MiB)."\
|
|
14
|
+
" Allowed size: #{Zarchitect.conf.audio_limit.to_f.mb_to_mib.round(2)}"
|
|
15
|
+
GPI.quit
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.is_valid?(filename)
|
|
20
|
+
[".mp3",".ogg"].include?(File.extname(filename))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.find(k, v)
|
|
24
|
+
ObjectSpace.each_object(Audio) do |a|
|
|
25
|
+
str = a.send(k)
|
|
26
|
+
return a if str == v
|
|
27
|
+
end
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
class Category < Zarchitect
|
|
2
|
+
attr_reader :key, :name, :section, :url, :tags
|
|
3
|
+
|
|
4
|
+
def initialize(key, name, section)
|
|
5
|
+
@key = key
|
|
6
|
+
@name = name
|
|
7
|
+
@section = section
|
|
8
|
+
@url = "/#{@section.key}/#{@key}/index.html"
|
|
9
|
+
|
|
10
|
+
create_dir
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def build_html
|
|
14
|
+
if @tags
|
|
15
|
+
@tags.each do |t|
|
|
16
|
+
t.build_html
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
@index.build_html
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def write_html
|
|
23
|
+
if @tags
|
|
24
|
+
@tags.each do |t|
|
|
25
|
+
t.write_html
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
@index.write_html
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def fetch_tags
|
|
32
|
+
# after fetch_pages is implemented
|
|
33
|
+
ar = Array.new
|
|
34
|
+
posts.each do |p|
|
|
35
|
+
if p.conf.has_option?("tags")
|
|
36
|
+
p.conf.tags.each { |t| ar.push t }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
ar.sort!.uniq!
|
|
40
|
+
if ar.count == 0
|
|
41
|
+
@tags = nil
|
|
42
|
+
else
|
|
43
|
+
@tags = Array.new
|
|
44
|
+
ar.each { |v| @tags.push Tag.new(v, self) }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def posts
|
|
49
|
+
@section.posts.select { |p| p.category == self }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def setup_index
|
|
53
|
+
@index = Index.new(self)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def create_dir
|
|
59
|
+
Util.mkdir(File.join(HTMLDIR, @section.key, @key))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module CMD
|
|
2
|
+
|
|
3
|
+
class Misc < Zarchitect
|
|
4
|
+
|
|
5
|
+
def self.setup
|
|
6
|
+
Zarchitect.setup_html_tree
|
|
7
|
+
Util.mkdir(FILEDIR)
|
|
8
|
+
Util.mkdir(ASSETDIR)
|
|
9
|
+
Util.mkdir(LAYOUTDIR)
|
|
10
|
+
Util.mkdir(CONFIGDIR)
|
|
11
|
+
|
|
12
|
+
a = File.join(Util.path_to_data, "_zarchitect.yaml")
|
|
13
|
+
b = File.join(CONFIGDIR, "_zarchitect.yaml")
|
|
14
|
+
|
|
15
|
+
File.copy(File.join(Util.path_to_data, "_zarchitect.yaml"), File.join(
|
|
16
|
+
CONFIGDIR, "_zarchitect.yaml"))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.update_files
|
|
20
|
+
@files = FileManager.new
|
|
21
|
+
@files.run
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.update_assets
|
|
25
|
+
Util.mkdir(File.join(HTMLDIR, ASSETSDIR))
|
|
26
|
+
SCSS.run
|
|
27
|
+
@assets = Assets.new
|
|
28
|
+
@assets.cpdirs
|
|
29
|
+
@assets.update
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module CMD
|
|
2
|
+
|
|
3
|
+
class New < Zarchitect
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
Zarchitect.sconf.each { |s| Zarchitect.add_section(s) }
|
|
7
|
+
@section = Zarchitect.section(GPI::CLU.parameters[0])
|
|
8
|
+
if @section.nil?
|
|
9
|
+
GPI.print "Error: Section with key #{GPI::CLU.parameters[0]} does " +
|
|
10
|
+
"not exist."
|
|
11
|
+
GPI.quit
|
|
12
|
+
end
|
|
13
|
+
if GPI::CLU.parameters.size > 2
|
|
14
|
+
@category = nil
|
|
15
|
+
@category = @section.find_category(GPI::CLU.parameters[1])
|
|
16
|
+
if @category.nil?
|
|
17
|
+
GPI.print "Error: category with key #{GPI::CLU.parameters[1]} " +
|
|
18
|
+
"not found in #{@section}."
|
|
19
|
+
GPI.quit
|
|
20
|
+
end
|
|
21
|
+
@title = GPI::CLU.parameters[2]
|
|
22
|
+
@dir = File.join(@section.key, @category.key)
|
|
23
|
+
else
|
|
24
|
+
@title = GPI::CLU.parameters[1]
|
|
25
|
+
@dir = File.join(@section.key)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def run
|
|
30
|
+
@id = get_id
|
|
31
|
+
# write file
|
|
32
|
+
a = ZERB.new(File.join(Util.path_to_data, "post.md.erb"))
|
|
33
|
+
data = Hash.new
|
|
34
|
+
data["title"] = @title
|
|
35
|
+
data["date"] = Time.now
|
|
36
|
+
data["author"] = Zarchitect.conf.admin
|
|
37
|
+
data["id"] = @id
|
|
38
|
+
data["category"] = @category
|
|
39
|
+
a.handle_data(data)
|
|
40
|
+
a.prepare
|
|
41
|
+
a.render
|
|
42
|
+
str = a.output
|
|
43
|
+
@dest = File.join(@dir, "#{@id}-#{@title}.md")
|
|
44
|
+
GPI.print "Writing #{@dest}"
|
|
45
|
+
if File.exist?(@dest)
|
|
46
|
+
GPI.print "Error: File at #{@dest} already exists!"
|
|
47
|
+
GPI.quit
|
|
48
|
+
end
|
|
49
|
+
File.open(@dest, "w") { |f| f.write(str) }
|
|
50
|
+
GPI.print "Wrote #{@dest}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def get_id
|
|
56
|
+
t = Time.now.to_i
|
|
57
|
+
id = t.to_s(16).downcase
|
|
58
|
+
|
|
59
|
+
idlist = Array.new
|
|
60
|
+
Zarchitect.sections.each do |s|
|
|
61
|
+
s.all_posts.each do |p|
|
|
62
|
+
idlist.push p.conf.id if p.conf.has_option?("id")
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
i = 1
|
|
67
|
+
while idlist.include?(id) do
|
|
68
|
+
id = (t+i).to_s(16).upcase
|
|
69
|
+
i += 1
|
|
70
|
+
end
|
|
71
|
+
id
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
end
|