summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/db/pre.sql15
-rwxr-xr-xsources/db/update.sh3
-rw-r--r--sources/master/master.sql12
-rwxr-xr-xsources/wiki/classify_links.rb127
-rwxr-xr-xsources/wiki/get_links.rb81
-rw-r--r--sources/wiki/pre.sql14
-rwxr-xr-xsources/wiki/update.sh6
-rw-r--r--tagstats/.gitignore1
-rw-r--r--tagstats/Makefile10
-rw-r--r--tagstats/taginfo_unicode.cpp163
-rw-r--r--web/i18n/fr.yml2
-rw-r--r--web/lib/api.rb4
-rw-r--r--web/public/css/taginfo.css11
-rwxr-xr-xweb/taginfo.rb7
-rw-r--r--web/views/layout.erb7
-rw-r--r--web/views/test-index.erb141
-rw-r--r--web/viewsjs/test-index.js.erb53
17 files changed, 644 insertions, 13 deletions
diff --git a/sources/db/pre.sql b/sources/db/pre.sql
index 9faf613..c896758 100644
--- a/sources/db/pre.sql
+++ b/sources/db/pre.sql
@@ -27,6 +27,7 @@ CREATE TABLE keys (
cells_nodes INTEGER DEFAULT 0,
cells_ways INTEGER DEFAULT 0,
in_wiki INTEGER DEFAULT 0,
+ in_wiki_en INTEGER DEFAULT 0,
in_projects INTEGER DEFAULT 0,
characters VARCHAR,
grade CHAR DEFAULT 'u'
@@ -81,6 +82,7 @@ CREATE TABLE tags (
count_ways INTEGER DEFAULT 0,
count_relations INTEGER DEFAULT 0,
in_wiki INTEGER DEFAULT 0,
+ in_wiki_en INTEGER DEFAULT 0,
in_projects INTEGER DEFAULT 0
);
@@ -139,3 +141,16 @@ CREATE TABLE prevalent_roles (
fraction REAL
);
+DROP TABLE IF EXISTS key_characters;
+
+CREATE TABLE key_characters (
+ key TEXT,
+ num INTEGER,
+ utf8 TEXT,
+ codepoint TEXT,
+ block INTEGER,
+ category TEXT,
+ direction INTEGER,
+ name TEXT
+);
+
diff --git a/sources/db/update.sh b/sources/db/update.sh
index faa5cde..add5a29 100755
--- a/sources/db/update.sh
+++ b/sources/db/update.sh
@@ -76,6 +76,9 @@ sqlite3 $DATABASE <post_similar_keys.sql
echo "`$DATECMD` Running update_characters... "
./update_characters.rb $DIR
+#echo "`$DATECMD` Running taginfo_unicode... "
+#./taginfo_unicode $DATABASE
+
echo "`$DATECMD` Running post_grades.sql... "
sqlite3 $DATABASE <post_grades.sql
diff --git a/sources/master/master.sql b/sources/master/master.sql
index d38f6d2..a3af332 100644
--- a/sources/master/master.sql
+++ b/sources/master/master.sql
@@ -48,14 +48,16 @@ INSERT INTO master_stats SELECT * FROM db.stats
INSERT INTO db.keys (key) SELECT DISTINCT key FROM wiki.wikipages WHERE key NOT IN (SELECT key FROM db.keys);
-UPDATE db.keys SET in_wiki=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE value IS NULL);
+UPDATE db.keys SET in_wiki=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE value IS NULL);
+UPDATE db.keys SET in_wiki_en=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE value IS NULL AND lang='en');
-- ============================================================================
-- too slow, so we drop it for now
-- INSERT INTO db.tags (key, value) SELECT DISTINCT key, value FROM wiki.wikipages WHERE key || '=XX=' || value NOT IN (SELECT key || '=XX=' || value FROM db.tags);
-UPDATE db.tags SET in_wiki=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*') AND key || '=' || value IN (SELECT distinct tag FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*');
+UPDATE db.tags SET in_wiki=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*') AND key || '=' || value IN (SELECT distinct tag FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*');
+UPDATE db.tags SET in_wiki_en=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*' AND lang='en') AND key || '=' || value IN (SELECT distinct tag FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*' AND lang='en');
-- ============================================================================
@@ -68,6 +70,7 @@ CREATE TABLE top_tags (
count_ways INTEGER DEFAULT 0,
count_relations INTEGER DEFAULT 0,
in_wiki INTEGER DEFAULT 0,
+ in_wiki_en INTEGER DEFAULT 0,
in_projects INTEGER DEFAULT 0
);
@@ -82,7 +85,8 @@ UPDATE top_tags SET
count_ways = (SELECT t.count_ways FROM db.tags t WHERE t.key=skey AND t.value=svalue),
count_relations = (SELECT t.count_relations FROM db.tags t WHERE t.key=skey AND t.value=svalue);
-UPDATE top_tags SET in_wiki=1 WHERE skey || '=' || svalue IN (SELECT distinct tag FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*');
+UPDATE top_tags SET in_wiki=1 WHERE skey || '=' || svalue IN (SELECT distinct tag FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*');
+UPDATE top_tags SET in_wiki_en=1 WHERE skey || '=' || svalue IN (SELECT distinct tag FROM wiki.wikipages WHERE value IS NOT NULL AND value != '*' AND lang='en');
UPDATE top_tags SET in_projects=(SELECT num FROM projects.project_counts p WHERE p.key=skey AND p.value=svalue);
@@ -97,6 +101,7 @@ CREATE TABLE popular_keys (
users INTEGER,
wikipages INTEGER DEFAULT 0,
in_wiki INTEGER DEFAULT 0,
+ in_wiki_en INTEGER DEFAULT 0,
scale_count REAL,
scale_users REAL,
scale_wiki REAL,
@@ -112,6 +117,7 @@ INSERT INTO popular_keys (key, count, users)
UPDATE popular_keys SET wikipages = (SELECT count(*) FROM wiki.wikipages w WHERE w.key=popular_keys.key);
UPDATE popular_keys SET in_wiki=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages);
+UPDATE popular_keys SET in_wiki_en=1 WHERE key IN (SELECT distinct key FROM wiki.wikipages WHERE lang='en');
-- ============================================================================
diff --git a/sources/wiki/classify_links.rb b/sources/wiki/classify_links.rb
new file mode 100755
index 0000000..907eadc
--- /dev/null
+++ b/sources/wiki/classify_links.rb
@@ -0,0 +1,127 @@
+#!/usr/bin/env ruby
+#------------------------------------------------------------------------------
+#
+# classify_links.rb [DIR]
+#
+#------------------------------------------------------------------------------
+#
+# Read the links we got from get_links.rb, classify them, and add the to the
+# taginfo-wiki.db database.
+#
+# Classification (link_class):
+#
+# category - From a Category: page
+# how_to_map - From any "How to map" page
+# import - From any "Import" page
+# key_to_tag - From a Key to one of its Tags
+# ktr - From any Key/Tag/Relation page
+# map_features - From any "Map Features" page
+# proposed - From any "Proposed" page
+# rest - From anything else
+# same - From one language variant to another of the same Key/Tag/Relation
+# tag_to_key - From a Tag to its Key
+# template - From any "Template:" page
+# user - From any "User:" or "User talk:" page
+#
+#------------------------------------------------------------------------------
+#
+# Copyright (C) 2015 Jochen Topf <jochen@remote.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#------------------------------------------------------------------------------
+
+require 'sqlite3'
+
+dir = ARGV[0] || '.'
+
+db = SQLite3::Database.new(dir + '/taginfo-wiki.db')
+db.results_as_hash = true
+
+# Regular expression matching Key/Tag/Relation pages in all languages
+regexp_ktr = Regexp.new('^(?:(.*):)?(Key|Tag|Relation):(.*)$')
+
+db.transaction do |db|
+
+ File.open(dir + '/links.list') do |linkfile|
+ linkfile.each do |line|
+ line.chomp!
+ (from, to) = line.split("\t")
+
+ link_class = 'rest'
+
+ if from =~ /^Category:/
+ link_class = 'category'
+ end
+
+ if from =~ /^(([A-Za-z]+):)?Template(_talk)?:/
+ link_class = 'template'
+ end
+
+ if from =~ /Map_Features/i
+ link_class = 'map_features'
+ end
+
+ if from =~ /Import/i
+ link_class = 'import'
+ end
+
+ if from =~ /How_to_map_a$/
+ link_class = 'how_to_map'
+ end
+
+ if from =~ /Proposed_features/i
+ link_class = 'proposed'
+ end
+
+ if from =~ /^(([A-Za-z]+):)?User(_talk)?:/
+ link_class = 'user'
+ end
+
+ fm = from.match regexp_ktr
+ if fm
+ from_lang = fm[1]
+ from_type = fm[2]
+ from_name = fm[3]
+ end
+
+ tm = to.match regexp_ktr
+ if tm
+ to_lang = tm[1]
+ to_type = tm[2]
+ to_name = tm[3]
+ end
+
+ if fm && tm
+ if from_type == to_type && from_name == to_name
+ link_class = 'same'
+ elsif from_type == 'Tag' && to_type == 'Key' && from_name.sub(/=.*/, '') == to_name
+ link_class = 'tag_to_key'
+ elsif from_type == 'Key' && to_type == 'Tag' && to_name.sub(/=.*/, '') == from_name
+ link_class = 'key_to_tag'
+ else
+ link_class = 'ktr'
+ end
+ end
+
+ db.execute("INSERT INTO wiki_links (link_class, from_title, from_lang, from_type, from_name, to_title, to_lang, to_type, to_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ link_class,
+ from, from_lang, from_type, from_name,
+ to, to_lang, to_type, to_name
+ )
+# puts "#{link_class}\t#{from}\t#{from_lang}\t#{from_type}\t#{from_name}\t#{to}\t#{to_lang}\t#{to_type}\t#{to_name}"
+ end
+ end
+end
diff --git a/sources/wiki/get_links.rb b/sources/wiki/get_links.rb
new file mode 100755
index 0000000..19c06c8
--- /dev/null
+++ b/sources/wiki/get_links.rb
@@ -0,0 +1,81 @@
+#!/usr/bin/env ruby
+#------------------------------------------------------------------------------
+#
+# get_links.rb [DIR]
+#
+#------------------------------------------------------------------------------
+#
+# Get a list of pages linking to all Key/Tag/Relation pages from the OSM
+# wiki. This list will include links from other language versions of the
+# same Key/Tag/Relation, links from other Key/Tag/Relation pages and links
+# from all other wiki pages.
+#
+# Output is on STDOUT with the title of the page the link is from a TAB
+# character and the title of the page the link is to. The underscore (_) is
+# used where there are spaces in a title.
+#
+#------------------------------------------------------------------------------
+#
+# Copyright (C) 2015 Jochen Topf <jochen@remote.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#------------------------------------------------------------------------------
+
+require 'net/http'
+require 'uri'
+require 'json'
+require 'pp'
+
+require './lib/mediawikiapi.rb'
+
+#------------------------------------------------------------------------------
+
+def what_links_to(api, title)
+ blcontinue = nil
+ loop do
+ options = { :action => 'query', :list => 'backlinks', :bltitle => title, :bllimit => 500 }
+ if blcontinue
+ options[:blcontinue] = blcontinue
+ end
+ data = api.query(options)
+ data['query']['backlinks'].each do |bl|
+ bl['title'].gsub!(/\s/, '_')
+ puts "#{bl['title']}\t#{title}"
+ end
+ if data['query-continue']
+ blcontinue = data['query-continue']['backlinks']['blcontinue'].gsub(/\s/, '_')
+ else
+ return
+ end
+ end
+end
+
+#------------------------------------------------------------------------------
+
+dir = ARGV[0] || '.'
+
+api = MediaWikiAPI::API.new('wiki.openstreetmap.org')
+
+File.open(dir + '/tagpages.list') do |tagpages|
+ tagpages.each do |line|
+ line.chomp!
+ (type, timestamp, namespace, title) = line.split("\t")
+ what_links_to(api, title)
+ end
+end
+
+
+#-- THE END -------------------------------------------------------------------
diff --git a/sources/wiki/pre.sql b/sources/wiki/pre.sql
index 280949a..742d8f0 100644
--- a/sources/wiki/pre.sql
+++ b/sources/wiki/pre.sql
@@ -87,6 +87,20 @@ CREATE TABLE wiki_languages (
count_pages INTEGER
);
+DROP TABLE IF EXISTS wiki_links;
+
+CREATE TABLE wiki_links (
+ link_class TEXT,
+ from_title TEXT,
+ from_lang TEXT,
+ from_type TEXT,
+ from_name TEXT,
+ to_title TEXT,
+ to_lang TEXT,
+ to_type TEXT,
+ to_name TEXT
+);
+
DROP TABLE IF EXISTS invalid_page_title;
CREATE TABLE invalid_page_titles (
diff --git a/sources/wiki/update.sh b/sources/wiki/update.sh
index e922710..b8ad763 100755
--- a/sources/wiki/update.sh
+++ b/sources/wiki/update.sh
@@ -53,6 +53,12 @@ $EXEC_RUBY ./get_wiki_data.rb $DIR >$LOGFILE_WIKI_DATA
echo "`$DATECMD` Getting image info..."
$EXEC_RUBY ./get_image_info.rb $DIR >$LOGFILE_IMAGE_INFO
+#echo "`$DATECMD` Getting links to Key/Tag/Relation pages..."
+#$EXEC_RUBY ./get_links.rb $DIR >$DIR/links.list
+
+#echo "`$DATECMD` Classifying links..."
+#$EXEC_RUBY ./classify_links.rb $DIR
+
echo "`$DATECMD` Extracting words..."
$EXEC_RUBY ./extract_words.rb $DIR
diff --git a/tagstats/.gitignore b/tagstats/.gitignore
index 2d82327..a5a613a 100644
--- a/tagstats/.gitignore
+++ b/tagstats/.gitignore
@@ -1,4 +1,5 @@
similarity
+taginfo_unicode
tagstats
osmstats
taginfo-db.db
diff --git a/tagstats/Makefile b/tagstats/Makefile
index 0752b49..220ce56 100644
--- a/tagstats/Makefile
+++ b/tagstats/Makefile
@@ -40,10 +40,13 @@ LIB_EXPAT := -lexpat
LIB_PBF := -pthread -lz -lprotobuf-lite -losmpbf
LIB_GD := -lgd -lz -lm
LIB_SQLITE := -lsqlite3
+LIB_ICU := `pkg-config --libs icu-uc icu-io`
+
+CXXFLAGS_ICU := `pkg-config --cflags icu-uc icu-io`
.PHONY: all check indent install clean
-all: tagstats osmstats similarity
+all: tagstats osmstats similarity taginfo_unicode
osmstats: osmstats.cpp statistics_handler.hpp
$(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) -o $@ $< $(LDFLAGS) $(LIB_EXPAT) $(LIB_PBF) $(LIB_SQLITE)
@@ -54,6 +57,9 @@ tagstats: tagstats.cpp tagstats_handler.hpp statistics_handler.hpp string_store.
similarity: similarity.cpp sqlite.hpp
$(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_FEATURES) -o $@ $< $(LDFLAGS) $(LIB_SQLITE)
+taginfo_unicode: taginfo_unicode.cpp sqlite.hpp
+ $(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_FEATURES) $(CXXFLAGS_ICU) -o $@ $< $(LDFLAGS) $(LIB_SQLITE) $(LIB_ICU)
+
check:
cppcheck --enable=all tagstats.cpp osmstats.cpp
@@ -64,5 +70,5 @@ install:
install -m 755 tagstats ../sources/db/tagstats
clean:
- rm -f *.o *.gcno *.gcda *.gcov gmon.out core tagstats osmstats
+ rm -f *.o *.gcno *.gcda *.gcov gmon.out core tagstats osmstats similarity
diff --git a/tagstats/taginfo_unicode.cpp b/tagstats/taginfo_unicode.cpp
new file mode 100644
index 0000000..9a53f18
--- /dev/null
+++ b/tagstats/taginfo_unicode.cpp
@@ -0,0 +1,163 @@
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <vector>
+
+#include <unicode/schriter.h>
+#include <unicode/uchar.h>
+#include <unicode/unistr.h>
+
+#include "sqlite.hpp"
+
+const char* category_to_string(int8_t category) {
+ switch (category) {
+ // letters
+ case 1: return "Lu"; // uppercase letter
+ case 2: return "Ll"; // lowercase letter
+ case 3: return "Lt"; // titlecase letter
+ case 4: return "Lm"; // modifier letter
+ case 5: return "Lo"; // other letter
+ // marks
+ case 6: return "Mn"; // non-spacing mark
+ case 7: return "Me"; // enclosing mark
+ case 8: return "Mc"; // combining spacing mark
+ // numbers
+ case 9: return "Nd"; // decimal digit number
+ case 10: return "Nl"; // letter number
+ case 11: return "No"; // other number
+ // separators
+ case 12: return "Zs"; // space separator
+ case 13: return "Zl"; // line separator
+ case 14: return "Zp"; // paragraph separator
+ // control characters etc.
+ case 15: return "Cc"; // control char
+ case 16: return "Cf"; // format char
+ case 17: return "Co"; // private use char
+ case 18: return "Cs"; // surrogate
+ // punctuations
+ case 19: return "Pd"; // dash punctuation
+ case 20: return "Ps"; // start punctuation
+ case 21: return "Pe"; // end punctuation
+ case 22: return "Pc"; // connector punctuation
+ case 23: return "Po"; // other punctuation
+ // symbols
+ case 24: return "Sm"; // math symbol
+ case 25: return "Sc"; // currency symbol
+ case 26: return "Sk"; // modifier symbol
+ case 27: return "So"; // other symbol
+ // punctuations cont.
+ case 28: return "Pi"; // initial punctuation
+ case 29: return "Pf"; // final punctuation
+ default:
+ return "UNKNOWN";
+ }
+}
+
+void get_unicode_info(const char* text, const icu::UnicodeString& us, Sqlite::Statement& insert) {
+ bool allokay = true;
+ for (const char* t = text; *t; ++t) {
+ if (!(std::isalnum(*t) || *t == '_' || *t == ':' || *t == ' ' || *t == '.' || *t == '-')) {
+ allokay = false;
+ break;
+ }
+ }
+
+ if (allokay) {
+ return;
+ }
+
+ bool unusual = false;
+ for (icu::StringCharacterIterator it(us); it.hasNext(); it.next()) {
+ UChar32 codepoint = it.current32();
+ int8_t chartype = u_charType(codepoint);
+ if (! u_isprint(codepoint)) {
+ unusual = true;
+ break;
+ }
+ if (u_charDirection(codepoint) != 0) {
+ unusual = true;
+ break;
+ }
+ if (chartype != 1 && // UPPERCASE_LETTER
+ chartype != 2 && // LOWERCASE_LETTER
+ chartype != 9 && // DECIMAL_DIGIT_NUMBER
+ chartype != 12 && // SPACE_SEPARATOR
+ chartype != 19 && // DASH_PUNCTUATION
+ chartype != 22 && // CONNECTOR_PUNCTUATION
+ chartype != 23) { // OTHER_PUNCTUATION
+ unusual = true;
+ break;
+ }
+ }
+
+ if (unusual) {
+ int num = 0;
+ for (icu::StringCharacterIterator it(us); it.hasNext(); it.next(), ++num) {
+ UChar32 codepoint = it.current32();
+
+ int8_t chartype = u_charType(codepoint);
+
+ char buffer[100];
+ UErrorCode errorCode = U_ZERO_ERROR;
+ u_charName(codepoint, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
+
+ UCharDirection direction = u_charDirection(codepoint);
+ int32_t block = u_getIntPropertyValue(codepoint, UCHAR_BLOCK);
+
+ icu::UnicodeString ustr(codepoint);
+ std::string str;
+ ustr.toUTF8String(str);
+
+ char uplus[10];
+ snprintf(uplus, 10, "U+%04x", codepoint);
+
+ insert.
+ bind_text(text).
+ bind_int(num).
+ bind_text(str.c_str()).
+ bind_text(uplus).
+ bind_int(block).
+ bind_text(category_to_string(chartype)).
+ bind_int(direction).
+ bind_text(buffer).
+ execute();
+ }
+ }
+}
+
+void find_unicode_info(const char* begin, const char* end, Sqlite::Statement& insert) {
+ for (; begin != end; begin += strlen(begin) + 1) {
+ get_unicode_info(begin, icu::UnicodeString::fromUTF8(begin), insert);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ if (argc != 2) {
+ std::cerr << "taginfo_unicode DATABASE\n";
+ return 1;
+ }
+
+ std::string data;
+
+ Sqlite::Database db(argv[1], SQLITE_OPEN_READWRITE);
+ Sqlite::Statement select(db, "SELECT key FROM keys WHERE characters NOT IN ('plain', 'colon') ORDER BY key");
+ while (select.read()) {
+ data += select.get_string(0);
+ data += '\0';
+ }
+
+
+ Sqlite::Statement insert(db, "INSERT INTO key_characters (key, num, utf8, codepoint, block, category, direction, name) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+ db.begin_transaction();
+ find_unicode_info(data.c_str(), data.c_str() + data.size(), insert);
+ db.commit();
+
+ return 0;
+}
+
diff --git a/web/i18n/fr.yml b/web/i18n/fr.yml
index 48511a6..4da94a7 100644
--- a/web/i18n/fr.yml
+++ b/web/i18n/fr.yml
@@ -483,7 +483,7 @@ reports:
<p>Les clés contenant des symboles problématiques : <span
class="char">=+/&amp;&lt;&gt;;'"?%#@\,</span> ou les caractères
de contrôle. Ces caractères
- peuvent poser des problèmes, car ils sont utilisés pour délimiter les chaines de caratères dans
+ peuvent poser des problèmes, car ils sont utilisés pour délimiter les chaines de caractères dans
les langages de programmation. Ils ont une sens particulier en XML, HTML, dans les
URLs, et ailleurs aussi. Le signe égal (<span class="char">=</span>) est souvent utilisé comme séparateur
entre les clés et les valeurs des tags.<br/>
diff --git a/web/lib/api.rb b/web/lib/api.rb
index 9ad8c42..5c8cb5c 100644
--- a/web/lib/api.rb
+++ b/web/lib/api.rb
@@ -127,8 +127,8 @@ class APIParameters
if p[:rp] !~ /^[0-9]{1,3}$/
raise ArgumentError, 'results per page must be integer between 0 and 999'
end
- if p[:page] !~ /^[0-9]{1,4}$/
- raise ArgumentError, 'page must be integer between 0 and 9999'
+ if p[:page] !~ /^[0-9]{1,6}$/
+ raise ArgumentError, 'page must be integer between 0 and 999999'
end
@page = p[:page].to_i
@results_per_page = p[:rp].to_i
diff --git a/web/public/css/taginfo.css b/web/public/css/taginfo.css
index fd694e3..2cf231f 100644
--- a/web/public/css/taginfo.css
+++ b/web/public/css/taginfo.css
@@ -204,14 +204,17 @@ select#locale, select#lang {
border: none;
}
+div#header input#search {
+ height: 18px;
+ width: 228px;
+ padding: 2px;
+}
+
input#search, p.search {
background-image: url('/css/flexigrid/images/magnifier.png');
background-repeat: no-repeat;
- background-position: right 3px;
+ background-position: right center;
background-color: #ffffff;
- height: 18px;
- width: 228px;
- padding: 2px;
border: 1px solid #a0a0a0;
border-radius: 4px;
}
diff --git a/web/taginfo.rb b/web/taginfo.rb
index 7dcec2c..778602a 100755
--- a/web/taginfo.rb
+++ b/web/taginfo.rb
@@ -9,7 +9,7 @@
#
#------------------------------------------------------------------------------
#
-# Copyright (C) 2010-2014 Jochen Topf <jochen@remote.org>
+# Copyright (C) 2010-2015 Jochen Topf <jochen@remote.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -165,6 +165,11 @@ class Taginfo < Sinatra::Base
erb :index
end
+ get '/test-index' do
+ javascript "#{ r18n.locale.code }/test-index"
+ erb :'test-index'
+ end
+
#-------------------------------------
%w(about download sources).each do |page|
diff --git a/web/views/layout.erb b/web/views/layout.erb
index 6c3b98a..3320c15 100644
--- a/web/views/layout.erb
+++ b/web/views/layout.erb
@@ -8,6 +8,11 @@
<link rel="stylesheet" type="text/css" href="/css/smoothness/jquery-ui-1.8.10.custom-minified.css" />
<link rel="stylesheet" type="text/css" href="/css/flexigrid/flexigrid-minified.css" />
<link rel="search" type="application/opensearchdescription+xml" href="/search/opensearch.xml" title="<%= TaginfoConfig.get('opensearch.shortname') %>" />
+<% if @css %>
+ <style type="text/css"><!--
+<%= @css %>
+--></style>
+<% end %>
<%= javascript_tags %>
</head>
<body>
@@ -22,7 +27,9 @@
<% end %>
</select>
</form>
+<% unless @nosearch %>
<form id="search_form" action="/search"><input type="text" id="search" name="q" value="<%= h(params[:q]) %>"/></form>
+<% end %>
</div>
<div id="header_logo">
<a href="/"><img width="49" height="49" src="<%= TaginfoConfig.get('instance.icon', '/img/logo/world.png') %>" alt="taginfo"/></a>
diff --git a/web/views/test-index.erb b/web/views/test-index.erb
new file mode 100644
index 0000000..391efde
--- /dev/null
+++ b/web/views/test-index.erb
@@ -0,0 +1,141 @@
+<% @nosearch = true
+ @css = <<'CSS'
+div#menu {
+ position: relative;
+ margin: 0 auto;
+ width: 100%;
+ height: 30px;
+ border-bottom: 1px solid #a0a0a0;
+}
+
+div#menuitems {
+ position: absolute;
+ width: 100%;
+}
+
+div#menu .mitem {
+ position: relative;
+}
+
+div#menu h2 {
+ text-transform: uppercase;
+ font-weight: normal;
+ margin: 2px 40px 2px 0px;
+ height: 26px;
+ float: left;
+}
+
+div#menu h2:hover {
+ border-bottom: 3px solid #a0a0a0;
+}
+
+div#menu h2 a {
+ text-decoration: none;
+}
+
+div#menu div.mitem .mpop {
+ position: absolute;
+ visibility: hidden;
+ padding-top: 6px;
+ width: 100%;
+ height: 210px;
+ top: 31px;
+ background: -moz-linear-gradient(top, #ffffff, #f0f0f0);
+ border-radius: 4px;
+}
+
+div#menu div.mitem .mpop p {
+ padding: 8px 16px;
+ max-width: 40em;
+}
+
+div#menu div.mitem .mpop div {
+ padding: 8px 16px;
+}
+
+div#menu div.mitem:hover .mpop {
+ visibility: visible;
+}
+
+div#search_box {
+ text-align: center;
+}
+
+div#search_box p {
+ max-width: 100%;
+ font-size: 80%;
+}
+
+div#main input#search {
+ font-size: 140%;
+ padding: 2px 6px;
+}
+CSS
+%>
+<div class="resize">
+ <div id="menu"><div id="menuitems">
+ <div class="mitem"><h2><a href="/keys"><%= h(t.osm.keys) %></a></h2>
+ <div class="mpop">
+ <p>All tag keys that exist in the database or in any of the other sources.</p>
+ <div id="key_list"></div>
+ <p class="emphasis"><a href="/keys"><%= h(t.pages.index.keys.listkeys) %></a></p>
+ </div>
+ </div>
+ <div class="mitem"><h2><a href="/tags"><%= h(t.osm.tags) %></a></h2>
+ <div class="mpop">
+ <p>The most common tags in the database.</p>
+ <div id="tag_list"></div>
+ <p class="emphasis"><a href="/tags"><%= h(t.pages.index.tags.listtags) %></a></p>
+ </div>
+ </div>
+ <div class="mitem"><h2><a href="/relations"><%= h(t.osm.relation_types) %></a></h2>
+ <div class="mpop">
+ <p>The different types of relations (indicated by the type tag).</p>
+ <div id="relation_list"></div>
+ <p class="emphasis"><a href="/relations"><%= h(t.pages.index.relations.listrelations) %></a></p>
+ </div>
+ </div>
+ <div class="mitem"><h2><a href="/projects"><%= h(t.taginfo.projects) %></a></h2>
+ <div class="mpop">
+ <p>Projects that use OSM data in some way.</p>
+ <div>
+<% @db.select('SELECT id, name, icon_url FROM projects.projects').execute().each do |project| %>
+ <a href="/projects/<%= project['id'] %>"><img width="20" height="20" src="<%= project['icon_url'] %>" alt="" title="<%= project['name'] %>"/></a>
+<% end %>
+ </div>
+ <p class="emphasis"><a href="/projects">Show all projects...</a></p>
+ </div>
+ </div>
+ <div class="mitem"><h2><a href="/reports"><%= h(t.taginfo.reports) %></a></h2>
+ <div class="mpop">
+ <p>Reports show the tag data from different angles. They often
+ bring together data from several sources in interesting ways.
+ Some of the reports can help with finding specific errors.</p>
+ <div>
+ <a href="/reports/characters_in_keys">Characters in keys</a> &bull;
+ <a href="/reports/database_statistics">Database statistics</a> &bull;
+ <a href="/reports/historic_development">Historic development</a> &bull;
+ <a href="/reports/key_lengths">Key lengths</a> &bull;
+ <a href="/reports/similar_keys">Similar keys</a>
+ </div>
+ <p class="emphasis"><a href="/reports"><%= h(t.pages.index.reports.listreports) %></a></p>
+ </div>
+ </div>
+ <div class="mitem"><h2><a href="/about"><%= h(t.taginfo.about) %></a></h2>
+ <div class="mpop">
+ <p>OpenStreetMap uses tags to add meaning to geographic
+ objects. There is no fixed list of those tags. New tags can be
+ invented and used as needed. Taginfo tries to bring together
+ all information about tags to help you understand how they are
+ used and what they mean.</p>
+ <p class="emphasis"><a href="/about">More...</a></p>
+ </div>
+ </div>
+ </div></div>
+ <div style="clear: both; height: 240px;"></div>
+ <div id="search_box">
+ <form id="search_form" action="/search"><input type="text" id="search" name="q" value="<%= h(params[:q]) %>"/></form>
+ <p>Search the taginfo database.<br/>
+ Formats: KEY, KEY=VALUE, =VALUE, ...</p>
+ </div>
+</div>
diff --git a/web/viewsjs/test-index.js.erb b/web/viewsjs/test-index.js.erb
new file mode 100644
index 0000000..8920c3c
--- /dev/null
+++ b/web/viewsjs/test-index.js.erb
@@ -0,0 +1,53 @@
+<%
+# This is the maximum number of keys/tags/relations in the lists. Javascript
+# code will only show as many of them as will fit in the window.
+tagcloud_number_of_keys = 100
+tagcloud_number_of_tags = 100
+tagcloud_number_of_rels = 100
+keys = @db.select("SELECT key FROM popular_keys ORDER BY scale1 DESC LIMIT #{ tagcloud_number_of_keys }").execute()
+tags = @db.select("SELECT skey, svalue FROM top_tags WHERE skey NOT IN ('source', 'source_ref', 'attribution') ORDER BY count_all DESC LIMIT #{ tagcloud_number_of_tags }").execute()
+rels = @db.select("SELECT rtype FROM db.relation_types WHERE count >= 1000 ORDER BY count DESC LIMIT #{ tagcloud_number_of_rels }").execute()
+%>
+
+var data = {
+ 'keys': <%= keys.map{ |tag| tag['key'] }.to_json %>,
+ 'tags': <%= tags.map{ |entry| [ entry['skey'], entry['svalue'] ] }.to_json %>,
+ 'rels': <%= rels.map{ |row| row['rtype'] }.to_json %>
+};
+
+up = function() {};
+
+function create_list(element, max_height, data, decrease, func) {
+ var i = 0,
+ size = 160;
+
+ while (element.innerHeight() < max_height && data[i]) {
+ element.append(func(data[i], size));
+ element.append('<span style="font-size: ' + size + '%;"> &bull; </span>');
+ i++;
+ size -= decrease;
+ }
+
+ element.append('...');
+}
+
+function resize_home() {
+
+ create_list(jQuery('#key_list').empty(), 120, data.keys, 1, function(d, size) {
+ return link_to_key(d, { 'style': 'font-size: ' + size + "%;" });
+ });
+
+ create_list(jQuery('#tag_list').empty(), 120, data.tags, 2, function(d, size) {
+ return '<span style="font-size: ' + size + '%;"> ' + link_to_tag(d[0], d[1]) + ' </span>'
+ });
+
+ create_list(jQuery('#relation_list').empty(), 120, data.rels, 5, function(d, size) {
+ return link_to_rtype(d, { 'style': 'font-size: ' + size + "%;" });
+ });
+
+}
+
+function page_init() {
+ jQuery(window).resize(resize_home);
+ resize_home();
+}