Bläddra i källkod

chore: insight search: split file & add untitled item support

ppoffice 9 år sedan
förälder
incheckning
029442f7c4

+ 1 - 0
languages/en.yml

@@ -34,4 +34,5 @@ insight:
     pages: 'Pages'
     categories: 'Categories'
     tags: 'Tags'
+    untitled: '(Untitled)'
 

+ 1 - 0
languages/es.yml

@@ -34,3 +34,4 @@ insight:
     pages: 'Pages'
     categories: 'Categorias'
     tags: 'Etiquetas'
+    untitled: '(Untitled)'

+ 1 - 0
languages/fr.yml

@@ -33,3 +33,4 @@ insight:
     pages: 'Pages'
     categories: 'Catégories'
     tags: 'Tags'
+    untitled: '(Untitled)'

+ 1 - 0
languages/id.yml

@@ -32,3 +32,4 @@ insight:
     pages: 'Pages'
     categories: 'kategori'
     tags: 'tag'
+    untitled: '(Untitled)'

+ 1 - 0
languages/ja.yml

@@ -33,3 +33,4 @@ insight:
     pages: 'Pages'
     categories: 'カテゴリ'
     tags: 'タグ'
+    untitled: '(Untitled)'

+ 1 - 0
languages/ko.yml

@@ -34,3 +34,4 @@ insight:
     pages: 'Pages'
     categories: '카테고리'
     tags: '태그'
+    untitled: '(Untitled)'

+ 1 - 0
languages/ru.yml

@@ -34,3 +34,4 @@ insight:
     pages: 'Pages'
     categories: 'категории'
     tags: 'тэги'
+    untitled: '(Untitled)'

+ 1 - 0
languages/zh-CN.yml

@@ -34,3 +34,4 @@ insight:
     pages: '页面'
     categories: '分类'
     tags: '标签'
+    untitled: '(未命名)'

+ 1 - 0
languages/zh-TW.yml

@@ -33,3 +33,4 @@ insight:
     pages: 'Pages'
     categories: '分類'
     tags: '標籤'
+    untitled: '(Untitled)'

+ 16 - 189
layout/search/insight.ejs

@@ -11,192 +11,19 @@
     </div>
 </div>
 <script>
