Journey源碼分析三:模板編譯

Journey源碼分析二:總體啓動流程中提到了模板編譯,這裏詳細說下啓動流程數據庫

看下templates.Generate()源碼:ide

func Generate() error {
	compiledTemplates.Lock()
	defer compiledTemplates.Unlock()
	// 首先清除模板(主題可能已經改變了)
	compiledTemplates.m = make(map[string]*structure.Helper)
	// 編譯全部模板文件。
	err := checkThemes()
	if err != nil {
		return err
	}
	// If the dev flag is set, watch the theme directory and the plugin directoy for changes
	// TODO: It seems unclean to do the watching of the plugins in the templates package. Move this somewhere else.
	if flags.IsInDevMode {
		// Get the currently used theme path
		activeTheme, err := database.RetrieveActiveTheme()
		if err != nil {
			return err
		}
		currentThemePath := filepath.Join(filenames.ThemesFilepath, *activeTheme)
		// Create watcher
		err = watcher.Watch([]string{currentThemePath, filenames.PluginsFilepath}, map[string]func() error{".hbs": Generate, ".lua": plugins.Load})
		if err != nil {
			return err
		}
	}
	return nil
}

模板編譯主要在checkThemes()函數中:函數

func checkThemes() error {
	// Get currently set theme from database
	// 從數據庫獲取當前數據庫
	activeTheme, err := database.RetrieveActiveTheme()
	if err != nil {
		return err
	}
	currentThemePath := filepath.Join(filenames.ThemesFilepath, *activeTheme)
	err = compileTheme(currentThemePath)
	if err == nil {
		return nil
	}
	// 若是當前主題編譯失敗,則嘗試默認主題(promenade)
	err = compileTheme(filepath.Join(filenames.ThemesFilepath, "promenade"))
	if err == nil {
		// Update the theme name in the database
		err = methods.UpdateActiveTheme("promenade", 1)
		if err != nil {
			return err
		}
		return nil
	}
	// 若是默認主題也編譯失敗,則遍歷全部可用的主題,選取第一個可用的。
	allThemes := GetAllThemes()
	for _, theme := range allThemes {
		err = compileTheme(filepath.Join(filenames.ThemesFilepath, theme))
		if err == nil {
			// Update the theme name in the database
			err = methods.UpdateActiveTheme(theme, 1)
			if err != nil {
				return err
			}
			return nil
		}
	}
	return errors.New("Couldn't find a theme to use in " + filenames.ThemesFilepath)
}

看下compileTheme(currentThemePath)源碼:源碼分析

func compileTheme(themePath string) error {
	// 檢查主題目錄是否存在
	if _, err := os.Stat(themePath); os.IsNotExist(err) {
		return errors.New("Couldn't find theme files in " + themePath + ": " + err.Error())
	}
	err := filepath.Walk(themePath, inspectTemplateFile)
	if err != nil {
		return err
	}
	// Check if index and post templates are compiled
	if _, ok := compiledTemplates.m["index"]; !ok {
		return errors.New("Couldn't compile template 'index'. Is index.hbs missing?")
	}
	if _, ok := compiledTemplates.m["post"]; !ok {
		return errors.New("Couldn't compile template 'post'. Is post.hbs missing?")
	}
	// Check if pagination and navigation templates have been provided by the theme.
	// If not, use the build in ones.
	if _, ok := compiledTemplates.m["pagination"]; !ok {
		err = compileFile(filepath.Join(filenames.HbsFilepath, "pagination.hbs"))
		if err != nil {
			log.Println("Warning: Couldn't compile pagination template.")
		}
	}
	if _, ok := compiledTemplates.m["navigation"]; !ok {
		err = compileFile(filepath.Join(filenames.HbsFilepath, "navigation.hbs"))
		if err != nil {
			log.Println("Warning: Couldn't compile navigation template.")
		}
	
	}
	return nil
}

上面代碼的核心代碼是err := filepath.Walk(themePath, inspectTemplateFile),該方法遍歷主題目錄中的文件,並調用inspectTemplateFile()函數,看下inspectTemplateFile()的源碼:post

func inspectTemplateFile(filePath string, info os.FileInfo, err error) error {
	if !info.IsDir() && filepath.Ext(filePath) == ".hbs" {
		err := compileFile(filePath)
		if err != nil {
			return err
		}
	}
	return nil
}

若是filePath是文件而且以.hbs結尾則編譯它。看下compileFile(filePath)源碼:ui

func compileFile(fileName string) error {
	// 編譯模板文件
	helper, err := createTemplateFromFile(fileName)
	if err != nil {
		return err
	}
	// 將模板放入到全局變量compiledTemplates.m中去。
	compiledTemplates.m[helper.Name] = helper
	return nil
}

看下createTemplateFromFile(fileName)源碼:this

func createTemplateFromFile(filename string) (*structure.Helper, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	fileNameWithoutExtension := helpers.GetFilenameWithoutExtension(filename)
	// 若是同名的模板已經存在compiledTemplates.m字典中則報錯。
	if compiledTemplates.m[fileNameWithoutExtension] != nil {
		return nil, errors.New("Error: Conflicting .hbs name '" + fileNameWithoutExtension + "'. A theme file of the same name already exists.")
	}
	helper := compileTemplate(data, fileNameWithoutExtension)
	return helper, nil
}

該函數主要是讀取模板文件,而後調用compileTemplate(data, fileNameWithoutExtension)作最終編譯。lua

模板編譯方面更細節的東西我就沒什麼興趣了,你們有興趣能夠本身研究下,歡迎交流^_^code

相關文章
相關標籤/搜索