Skip to content

ARCHIVED

!注意“归档”

This chapter has not been updated for the current version of Orchard, and has been ARCHIVED.

Context

上下文

Many applications owe their success in part to the availability of a large number of themes, which is in turn due to the simplicity of building new themes. An MVC type of framework where the view to use can be dynamically determined instead of being mapped 1:1 from url to file system like in WebForms certainly helps building a theming engine.

许多应用程序的成功部分归功于大量主题的可用性,而这主要是由于构建新主题的简单性。一种MVC类型的框架,其中可以动态确定要使用的视图,而不是像在WebForms中那样从url以1:1方式映射到文件系统,这当然有助于构建主题引擎。

Audience

听众

The audiences for this feature are:

此功能的受众群体是:

  • Application administrators and users: users with little to no technical skills. These users will typically upload a theme to their application or choose one of the pre-installed ones, configure it and use it.

  • 应用程序管理员和用户:几乎没有技术技能的用户。这些用户通常会将主题上传到他们的应用程序,或者选择一个预安装的主题,配置并使用它。 *

  • Designers: users with little to no knowledge of programming concepts but with design, CSS and HTML skills. Might create a new theme by modifying an existing one.

  • 设计师:对编程概念知之甚少但具有设计,CSS和HTML技能的用户。可以通过修改现有主题来创建新主题。 *

Goals

目标

  • Simplicity of the theme model, enabling the designer audience to create themes.

  • 主题模型的简单性,使设计师观众能够创建主题。 *

  • Enable theme development using notepad and an FTP client.

  • 使用记事本和FTP客户端启用主题开发。 *

  • Enable users to change themes on the fly.

  • 使用户能够动态更改主题。 *

  • Enable users to easily discover and install new themes.

  • 使用户能够轻松发现和安装新主题。 *

  • Enable users to customize the look of their site without having writing rights to the site file system.

  • 使用户无需具有站点文件系统的写入权限即可自定义其站点的外观。 *

Scenarios

方案

Installation

安装

The installation experience for a theme must be extremely simple.

主题的安装体验必须非常简单。

It should be possible to choose a theme from our online repository and just add it to the site. In that scenario, the user goes to the themes section of the admin tool, clicks "Search for themes online", navigates through categories or does a text search in the catalog. He then chooses a theme, clicks "install". The theme is then downloaded and installed. The user may then configure, preview and use the theme.

应该可以从我们的在线存储库中选择一个主题,然后将其添加到网站中。在该场景中,用户转到管理工具的主题部分,单击“在线搜索主题”,浏览类别或在目录中进行文本搜索。然后他选择一个主题,点击“安装”。然后下载并安装主题。然后,用户可以配置,预览和使用主题。

Ideally, the online repository of themes and the installed list of themes are one and the same (with the ability to filter by installed or online).

理想情况下,主题的在线存储库和已安装的主题列表是同一个(具有按安装或在线过滤的功能)。

In another scenario, the user unzips the theme on his local hard drive and uploads its contents to the server using FTP.

在另一种情况下,用户在其本地硬盘驱动器上解压缩主题,并使用FTP将其内容上载到服务器。

In another scenario, the user connects to his dedicated server using Terminal Services, copies the zip into the server's file system, directly under the application's themes folder and unzips the theme. Once this is done, the theme can be configured from the admin UI. The zip file can remain in the themes directory.

在另一种情况下,用户使用终端服务连接到他的专用服务器,将zip复制到服务器的文件系统,直接在应用程序的主题文件夹下并解压缩主题。完成此操作后,可以从管理UI配置主题。 zip文件可以保留在themes目录中。

In another scenario, the user uploads the zipped theme through the admin UI. The application then unzips and installs it.

在另一种情况下,用户通过管理UI上传压缩主题。然后应用程序解压缩并安装它。

Switching between themes

在主题之间切换

A user wants to switch from the current theme to one of the other themes installed on the box. He goes to the themes section of the admin UI, browses the list of installed themes (including thumbnail previews), chooses the new theme he wants. The admin UI shows an overlay that shows a live preview of the theme with the actual user's data, providing a faithful glimpse at what the site will look like with this theme. He can even navigate within that preview to check other pages look OK with the new theme. Once he has decided whether the new theme should be applied, he can revert the changes (which never affected other users of the site) or apply the changes for other users to enjoy.

用户想要从当前主题切换到该框上安装的其他主题之一。他进入管理界面的主题部分,浏览已安装主题的列表(包括缩略图预览),选择他想要的新主题。管理员界面显示了一个叠加层,其中显示了主题的实时预览以及实际用户的数据,可以让您忠实地了解该主题的网站外观。他甚至可以在该预览中导航,以检查其他页面在新主题中是否正常。一旦他决定是否应该应用新主题,他就可以恢复更改(从不影响网站的其他用户)或将更改应用于其他用户以享受。

Configuration

组态