-    (function ($) {
-        $main = $('.ins-search');
-        $container = $('.ins-section-container');
-        $main.parent().remove('.ins-search');
-        $('body').append($main);
-
-        $(document).on('click focus', '.search-form-input', function () {
-            $main.addClass('show');
-            $main.find('.ins-search-input').focus();
-        }).on('click', '.ins-search-item', function () {
-            location.href=$(this).attr('data-url');
-        }).on('click', '.ins-close', function () {
-            $main.removeClass('show');
-        });
-
-        function section (title) {
-            return $('<section>').addClass('ins-section')
-                .append($('<header>').addClass('ins-section-header').text(title));
-        }
-
-        function searchItem (icon, title, slug, preview, url) {
-            return $('<div>').addClass('ins-selectable').addClass('ins-search-item')
-                .append($('<header>').append($('<i>').addClass('fa').addClass('fa-' + icon)).append(title)
-                    .append(slug ? $('<span>').addClass('ins-slug').text(slug) : null))
-                .append(preview ? $('<p>').addClass('ins-search-preview').text(preview) : null)
-                .attr('data-url', url);
-        }
-
-        function sectionFactory (type, array) {
-            var sectionTitle;
-            var $searchItems;
-            if (array.length == 0) return null;
-            switch (type) {
-                case 'POSTS':
-                case 'PAGES':
-                    sectionTitle = type == 'POSTS' ? '<%= __("insight.posts") %>' : '<%= __("insight.pages") %>';
-                    $searchItems = array.map(function (item) {
-                        // Use config.root instead of permalink to fix url issue
-                        return searchItem('file', item.title, null, item.text.slice(0, 150), '<%= config.root %>' + item.path);
-                    });
-                    break;
-                case 'CATEGORIES':
-                case 'TAGS':
-                    sectionTitle = type == 'CATEGORIES' ? '<%= __("insight.categories") %>' : '<%= __("insight.tags") %>';
-                    $searchItems = array.map(function (item) {
-                        return searchItem(type == 'CATEGORIES' ? 'folder' : 'tag', item.name, item.slug, null, item.permalink);
-                    });
-                    break;
-                default:
-                    return null;
-            }
-            return section(sectionTitle).append($searchItems);
-        }
-
-        function extractToSet (json, key) {
-            var values = {};
-            var entries = json.pages.concat(json.posts);
-            entries.forEach(function (entry) {
-                if (entry[key]) {
-                    entry[key].forEach(function (value) {
-                        values[value.name] = value;
-                    });
-                }
-            });
-            var result = [];
-            for (var key in values) {
-                result.push(values[key]);
-            }
-            return result;
-        }
-
-        function parseKeywords (keywords) {
-            return keywords.split(' ').filter(function (keyword) {
-                return !!keyword;
-            }).map(function (keyword) {
-                return keyword.toUpperCase();
-            });
-        }
-
-        /**
-         * Judge if a given post/page/category/tag contains all of the keywords.
-         * @param Object            obj     Object to be weighted
-         * @param Array<String>     fields  Object's fields to find matches
-         */
-        function filter (keywords, obj, fields) {
-            var result = false;
-            var keywordArray = parseKeywords(keywords);
-            var containKeywords = keywordArray.filter(function (keyword) {
-                var containFields = fields.filter(function (field) {
-                    if (!obj.hasOwnProperty(field))
-                        return false;
-                    if (obj[field].toUpperCase().indexOf(keyword) > -1)
-                        return true;
-                });
-                if (containFields.length > 0)
-                    return true;
-                return false;
-            });
-            return containKeywords.length == keywordArray.length;
-        }
-
-        function filterFactory (keywords) {
-            return {
-                POST: function (obj) {
-                    return filter(keywords, obj, ['title', 'text']);
-                },
-                PAGE: function (obj) {
-                    return filter(keywords, obj, ['title', 'text']);
-                },
-                CATEGORY: function (obj) {
-                    return filter(keywords, obj, ['name', 'slug']);
-                },
-                TAG: function (obj) {
-                    return filter(keywords, obj, ['name', 'slug']);
-                }
-            };
-        }
-
-        /**
-         * Calculate the weight of a matched post/page/category/tag.
-         * @param Object            obj     Object to be weighted
-         * @param Array<String>     fields  Object's fields to find matches
-         * @param Array<Integer>    weights Weight of every field
-         */
-        function weight (keywords, obj, fields, weights) {
-            var value = 0;
-            parseKeywords(keywords).forEach(function (keyword) {
-                var pattern = new RegExp(keyword, 'img'); // Global, Multi-line, Case-insensitive
-                fields.forEach(function (field, index) {
-                    if (obj.hasOwnProperty(field)) {
-                        var matches = obj[field].match(pattern);
-                        value += matches ? matches.length * weights[index] : 0;
-                    }
-                });
-            });
-            return value;
-        }
-
-        function weightFactory (keywords) {
-            return {
-                POST: function (obj) {
-                    return weight(keywords, obj, ['title', 'text'], [3, 1]);
-                },
-                PAGE: function (obj) {
-                    return weight(keywords, obj, ['title', 'text'], [3, 1]);
-                },
-                CATEGORY: function (obj) {
-                    return weight(keywords, obj, ['name', 'slug'], [1, 1]);
-                },
-                TAG: function (obj) {
-                    return weight(keywords, obj, ['name', 'slug'], [1, 1]);
-                }
-            };
-        }
-
-        function search (json, keywords) {
-            var WEIGHTS = weightFactory(keywords);
-            var FILTERS = filterFactory(keywords);
-            var posts = json.posts;
-            var pages = json.pages;
-            var tags = extractToSet(json, 'tags');
-            var categories = extractToSet(json, 'categories');
-            return {
-                posts: posts.filter(FILTERS.POST).sort(function (a, b) { return WEIGHTS.POST(b) - WEIGHTS.POST(a); }).slice(0, 5),
-                pages: pages.filter(FILTERS.PAGE).sort(function (a, b) { return WEIGHTS.PAGE(b) - WEIGHTS.PAGE(a); }).slice(0, 5),
-                categories: categories.filter(FILTERS.CATEGORY).sort(function (a, b) { return WEIGHTS.CATEGORY(b) - WEIGHTS.CATEGORY(a); }).slice(0, 5),
-                tags: tags.filter(FILTERS.TAG).sort(function (a, b) { return WEIGHTS.TAG(b) - WEIGHTS.TAG(a); }).slice(0, 5)
-            };
-        }
-
-        function searchResultToDOM (searchResult) {
-            $container.empty();
-            for (var key in searchResult) {
-                $container.append(sectionFactory(key.toUpperCase(), searchResult[key]));
-            }
-        }
-
-        $.getJSON('<%- url_for("/content.json")%>', function (json) {
-            if (location.hash.trim() == '#ins-search') {
-                $main.addClass('show');
-            }
-            $('.ins-search-input').on('input', function () {
-                var keywords = $(this).val();
-                searchResultToDOM(search(json, keywords));
-            });
-            $('.ins-search-input').trigger('input');
-        });
-    })(jQuery);
-</script>
+(function (window) {
+    var INSIGHT_CONFIG = {
+        TRANSLATION: {
+            POSTS: '<%= __("insight.posts") %>',
+            PAGES: '<%= __("insight.pages") %>',
+            CATEGORIES: '<%= __("insight.categories") %>',
+            TAGS: '<%= __("insight.tags") %>',
+            UNTITLED: '<%= __("insight.untitled") %>',
+        },
+        ROOT_URL: '<%= config.root %>',
+        CONTENT_URL: '<%- url_for("/content.json")%>',
+    };
+    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
+})(window);
+</script>
+<%- js('js/insight') %>

