Giter Club home page Giter Club logo

freemarker-java-8's People

Contributors

dependabot[bot] avatar dertobsch avatar lazee avatar michaelkrog avatar mthmulders avatar tifoha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

freemarker-java-8's Issues

Syntax ${mylocaldatetime.format()} throws Exception for LocalDateTime

Hello, I created mcve example https://github.com/kortov/freemarker-java-8-mcve
You can run it as any SpringBoot app or with ./mvnw spring-boot:run then open localhost:8080 and it throws an exception

I'm just using an orinary LocalDateTime.now() and ${myDate.format()} in the template
My environment: Windows 7 SP 1, java 1.8.0_211, locale ru-RU
spring-boot 2.1.4.RELEASE
My date is printed in the logger as 2019-05-13T15:41:23.288

Maybe I'm using your library the wrong way, but readme says that I can use syntax ${mylocaldatetime.format()}

2019-05-13 15:48:07.713 ERROR 4436 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds] with root cause

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
	at java.time.LocalDate.get0(LocalDate.java:680) ~[na:1.8.0_181]
	at java.time.LocalDate.getLong(LocalDate.java:659) ~[na:1.8.0_181]
	at java.time.LocalDateTime.getLong(LocalDateTime.java:720) ~[na:1.8.0_181]
	at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298) ~[na:1.8.0_181]
	at java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.format(DateTimeFormatterBuilder.java:3335) ~[na:1.8.0_181]
	at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179) ~[na:1.8.0_181]
	at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179) ~[na:1.8.0_181]
	at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746) ~[na:1.8.0_181]
	at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720) ~[na:1.8.0_181]
	at java.time.LocalDateTime.format(LocalDateTime.java:1752) ~[na:1.8.0_181]
	at no.api.freemarker.java8.time.LocalDateTimeAdapter$LocalDateTimeFormatter.exec(LocalDateTimeAdapter.java:61) ~[freemarker-java8-1.1.5.jar:na]
	at freemarker.core.MethodCall._eval(MethodCall.java:65) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.core.Expression.eval(Expression.java:83) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.core.DollarVariable.accept(DollarVariable.java:63) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.core.Environment.visit(Environment.java:330) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.core.Environment.visit(Environment.java:336) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.core.Environment.process(Environment.java:309) ~[freemarker-2.3.28.jar:2.3.28]
	at freemarker.template.Template.process(Template.java:384) ~[freemarker-2.3.28.jar:2.3.28]
	at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:389) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:302) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:253) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:178) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1370) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1116) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) ~[tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.17.jar:9.0.17]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]

Jakob, did you receive my email?

Hi, sorry to use this communication channel a bit inappropriately. But I'm not 100% sure you got my recent email. Maybe it ended up in the SPAM folder. (This has been happening to me a fair bit recently with gmail.)

I wrote you an email to bring your attention to my recent efforts on the FreeMarker codebase. (Look at https://github.com/freemarker/freemarker3/wiki). We had some email correspondence almost 4 years ago and I had stated my intention to work on this and you seemed interested in it. But 4 years is a lot of water under the bridge. So, if you're not really very interested in FreeMarker at this point, I won't be offended at all. It would be nice to have some clarity on this one way or the other, I guess.

I hope all is going well for you.

ZoneOffsetAdapter is not used

ZoneOffset is subclass of ZoneId so it is means that ZoneOffsetAdapter is never used (ZoneIdAdapter is always used for objects of ZoneId and ZoneOffset type)
So the following two if statements should be in reverted order. (ZoneOffset first)

} else if (obj instanceof ZoneId) {
            return new ZoneIdAdapter((ZoneId) obj);
        } else if (obj instanceof ZoneOffset) {
            return new ZoneOffsetAdapter((ZoneOffset) obj);
}

LocalDateTimeAdapter uses incorrect pattern

LocalDateTimeAdapter uses ISO_ZONED_DATE_TIME and I guess it should be using ISO_LOCAL_DATE_TIME because I'm getting the following exception:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds

support instant type format

as reference mentioned, java instant type can be formatted as following:

https://github.com/lazee/freemarker-java-8#ballot_box_with_check-javatimeinstant

${myinstant.format()}

but It doesnt support format as coded like this:

    @Override
    public TemplateModel getForType(String s) throws TemplateModelException {
        if (METHOD_FORMAT.equals(s)) {
            return new InstantFormatter(getObject());
        }
        throw new TemplateModelException(METHOD_UNKNOWN_MSG + s);
    }


    public class InstantFormatter extends AbstractFormatter<Instant> implements TemplateMethodModelEx {

        public InstantFormatter(Instant obj) {
            super(obj);
        }


        @Override
        public Object exec(List list) throws TemplateModelException {
            return getObject().toString();  // format ignored
        }
    }

generated value is always getObject().toString() so formatting wont work

I've searched other types of type, and find out this:

    public class LocalDateFormatter extends AbstractFormatter<LocalDate> implements TemplateMethodModelEx {

        public LocalDateFormatter(LocalDate obj) {
            super(obj);
        }


        @Override
        public Object exec(List list) throws TemplateModelException {
            return getObject().format(createDateTimeFormatter(list, 0, DateTimeFormatter.ISO_LOCAL_DATE));
        }
    }

in your code-context, instant type also can be formatted.