A user adds a new theme to his site. He goes to the admin tool, goes to the themes section and chooses the new theme. He is then taken to the theme's admin applet where he chooses a different color palette that fits his company's design guidelines. He also uploads a new logo that replaces the default logo that came with the theme.

用户向其网站添加新主题。他转到管理工具,转到主题部分并选择新主题。然后他被带到主题的管理小程序,在那里他选择了一个符合他公司设计指南的不同调色板。他还上传了一个新徽标,取代了主题附带的默认徽标。

Theme Creation

主题创作

A user downloads an existing two-column theme. He opens its files in a text editor and modifies them by adding a third sidebar and tweaking the CSS to give it a completely new look. He tests the theme locally and checks everything works. He then packages the theme files into a zip file and uploads it to the Orchard theme repository.

用户下载现有的两列主题。他在文本编辑器中打开文件,并通过添加第三个侧边栏并调整CSS来修改它们,使其焕然一新。他在本地测试主题并检查一切是否有效。然后,他将主题文件打包成zip文件,并将其上传到Orchard主题库。

Uninstallation

卸载

A user decides not to use the "pretty in pink" theme anymore and wants it out of the system. He goes into the admin tool, selects the theme and clicks "uninstall". After confirming the operation, the theme is removed from the system. If the site was configured to still use that theme, it automatically reverts to the default theme (which can't be uninstalled).

用户决定不再使用“漂亮的粉红色”主题,并希望将其从系统中删除。他进入管理工具,选择主题并单击“卸载”。确认操作后,主题将从系统中删除。如果站点配置为仍使用该主题,则会自动恢复为默认主题(无法卸载)。

Local themes

本地主题

In some cases such as when the site contains several blogs, it will be desirable to apply different themes to different parts of the site.

在某些情况下,例如当网站包含多个博客时,最好将不同的主题应用于网站的不同部分。

To enable this scenario, we will provide the extensibility points for the theme to be determined dynamically, and will make the "apply theme" UI re-usable.

为了启用此方案,我们将为动态确定的主题提供可扩展性点,并使“应用主题”UI可重用。

Choices

选择

There are a number of choices a theme engine has to make that are impacting both its simplicity and its power.

主题引擎必须做出许多选择,这会影响其简单性和强大功能。

Should themes define a hierarchy and should there be a fallback from a theme to its parent when a file is absent?

主题是否应该定义层次结构,并且当文件不存在时,是否应该从主题回退到其父级?

Creating a fallback mechanism between themes enables theme authors to create derived themes that contain only the difference with the parent. For example, a theme might contain only a stylesheet.

在主题之间创建回退机制使主题作者能够创建仅包含与父对象的差异的派生主题。例如,主题可能只包含样式表。

On the other hand, the penalty of copying all files is relatively low and it removes the kind of confusion where it's difficult to understand in which file to look when something goes wrong or when one wants to modify something that is not part of the theme but that can only be found in one of the parents.

另一方面,复制所有文件的代价相对较低,它消除了一种混淆,即当出现问题或者想要修改不属于主题的内容时,难以理解哪个文件要查看这只能在父母中找到。

This also greatly simplifies both the theme engine and the development of the actual themes as dependencies of the theme can be referenced directly, without the need to dynamically resolve them relatively to anything but the current view itself.

这也极大地简化了主题引擎和实际主题的开发,因为主题的依赖关系可以直接引用,而不需要相对于当前视图本身的任何内容动态地解析它们。

Without fallback, themes are self-contained and can be copied around without having to also copy parent themes with them. It is also avoiding the issue where the parent theme is uninstalled and its descendants stop working or change behavior.

没有后备,主题是自包含的,可以复制,而不必复制父主题。它还避免了卸载父主题及其后代停止工作或更改行为的问题。

In summary, the added complexity and potential confusion that cross-theme fallback introduces does not seem to be justified by the marginal benefit it brings. Without fallback, all the views and their dependencies that might be used to display any data will always be found within the current theme's directory.

总之,跨主题回退引入的额外复杂性和潜在混淆似乎并不能通过它带来的边际收益来证明。如果没有回退,则可以在当前主题的目录中找到可能用于显示任何数据的所有视图及其依赖项。

An intermediate solution is to have one minimalist default theme that must always be present and have this be the only fallback mechanism that works across themes. This enables a theme author to only override the stylesheet for example without having to copy all files, and it avoids the issues associated with deleting the parent theme for example.

一个中间解决方案是拥有一个必须始终存在的极简主义默认主题,并使其成为跨主题的唯一回退机制。这使得主题作者只能覆盖样式表而不必复制所有文件,并且例如避免了与删除父主题相关的问题。

Having a default or system theme also makes it easier to add or remove theming from an application. One could consider that the default theme is the application itself and that themes are just a way to override parts or all of the default rendering of the application. This plays very well with the architecture of view engines in ASP.NET MVC.

拥有默认或系统主题也可以更轻松地从应用程序添加或删除主题。可以认为默认主题是应用程序本身,主题只是覆盖应用程序的部分或全部默认呈现的一种方式。这与ASP.NET MVC中的视图引擎的体系结构非常相似。

The theme engine will be developed as a package that could be de-activated or uninstalled. When that is the case, the application would revert to the "safe mode"'s default views.

主题引擎将作为可以取消激活或卸载的包开发。在这种情况下,应用程序将恢复为“安全模式”的默认视图。

Should themes handle multiple content types?

主题应该处理多种内容类型吗?

Having themes that can be applied to any content type seems quite compelling. Still, on first analysis, themes that are too general might be too much of a constraint and might impair the ability of each application to provide an experience that is unique and well adapted to the problem it's addressing.

拥有可应用于任何内容类型的主题似乎非常引人注目。尽管如此,在第一次分析时,过于笼统的主题可能过于严格,可能会削弱每个应用程序提供独特且适应其所解决问题的体验的能力。

The approach of having a fallback within the themes from the most specific view to more generic views allows for both specialized and generic themes.

从最具体的视图到更通用的视图在主题中回退的方法允许专门和通用主题。

In Orchard, the same thing opens the door for even a theme that is specialized for e-commerce, for example, to be used with a blogging content-type unmodified, or to be modified to adapt to another type of contents. A theme could also have specialized views available for more than one content type.

在Orchard,同样的事情为即使是专门用于电子商务的主题打开了大门,例如,用于未经修改的博客内容类型,或者被修改以适应其他类型的内容。主题还可以具有针对多种内容类型的专用视图。

The separation of layout templates from specialized partial views is also a way to make it easier to obtain more universal themes.

将布局模板与专用局部视图分离也是一种使获取更多通用主题更容易的方法。

The default theme should include very basic and semantic markup, with a stylesheet that is easy to modify and override. Packages will typically add new partial views to that default theme, and those should have the same semantic qualities so that themes can get good results even if they only override CSS and have no knowledge of the installed packages. Most themes will do most of their work through CSS, but the theme author or the site administrator should be able to get into the theme and add specialized overrides for any view, including the ones that are added by packages.

默认主题应包括非常基本和语义标记,其样式表易于修改和覆盖。包通常会为该默认主题添加新的部分视图,并且这些视图应具有相同的语义质量,这样即使主题只覆盖CSS并且不了解已安装的包,主题也可以获得良好的结果。大多数主题将通过CSS完成大部分工作,但主题作者或网站管理员应该能够进入主题并为任何视图添加专门的覆盖,包括由包添加的视图。

Should themes be customizable from the admin tool?

主题是否可以从管理工具中自定义?

It is debatable on first analysis whether themes should expose any sort of configuration as they can easily be modified using simple text editors. On closer look, when one considers the end user's point of view as well as multi-tenant scenarios, the ability for themes to expose settings such as a logo or a color palette becomes much more important.

在第一次分析时,主题是否应公开任何类型的配置是有争议的,因为它们可以使用简单的文本编辑器轻松修改。仔细观察,当考虑最终用户的观点以及多租户场景时,主题暴露徽标或调色板等设置的能力变得更加重要。

When a user just installed an e-commerce package, for example, the first thing he will want to do, before even starting to populate the product catalog, will be to brand the application with his logo and colors. If the experience to do that is to go into a code editor, we probably already failed him.

例如,当用户刚刚安装了电子商务软件包时,在开始填充产品目录之前,他要做的第一件事就是用他的徽标和颜色来标记应用程序。如果要做到这一点的经验是进入代码编辑器,我们可能已经失败了。

In multi-tenant scenarios (which we don't explicitly support as a goal today but want to keep in our sights for the relatively near future), the user won't have access to any modifications of the site's physical files. One solution that is adopted by many applications is to expose "CSS overrides" which are a secondary, database-bound CSS stylesheet that the application can add to the theme's default CSS at runtime. This clearly works and we will support it, but exposing the most common settings directly in the admin with an adapted UI would be friendlier.

在多租户场景中(我们今天没有明确支持作为目标,但希望在不久的将来保持我们的目标),用户将无法访问站点物理文件的任何修改。许多应用程序采用的一种解决方案是公开“CSS覆盖”,这是一个辅助的,数据库绑定的CSS样式表,应用程序可以在运行时将其添加到主题的默认CSS中。这显然有效,我们将支持它,但直接在管理员中使用适合的UI公开最常见的设置会更友好。

Should themes use master pages?

主题应该使用母版吗?

Master pages are a great feature of ASP.NET but also one that is virtually unseen on other platforms that seem content with a simpler include mechanism.

母版页是ASP.NET的一个很好的特性,但也是在其他平台上几乎看不到的,它们似乎满足于更简单的包含机制。

They constitute an inversion of the concept of an include or user control: it's the contents that "include" the master instead of the more familiar case where the main files includes the contents.

它们构成了包含或用户控制概念的反转:它是“包含”主人的内容,而不是主要文件包含内容的更熟悉的情况。

This inversion works really well once it's understood and removes some repetition but it definitely is a concept that can be hard to grasp, especially for non-developers. Theme development will precisely be done by designers that are not necessarily familiar with such concepts. In the context of themes, master pages don't seem to bring enough value to justify introducing the new concept.

一旦它被理解并且消除了一些重复,这种反演就非常有效,但它肯定是一个难以掌握的概念,特别是对于非开发人员而言。主题开发将由不一定熟悉这些概念的设计者精确完成。在主题的背景下,母版似乎没有带来足够的价值来证明引入新概念的合理性。

Some themes might very well use master pages, but the default ones that we ship should probably avoid them.

一些主题可能很好地使用母版页,但我们发布的默认版本应该可以避免使用它们。

Should themes contain code files?

主题应该包含代码文件吗?

A code file may be the place where theme authors can write reusable helpers that are specific to the theme. This is also where themes could define specialized plug-ins and widgets. One example of a theme-specific plugin might be specific view resolution logic.

代码文件可以是主题作者可以编写特定于主题的可重用助手的位置。这也是主题可以定义专用插件和小部件的地方。特定于主题的插件的一个示例可以是特定的视图分辨率逻辑。

While not strictly necessary, it is an interesting addition, similar to an app_code local to the theme. On the other hand, having code in a theme goes against separation of concerns as the theme should be specialized purely in customizing the rendering. The view resolution scenario for example could be handled by having the theme depend on a package that contains the view resolution plug-in.

虽然不是绝对必要,但它是一个有趣的补充,类似于主题的本地app_code。另一方面,在主题中使用代码会违背关注点的分离,因为主题应该专门用于自定义渲染。例如,可以通过使主题依赖于包含视图解析插件的包来处理视图解析方案。

This might also be the place to define the theme's configuration settings as properties, but this scenario can also be handled through a YAML description similar to the ones we use for meta-data.

这也可能是将主题的配置设置定义为属性的位置,但也可以通过类似于我们用于元数据的YAML描述来处理此场景。

If a theme introduces a setting that has a specific editor, it could make sense to deploy the code for the editor with the theme, although it could also be argued that that editor, to be reusable by other themes, should be separated into a package rather than deployed with the theme.

如果一个主题引入了一个具有特定编辑器的设置,那么为主题编辑器部署代码是有意义的,尽管也可以认为该编辑器可以被其他主题重用,应该分成一个包而不是与主题一起部署。

In the absence of a compelling scenario that couldn't be handled in another way, we won't allow for code files in themes for now.

如果没有令人信服的场景无法以其他方式处理,我们暂时不会允许主题中的代码文件。

Where and how should meta-data be defined?

应该在何处以及如何定义元数据?

The way we define meta-data for themes should preferably be consistent with the way we define it for packages, i.e. a YAML file at the root of the theme. This will make it easy for the application to reflect on the theme to display the meta-data.

我们为主题定义元数据的方式应该最好与我们为包定义它的方式一致,即主题根目录的YAML文件。这将使应用程序能够轻松地反映主题以显示元数据。

Feature description

功能描述

Sample themes

示例主题

We will design several themes that will be delivered with the application.

我们将设计几个将随应用程序一起提供的主题。

One of these themes will be designed to exercise all the features of the theme engine, including overrides for specific display templates and widgets.

其中一个主题将用于练习主题引擎的所有功能,包括特定显示模板和小部件的覆盖。

Another theme will be designed to be a minimal theme, consisting simply of a manifest and a stylesheet (and associated images).

另一个主题将被设计为最小主题,仅包含清单和样式表(以及相关图像)。

Templates

模板

The list of templates that we will deliver initially is:

我们最初将提供的模板列表是:

  • One-column: a header, a large content zone and a footer

  • 单列:标题,大内容区域和页脚 *

  • Two-column: a header, a sidebar (positioned on the left in safe mode templates), a large content zone and a footer.

  • 双列:标题,侧边栏(位于安全模式模板的左侧),大内容区域和页脚。 *

  • Three-column: a header, a left sidebar, a large central content zone, a right sidebar and a footer.

  • 三列:标题,左侧边栏,大型中央内容区域,右侧边栏和页脚。 *

Those templates, in the safe mode default rendering, must have minimal markup.

在安全模式默认渲染中,这些模板必须具有最小标记。

Packaging

打包

A theme is essentially a collection of files. In order to make the creation and deployment of themes as easy as possible, they should be packaged using the most common packaging format: zip. Packaging a theme should be as simple as right-clicking the folder and choosing "compress".

主题本质上是文件的集合。为了使主题的创建和部署尽可能简单,应使用最常见的包装格式打包:zip。打包主题应该像右键单击文件夹并选择“压缩”一样简单。

While Virtual Path Providers in theory would enable us to serve the contents inside the zip without physically unpacking it, this won't work in medium trust with .NET 3.5 SP1. This is fixed in 4.0 but we decided we would run on 3.5 SP1 to help adoption.

虽然虚拟路径提供程序理论上可以让我们在没有物理解包的情况下提供zip中的内容,但这对于.NET 3.5 SP1的中等信任是行不通的。这已在4.0中修复,但我们决定在3.5 SP1上运行以帮助采用。

An alternative option is to unzip the package when it is uploaded, which can be done in medium trust and might be less confusing to users.

另一种选择是在上传包时解压缩包,这可以在中等信任中完成,并且可以减少用户的混淆。

The zip file containing a theme contains at its root a single folder named like the theme that contains the theme files.

包含主题的zip文件在其根目录中包含一个名为包含主题文件的主题的文件夹。

The name of the zip itself can include version information but the root folder inside it should not: Skyblue-1.0.1.zip/skyblue/.

zip本身的名称可以包含版本信息,但其中的根文件夹不应该:Skyblue-1.0.1.zip/skyblue/。

What we should focus on is that a single entity such as a theme is kept entirely in a single location so that it can be easily found, modified or deleted.

我们应该关注的是,诸如主题之类的单个实体完全保存在一个位置,以便可以轻松找到,修改或删除它。

Structure

结构体

The contents of a theme are images, stylesheets, pages, user controls and code. The files a theme can contain are:

主题的内容是图像,样式表,页面,用户控件和代码。主题可以包含的文件是:

  • Theme.txt: the manifest of the theme, where the meta-data for the theme is defined. If the manifest file is missing from a theme or if it can't be read, the admin UI will display the theme disabled (this is debatable) with a warning message explaining the problem: "This theme is missing a valid Theme.txt manifest file."

  • Theme.txt:主题的清单,其中定义了主题的元数据。如果主题中缺少清单文件或者无法读取清单文件,则管理UI将显示禁用的主题(这是有争议的),并显示解释问题的警告消息:“此主题缺少有效的Theme.txt清单文件。” *

  • Theme.png: the thumbnail that will appear in the theme galleries. This thumbnail should be relatively high resolution to enable JavaScript enhancements in the admin UI to show the higher resolution on hover. The high resolution thumbnail will be resized by the style of the img tag to a standard width when displayed in the list of themes.

  • Theme.png:将出现在主题库中的缩略图。此缩略图应具有相对较高的分辨率,以便在管理界面中启用JavaScript增强功能,以便在悬停时显示更高的分辨率。当在主题列表中显示时,高分辨率缩略图将通过img标签的样式调整为标准宽度。 *

  • Site.css: this is where most of the styles for the theme are defined. To enable settings to be inserted dynamically, a theme might have a dynamic style section in the master page or the template pages, in addition to the static link to the stylesheet.

  • Site.css:这是定义主题的大部分样式的地方。要启用动态插入设置,除了到样式表的静态链接外,主题页面或模板页面中的主题可能还有动态样式部分。 *

  • Views/Templates/Default.aspx: this is the default layout template. It typically contains a main zone where the application will insert a partial view depending on the nature of the contents being displayed (list of posts or details of a post for the home page of a blog, details of a product, etc.).

  • views / Templates / Default.aspx:这是默认的布局模板。它通常包含一个主区域,应用程序将根据所显示内容的性质(博客主页的帖子列表或详细信息,产品详细信息等)插入部分视图。 *

  • Images: a directory containing the images used by the theme.

  • Images:包含主题使用的图像的目录。 *

  • Scripts: a directory containing the client scripts used by the theme.

  • Scripts:包含主题使用的客户端脚本的目录。 *

Other, more specialized views and partial views may be optionally included into a theme, following a naming convention as described in the next section.

根据命名约定,可以选择将其他更专业的视图和部分视图包含在主题中,如下一节所述。

A typical organization for the templates in a package, and the corresponding organization for theme overrides of the templates of the same package could look like this:

包中模板的典型组织,以及相同包的模板的主题覆盖的相应组织可能如下所示:

  • Views

  • 查看 *

    • Admin

      • Blog

        • DisplayTemplates

        • EditorTemplates

      • BlogPost

        • DisplayTemplates

        • EditorTemplates

    • Blog

      • DisplayTemplates

      • EditorTemplates

    • BlogPost

      • DisplayTemplates

      • EditorTemplates

Optionally, a theme may also be localizable. For that purpose, it may contain a resources directory following the same resource definition convention as the rest of the site (TBD).

可选地,主题也可以是可本地化的。为此,它可以包含遵循与站点其余部分(TBD)相同的资源定义约定的资源目录。

If a folder in the theme folder starts with a non-alphanumerical character, it is not seen as a theme.

如果主题文件夹中的文件夹以非字母数字字符开头,则不会将其视为主题。

The theme directory by default is called "themes" and is at the root of the application. A site-level setting could enable users to relocate that folder, if they want for example to shorten file paths.

默认情况下,主题目录称为“主题”,位于应用程序的根目录下。站点级设置可以使用户重新定位该文件夹,如果他们想要缩短文件路径。

View selection

查看选择

Note

!注意

This section is speculative and depends on future decisions on the extensibility model of the application.

The selection of the most specialized view is done dynamically and is delegated to a plug-in. A default plug-in is provided by the Orchard framework but that can be overridden or completed by plug-ins.

选择最专业的视图是动态完成的,并委托给插件。默认插件由Orchard框架提供,但可以通过插件覆盖或完成。

The plug-in has the following signature:

该插件具有以下签名:

string ResolveView(

     string viewName, Theme theme, ControllerContext context)

A view resolution plug-in should return null if it can't find a relevant view. If no plug-in exists or if all returned null, the framework will use default.aspx or default.ascx (depending on whether a full or partial view is necessary in the calling context). As soon as any enabled plug-in returns something other than null, empty string or "default", the framework stops the call loop and uses that value as the name of the physical view to use. This implies that the order in which plug-ins run may be important. This order can be determined from the plug-in admin UI.

如果视图解析插件找不到相关视图,则应返回null。如果没有插件或者全部返回null,框架将使用default.aspxdefault.ascx(取决于在调用上下文中是否需要完整或部分视图)。只要任何已启用的插件返回null,空字符串或“default”以外的其他内容,框架就会停止调用循环并将该值用作要使用的物理视图的名称。这意味着插件运行的顺序可能很重要。可以从插件管理UI确定此顺序。

The view name that is getting passed into the plug-in is typically just what the controller action asked for. The plug-in system allows for arbitrary flexibility in selecting a physical view from what the action is asking for, depending on any convention and keeping the end result within what the current theme is able to display.

传递到插件的视图名称通常就是控制器操作所要求的。插件系统允许根据动作要求选择物理视图的任意灵活性,具体取决于任何约定并将最终结果保持在当前主题能够显示的范围内。

The default view selection plug-in will try to find a view with <viewName>.aspx as the name within the theme and return this if it is found. If not, it will assume that the view name is built using the following convention: viewName = [ContentType]-[ItemSlug]

默认视图选择插件将尝试查找带有“ .aspx”的视图作为主题中的名称,如果找到则返回此视图。如果没有,它将假定使用以下约定构建视图名称:viewName = [ContentType] - [ItemSlug]

The default view resolver will split the file name on the first dash character, will remove what comes after and try to find a physical view with that name.

默认视图解析器将在第一个短划线字符上拆分文件名,将删除后面的内容并尝试查找具有该名称的物理视图。

Here's a possible implementation of the default view resolution plug-in:

以下是默认视图解析插件的可能实现:

public string ResolveView(

    string viewName, Theme theme, ControllerContext context) {



    // look for the specific view in the theme.

    if (theme.HasView(viewName)) {

        return viewName;

    }

    else {

        // fallback to generic view in the theme.

        viewName = GetGenericView(viewName);

        if (viewName != null && theme.HasView(viewName)){

                return viewName;

            }

        }

        // fallback to default view.

        return null;

    }

}



private static string GetGenericView(string viewName) {

    if (String.IsNullOrEmpty(viewName)) {

        return null;

    }

    int index = viewName.IndexOf("-");

    if (index == -1)

        return null;

    return viewName.Substring(0, index);

}

Of course, implementing any other convention to resolve the controller action-provided view name to a physical view name is just a matter of implementing a plug-in.

当然,实现任何其他约定来将控制器操作提供的视图名称解析为物理视图名称只是实现插件的问题。

In the example of displaying a blog post, one can see that the controller would ask for a view named for example post-my-first-post. The default view resolver would ask the current theme for a view named post-my-first-post. If it doesn't find it (which is quite likely), it will look for a view named post. If the current theme has been built for the blog application, it will most likely have it and that's what will be used, otherwise the engine will ask other plug-ins and ultimately fall back to default.

在显示博客文章的示例中,可以看到控制器将要求以例如“post-my-first-post”命名的视图。默认视图解析器会向当前主题询问名为post-my-first-post的视图。如果它找不到它(很可能),它将寻找一个名为post的视图。如果当前的主题是为博客应用程序构建的,那么它很可能会拥有它,这就是将要使用的内容,否则引擎会询问其他插件并最终回退到“default”。

In the example of a commerce package, the controller could ask for category-boots. The theme could contain that view but if it doesn't the default implementation will try to find category and then revert to default.

在商业软件包的示例中,控制器可以请求“类别引导”。主题可以包含该视图,但如果不是,则默认实现将尝试查找category然后恢复为默认。

But we can also look at other patterns to resolve views.

但我们也可以查看其他模式来解析视图。

For example, here's the code for a plug-in that implements the page branch of a resolution tree:

例如,这是实现解析树的页面分支的插件的代码:

public string ResolveView(

    string viewName, Theme theme, ControllerContext context) {



    if (viewName.StartsWith("page-") {

        var pageName = viewName.Substring(5);

        if (theme.HasView(pageName)) {

            return pageName;

        } else if (theme.HasView("page") {

            return "page";

        }

    }

    return null;

}

One thing to note is that the application does not need in any case to have pre-determined knowledge of the content types. Those are just a matter of establishing a convention between a controller and its associated view resolution plug-in (if I there is one). This makes the theme engine very extensible while remaining simple for the end user and theme developer.

需要注意的一点是,应用程序在任何情况下都不需要具有预先确定的内容类型知识。这只是在控制器及其相关的视图解析插件之间建立约定的问题(如果有的话)。这使得主题引擎非常易于扩展,同时对最终用户和主题开发人员来说仍然很简单。

Localization

本土化

Localization of a theme can be done using the same conventions as in the application itself. Insertion of localized strings can be done using special helpers for resource strings (TBD).

可以使用与应用程序本身相同的约定来完成主题的本地化。可以使用资源字符串(TBD)的特殊帮助程序插入本地化字符串。

Declaring meta-data

声明元数据

Meta-data about themes can be specified through a simple YAML manifest (Theme.txt). This enables an expressive declaration of the meta-data:

可以通过简单的YAML清单(Theme.txt)指定有关主题的元数据。这可以表达元数据的表达:

Name: Pretty in pink

Author: Bertrand Le Roy

Description:

    This theme is full of butterflies, hearts

    and unicorns.

Version: 1.0

Tags: pink, butterfly, heart, unicorn, pony, rainbow

Url: http://orchardproject.net/themegallery/prettyinpink

Website: http://weblogs.asp.net/bleroy

These attributes are used in the admin tool to display rich details about the theme, and are also used to populate the description of themes in the online gallery.

这些属性在管理工具中用于显示有关主题的丰富详细信息,还用于填充在线图库中主题的描述。

It is possible to define custom meta-data attributes beyond those that are provided out of the box.

除了开箱即用的属性之外,还可以定义自定义元数据属性。

Localization of the meta-data is not supported at this point. Our default themes will eventually provide an example of a localized theme description.

此时不支持元数据的本地化。我们的默认主题最终将提供本地化主题描述的示例。

The license can be specified using a License meta-data property in the manifest.

可以使用清单中的许可证元数据属性指定许可证。

The Orchard framework defines the following meta-data attributes out of the box:

Orchard框架定义了以下元数据属性:

  • Name (the default value for this is the theme's type name, "uncameled")

  • 名称(默认值为主题的类型名称,“未命名”) *

  • Author (can take a comma-separated list)

  • 作者(可以采用以逗号分隔的列表) *

  • Description

  • 描述 *

  • Category

  • 类别 *

  • Tags (comma-separated list)

  • 标签(以逗号分隔的列表) *

  • Version

  • *

  • License

  • 执照 *

  • Url (the URL where the latest version of the theme can be found)

  • Url(可以找到最新主题版本的URL) *

  • Website

  • 网站 *

  • Settings (this is detailed in the next section)

  • 设置(这将在下一节中详述) *

Settings

设置

Some themes can expose settings so that simple customization of a theme can be done without opening a text editor. Typically, a theme can expose settings for a color palette or a logo.

某些主题可以公开设置,以便无需打开文本编辑器即可完成主题的简单自定义。通常,主题可以显示调色板或徽标的设置。

The way themes can expose settings in through the YAML meta-data manifest:

主题可以通过YAML元数据清单公开设置的方式:

Settings:

  - Palette:

    - Description: A dominant color for the theme.

    - Default: Pink

    - Editor: ColorEditor

  - Logo:

    - Description: The site's logo.

    - Default: images/logo.png

    - Editor: MediaPicker

The description for each setting can have a description and an editor hint. This tells the system how to build the admin UI to handle that setting by finding a partial view with the same name.

每个设置的描述可以有描述和编辑器提示。这告诉系统如何通过查找具有相同名称的部分视图来构建管理UI以处理该设置。

There is no type information associated with a setting because the intended audience for theme authoring shouldn't be required to understand such coding concepts. Instead, seen from the theme views, all theme settings are strings and can be injected easily.

没有与设置相关联的类型信息,因为不应要求主题创作的目标受众理解这样的编码概念。相反,从主题视图中可以看出,所有主题设置都是字符串,可以轻松注入。

It's the editor that is responsible for translating the value of a setting back and forth between the string representation and any internal representation it may need in order to provide a good editing experience. For example, a color setting would be represented in a #RRGGBB format that is immediately usable in HTML, but the editor would transform that representation into an instance of the Color type internally, and would surface color picker UI in the admin view to edit it. When it's done, it would persist the string representation back to the theme engine.

它是编辑器,负责在字符串表示和它可能需要的任何内部表示之间来回转换设置的值,以便提供良好的编辑体验。例如,颜色设置将以“#RRGGBB”格式表示,该格式可立即在HTML中使用,但编辑器会在内部将该表示转换为Color类型的实例,并在管理视图中将颜色选择器UI显示为编辑它。完成后,它会将字符串表示持久化回主题引擎。

The editor is also responsible for validation of setting values.

编辑器还负责验证设置值。

Theme settings can be injected into a view using the Html.Theme helper (see Theme Includes and Overrides).

可以使用Html.Theme帮助器将主题设置注入视图(请参阅[主题包含和覆盖](主题包括))。

There is a set of setting values per theme so that switching to a new theme switches to a new set of values, and going back to the original theme restores the corresponding values.

每个主题都有一组设置值,以便切换到新主题切换到一组新值,然后返回到原始主题将恢复相应的值。

Each setting can expose a default value in the meta-data.

每个设置都可以在元数据中公开默认值。

Stylesheet overrides

样式表覆盖

Stylesheet overrides are a special kind of setting that enables more arbitrary customization of a theme even when the user doesn't have direct access to the theme directory's files.

样式表覆盖是一种特殊的设置,即使用户无法直接访问主题目录的文件,也可以对主题进行更多任意的自定义。

Stylesheet overrides are a large string of CSS that can be set for each site. It is stored in the database like other theme settings but doesn't need to be declared explicitly by the theme's manifest. There is a set of overrides per theme so that switching to a new theme switches to a new set of overrides, and going back to the original theme restores the corresponding overrides.

样式表覆盖是一个可以为每个站点设置的大型CSS字符串。它像其他主题设置一样存储在数据库中,但不需要由主题的清单明确声明。每个主题都有一组覆盖,以便切换到新主题切换到一组新的覆盖,并返回到原始主题将恢复相应的覆盖。

The stylesheet overrides will be served by a special action. The views will include stylesheet overrides in the head of the page after the other stylesheets.

样式表覆盖将由特殊操作提供。视图将在其他样式表之后的页面顶部包含样式表覆盖。

The themes directory

主题目录

Each theme is found as a subdirectory under the Themes subdirectory of the root of the application. The name of the theme's directory should be the same as the name of the class in theme.cs if there is one.

每个主题都在应用程序根目录的Themes子目录下的子目录中找到。主题目录的名称应该与theme.cs中的类名相同(如果有的话)。

Stylesheet overrides

样式表覆盖

All themes should contain a call to a helper, Html.IncludeRegisteredHeaders(), right after the inclusion of the theme's stylesheet.aspx that can include database-bound CSS that is specific to the current tenant, as well as script and css that may be added dynamically by extensions such as widgets.

所有主题都应该包含对帮助程序的调用,Html.IncludeRegisteredHeaders(),在包含主题的stylesheet.aspx之后,可以包含特定于当前租户的数据库绑定的CSS,以及脚本和css,可以通过小部件等扩展动态添加。

Setup

建立

Themes can be uploaded (unzipped) through FTP into the themes directory of the application, and that is enough to set them up.

主题可以通过FTP上传(解压缩)到应用程序的主题目录中,这足以设置它们。

Alternatively, the zipped theme can be uploaded through the admin tool, which will unzip the file into the themes directory.

或者,可以通过管理工具上载压缩主题,管理工具将文件解压缩到主题目录中。

Finally, the theme can be chosen from the online catalog of themes that we will host on our servers and directly installed. Installing an online theme will directly transfer the zipped theme from our server to the application's server and then unzip it into the themes directory.

最后,主题可以从我们将在我们的服务器上托管并直接安装的主题的在线目录中选择。安装在线主题将直接将压缩主题从我们的服务器传输到应用程序的服务器,然后将其解压缩到themes目录中。

Note: The online catalog scenario won't be immediately implemented as it is dependent on the existence of this catalog, which is not yet planned.

注意:在线目录方案不会立即实施,因为它取决于此目录的存在,该目录尚未计划。

Themes can also be uninstalled. When the currently used theme is uninstalled, the site will revert to the "safe mode" built-in theme (no theme at all).

主题也可以卸载。当卸载当前使用的主题时,该站点将恢复为“安全模式”内置主题(根本没有主题)。

Themes and widgets

主题和小部件

The design of themes will be coupled to the widget infrastructure. The widgets specification can be found here:

主题设计将与小部件基础结构相结合。小部件规范可以在这里找到:

Widgets

[窗口小部件(窗口小部件)

Permissions

权限

Here, owner means the site owner.

在此,所有者表示网站所有者。

Permission | Anon. | Authentic. | Owner | Admin. | Author | Editor

许可|匿名。 |真实。 |所有者|管理员。 |作者|编辑

------------------------------------------ | ----- | ---------- | ----- | ------ | ------ | ------

  • | ----- | ---------- | ----- | ------ | ------ | ------

Change current theme | No | No | Yes | Yes | No | No

改变当前主题|没有|没有|是的|是的|没有|没有

Edit theme | No | No | Yes | Yes | No | No

编辑主题|没有|没有|是的|是的|没有|没有

Install and uninstall themes | No | No | Yes | Yes | No | No

安装和卸载主题|没有|没有|是的|是的|没有|没有

Additional permissions may apply to local themes when they get implemented.

实施后,其他权限可能适用于本地主题。