+ 2 - 0
source/css/_partial/insight.styl

@@ -40,7 +40,9 @@ $ins-full-screen
     border: none
     outline: none
     font-size: 16px
+    box-shadow: none
     font-weight: 200
+    border-radius: 0
     background: white
     line-height: 20px
     box-sizing: border-box

+ 191 - 0
source/js/insight.js

@@ -0,0 +1,191 @@
+/**
+ * Insight search plugin
+ * @author PPOffice { @link https://github.com/ppoffice }
+ */
+(function ($, CONFIG) {
+    $main = $('.ins-search');
+    $container = $('.ins-section-container');
+    $main.parent().remove('.ins-search');
+    $('body').append($main);
+
+    $(document).on('click focus', '.search-form-input', function () {
+        $main.addClass('show');
+        $main.find('.ins-search-input').focus();
+    }).on('click', '.ins-search-item', function () {
+        location.href=$(this).attr('data-url');
+    }).on('click', '.ins-close', function () {
+        $main.removeClass('show');
+    });
+
+    function section (title) {
+        return $('<section>').addClass('ins-section')
+            .append($('<header>').addClass('ins-section-header').text(title));
+    }
+
+    function searchItem (icon, title, slug, preview, url) {
+        return $('<div>').addClass('ins-selectable').addClass('ins-search-item')
+            .append($('<header>').append($('<i>').addClass('fa').addClass('fa-' + icon)).append(title != null && title != '' ? title : CONFIG.TRANSLATION['UNTITLED'])
+                .append(slug ? $('<span>').addClass('ins-slug').text(slug) : null))
+            .append(preview ? $('<p>').addClass('ins-search-preview').text(preview) : null)
+            .attr('data-url', url);
+    }
+
+    function sectionFactory (type, array) {
+        var sectionTitle;
+        var $searchItems;
+        if (array.length == 0) return null;
+        sectionTitle = CONFIG.TRANSLATION[type];
+        switch (type) {
+            case 'POSTS':
+            case 'PAGES':
+                $searchItems = array.map(function (item) {
+                    // Use config.root instead of permalink to fix url issue
+                    return searchItem('file', item.title, null, item.text.slice(0, 150), CONFIG.ROOT_URL + item.path);
+                });
+                break;
+            case 'CATEGORIES':
+            case 'TAGS':
+                $searchItems = array.map(function (item) {
+                    return searchItem(type == 'CATEGORIES' ? 'folder' : 'tag', item.name, item.slug, null, item.permalink);
+                });
+                break;
+            default:
+                return null;
+        }
+        return section(sectionTitle).append($searchItems);
+    }
+
+    function extractToSet (json, key) {
+        var values = {};
+        var entries = json.pages.concat(json.posts);
+        entries.forEach(function (entry) {
+            if (entry[key]) {
+                entry[key].forEach(function (value) {
+                    values[value.name] = value;
+                });
+            }
+        });
+        var result = [];
+        for (var key in values) {
+            result.push(values[key]);
+        }
+        return result;
+    }
+
+    function parseKeywords (keywords) {
+        return keywords.split(' ').filter(function (keyword) {
+            return !!keyword;
+        }).map(function (keyword) {
+            return keyword.toUpperCase();
+        });
+    }
+
+    /**
+     * Judge if a given post/page/category/tag contains all of the keywords.
+     * @param Object            obj     Object to be weighted
+     * @param Array<String>     fields  Object's fields to find matches
+     */
+    function filter (keywords, obj, fields) {
+        var result = false;
+        var keywordArray = parseKeywords(keywords);
+        var containKeywords = keywordArray.filter(function (keyword) {
+            var containFields = fields.filter(function (field) {
+                if (!obj.hasOwnProperty(field))
+                    return false;
+                if (obj[field].toUpperCase().indexOf(keyword) > -1)
+                    return true;
+            });
+            if (containFields.length > 0)
+                return true;
+            return false;
+        });
+        return containKeywords.length == keywordArray.length;
+    }
+
+    function filterFactory (keywords) {
+        return {
+            POST: function (obj) {
+                return filter(keywords, obj, ['title', 'text']);
+            },
+            PAGE: function (obj) {
+                return filter(keywords, obj, ['title', 'text']);
+            },
+            CATEGORY: function (obj) {
+                return filter(keywords, obj, ['name', 'slug']);
+            },
+            TAG: function (obj) {
+                return filter(keywords, obj, ['name', 'slug']);
+            }
+        };
+    }
+
+    /**
+     * Calculate the weight of a matched post/page/category/tag.
+     * @param Object            obj     Object to be weighted
+     * @param Array<String>     fields  Object's fields to find matches
+     * @param Array<Integer>    weights Weight of every field
+     */
+    function weight (keywords, obj, fields, weights) {
+        var value = 0;
+        parseKeywords(keywords).forEach(function (keyword) {
+            var pattern = new RegExp(keyword, 'img'); // Global, Multi-line, Case-insensitive
+            fields.forEach(function (field, index) {
+                if (obj.hasOwnProperty(field)) {
+                    var matches = obj[field].match(pattern);
+                    value += matches ? matches.length * weights[index] : 0;
+                }
+            });
+        });
+        return value;
+    }
+
+    function weightFactory (keywords) {
+        return {
+            POST: function (obj) {
+                return weight(keywords, obj, ['title', 'text'], [3, 1]);
+            },
+            PAGE: function (obj) {
+                return weight(keywords, obj, ['title', 'text'], [3, 1]);
+            },
+            CATEGORY: function (obj) {
+                return weight(keywords, obj, ['name', 'slug'], [1, 1]);
+            },
+            TAG: function (obj) {
+                return weight(keywords, obj, ['name', 'slug'], [1, 1]);
+            }
+        };
+    }
+
+    function search (json, keywords) {
+        var WEIGHTS = weightFactory(keywords);
+        var FILTERS = filterFactory(keywords);
+        var posts = json.posts;
+        var pages = json.pages;
+        var tags = extractToSet(json, 'tags');
+        var categories = extractToSet(json, 'categories');
+        return {
+            posts: posts.filter(FILTERS.POST).sort(function (a, b) { return WEIGHTS.POST(b) - WEIGHTS.POST(a); }).slice(0, 5),
+            pages: pages.filter(FILTERS.PAGE).sort(function (a, b) { return WEIGHTS.PAGE(b) - WEIGHTS.PAGE(a); }).slice(0, 5),
+            categories: categories.filter(FILTERS.CATEGORY).sort(function (a, b) { return WEIGHTS.CATEGORY(b) - WEIGHTS.CATEGORY(a); }).slice(0, 5),
+            tags: tags.filter(FILTERS.TAG).sort(function (a, b) { return WEIGHTS.TAG(b) - WEIGHTS.TAG(a); }).slice(0, 5)
+        };
+    }
+
+    function searchResultToDOM (searchResult) {
+        $container.empty();
+        for (var key in searchResult) {
+            $container.append(sectionFactory(key.toUpperCase(), searchResult[key]));
+        }
+    }
+
+    $.getJSON(CONFIG.CONTENT_URL, function (json) {
+        if (location.hash.trim() == '#ins-search') {
+            $main.addClass('show');
+        }
+        $('.ins-search-input').on('input', function () {
+            var keywords = $(this).val();
+            searchResultToDOM(search(json, keywords));
+        });
+        $('.ins-search-input').trigger('input');
+    });
+})(jQuery, window.INSIGHT_CONFIG);