public class FormattableInstantAdapter extends AbstractAdapter<Instant> implements AdapterTemplateModel,
    TemplateScalarModel, TemplateHashModel {

    public FormattableInstantAdapter(Instant obj, BeansWrapper wrapper) {
        super(obj, wrapper);
    }

    @Override
    public TemplateModel getForType(String s) throws TemplateModelException {
        if (METHOD_FORMAT.equals(s)) {
            return new InstantFormatter(getObject());
        }

        throw new TemplateModelException(METHOD_UNKNOWN_MSG + s);
    }

    public class InstantFormatter extends AbstractFormatter<Instant> implements TemplateMethodModelEx {

        public InstantFormatter(Instant obj) {
            super(obj);
        }

        @Override
        public Object exec(List list) throws TemplateModelException {
            return createDateTimeFormatter(list, 0, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                .withZone(ZoneId.systemDefault())  // instant use UTC as default
                .format(getObject());
        }
    }
}

Maybe instruction in the readme for SpringBoot is a bit outdated

Hello, I created mcve example https://github.com/kortov/freemarker-java-8-mcve
and in folder config you can check my config that I adapted a bit for a current Spring Boot.

In your readme you write
public class FreemarkerConfig extends FreeMarkerAutoConfiguration.FreeMarkerWebConfiguration {

When in Spring Boot 2.1.4.RELEASE I wrote
public class FreemarkerConfig extends FreeMarkerAutoConfiguration {

And I don't see any inner classes in FreeMarkerAutoConfiguration

plus I created a constructor, as Intellij Idea suggested it to me

public FreemarkerConfig(ApplicationContext applicationContext, FreeMarkerProperties properties) {
        super(applicationContext, properties);
    }

This issue just FYI and I don't see it as a big problem or maybe I'm used your config the wrong way, anyway I guess it could be interesting for you

Deploy to mavenCentral

Just to add the requested issue to see this getting deployed to maven central. Thanks for your contribution.

it doesn't work in FreeMarker VERSION_2_3_31

cfg = new Configuration(Configuration.VERSION_2_3_31);       
 cfg.setObjectWrapper(new Java8ObjectWrapper(Configuration.VERSION_2_3_31));

Instant arriveTime =  Instant.now();

 ${arriveTime.format('yyyy-MM-dd HH : mm : ss')}

the output is not printed as excepted: 2021-03-16T16:17:45Z

Add support for default format per time class

My use case is a small tool that generates XMLs.
All times should have the format HH:mm:ss
However, by default seconds are only output if non-zero.

So, currently I have to to explicitly include the format everyhwere, so instead of
${startDate} I have to write ${startDate.format("yyyy-MM-dd'T'HH:mm:ss")}
Since I have a lot of LocalDateTime and LocalTime instances, this makes the templates unnecessary long and error prone.

It would be very nice to configure the time adapters to use a specific default formatter!

Would you like to contribute this work to the FreeMarker core?

Hi, Jakob. I'm trying to reactivate the FreeMarker project (outside of ASF, long story which I'll tell you if you're interested) and get a FreeMarker 3 out. I am, by the way, to all intents and purposes, the original author.

I ran across this and was wondering if you wanted to just add this newer time/date functionality straight to the FreeMarker core. (And possibly some other things if they occur to you.)

Please feel free to write me at [email protected]

ZonedDateTime.format() should fallback to it's own zone when not specified

Calling zoned_date_object.format(fmt_string) without the second argument for zone_id will use the system's timezone - which really defeats the purpose of a ZonedDateTime.

In it's current form, to correctly format the zoned date time the ZoneId must also be passed as a string into the template - zoned_date_object.format(fmt_string, zoned_id_string).

If the user wanted to format the date object in the system timezone, they should use LocalDateTime.

I could probably submit a PR, but I first wanted to see if this line of thinking was valid.

Add support for localized date

I have a LocalDateTime I want to format as a date for specific locales.

Currently I have to set a specific pattern, but what I really want is to use the formatter from DateTimeFormatter.ofLocalizedDate(FormatStyle).

So in effect, a DateTimeFormatter created like the following would be great:

DateTimeFormatter.ofLocalizedDate(myFormatStyle).withLocale(myLocale);

wrong maven dependency

Please fix in documentation

<dependency>
    <groupId>no.api.freemarker</groupId>
    <artifactId>freemarker-java-8</artifactId>
    <version>1.1.2</version>
</dependency>

to

<dependency>
    <groupId>no.api.freemarker</groupId>
    <artifactId>freemarker-java8</artifactId>
    <version>1.1.2</version>
</dependency>

Documentation on Spring configuration

This might be useful for people using Spring in e.g. in the readme.md: -

import no.api.freemarker.java8.Java8ObjectWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class FreemarkerConfig extends FreeMarkerAutoConfiguration.FreeMarkerWebConfiguration {

    @Autowired
    private freemarker.template.Configuration configuration;

    @PostConstruct
    public void postConstruct() {
        configuration.setObjectWrapper(
                new Java8ObjectWrapper(freemarker.template.Configuration.getVersion())); // VERSION_2_3_26
    }

}

Install error

I get this trying to install locally:

$ mvn clean install
[INFO] Scanning for projects...
Downloading: https://repo.maven.apache.org/maven2/no/api/maven-projects/v3-super-pom/3.51/v3-super-pom-3.51.pom
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM for no.api.freemarker:freemarker-java8:1.0.1-SNAPSHOT: Could not find artifact no.api.maven-projects:v3-super-pom:pom:3.51 in central (https://repo.maven.apache.org/maven2) and 'parent.relativePath' points at wrong local POM @ line 21, column 13
 @
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]
[ERROR]   The project no.api.freemarker:freemarker-java8:1.0.1-SNAPSHOT (/Users/lovatog/Workspaces/github/amedia/freemarker-java-8/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for no.api.freemarker:freemarker-java8:1.0.1-SNAPSHOT: Could not find artifact no.api.maven-projects:v3-super-pom:pom:3.51 in central (https://repo.maven.apache.org/maven2) and 'parent.relativePath' points at wrong local POM @ line 21, column 13 -> [Help 2]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.